Merge branch 'for-2637/i2c/i2c-nomadik' into next-i2c
authorBen Dooks <ben-linux@fluff.org>
Thu, 28 Oct 2010 09:07:08 +0000 (10:07 +0100)
committerBen Dooks <ben-linux@fluff.org>
Thu, 28 Oct 2010 09:07:08 +0000 (10:07 +0100)
1409 files changed:
Documentation/ABI/obsolete/dv1394 [deleted file]
Documentation/ABI/removed/dv1394 [new file with mode: 0644]
Documentation/ABI/removed/raw1394 [new file with mode: 0644]
Documentation/ABI/removed/raw1394_legacy_isochronous [deleted file]
Documentation/ABI/removed/video1394 [new file with mode: 0644]
Documentation/ABI/testing/sysfs-devices-system-ibm-rtl [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
Documentation/filesystems/nfs/00-INDEX
Documentation/filesystems/nfs/idmapper.txt [new file with mode: 0644]
Documentation/filesystems/nfs/nfsroot.txt
Documentation/hwmon/ltc4261 [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/HD-Audio.txt
MAINTAINERS
arch/arm/Kconfig
arch/arm/configs/da8xx_omapl_defconfig
arch/arm/configs/n8x0_defconfig [deleted file]
arch/arm/configs/omap2plus_defconfig [moved from arch/arm/configs/omap3_defconfig with 90% similarity]
arch/arm/configs/omap_4430sdp_defconfig [deleted file]
arch/arm/configs/omap_generic_2420_defconfig [deleted file]
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/aemif.c [new file with mode: 0644]
arch/arm/mach-davinci/board-da830-evm.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-mityomapl138.c [new file with mode: 0644]
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-omapl138-hawk.c [new file with mode: 0644]
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/board-tnetv107x-evm.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/cpufreq.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/devices-tnetv107x.c
arch/arm/mach-davinci/devices.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/dma.c
arch/arm/mach-davinci/include/mach/aemif.h [new file with mode: 0644]
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/include/mach/dm365.h
arch/arm/mach-davinci/include/mach/dm644x.h
arch/arm/mach-davinci/include/mach/dm646x.h
arch/arm/mach-davinci/include/mach/nand.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-davinci/include/mach/tnetv107x.h
arch/arm/mach-davinci/include/mach/uncompress.h
arch/arm/mach-davinci/tnetv107x.c
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/simone.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/netspace_v2-setup.c
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-h2-mmc.c
arch/arm/mach-omap1/board-h3-mmc.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/board-sx1-mmc.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/include/mach/camera.h [new file with mode: 0644]
arch/arm/mach-omap1/pm_bus.c [new file with mode: 0644]
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-3630sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c [new file with mode: 0644]
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/board-flash.h [moved from arch/arm/mach-omap2/include/mach/board-flash.h with 88% similarity]
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-igep0030.c [new file with mode: 0644]
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c [new file with mode: 0644]
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-rx51-sdram.c
arch/arm/mach-omap2/board-rx51-video.c
arch/arm/mach-omap2/board-zoom-debugboard.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/board-zoom2.c
arch/arm/mach-omap2/board-zoom3.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm-regbits-44xx.h
arch/arm/mach-omap2/cm44xx.h
arch/arm/mach-omap2/cm4xxx.c
arch/arm/mach-omap2/common.c [new file with mode: 0644]
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/control.h [moved from arch/arm/plat-omap/include/plat/control.h with 92% similarity]
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc-smsc911x.c [new file with mode: 0644]
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/hsmmc.h
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/board-rx51.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/board-zoom.h
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/io.h [new file with mode: 0644]
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/mux.h
arch/arm/mach-omap2/mux2420.c
arch/arm/mach-omap2/mux2430.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm_bus.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains44xx.h
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm-regbits-34xx.h
arch/arm/mach-omap2/prm-regbits-44xx.h
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx_3xxx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-omap2/sram34xx.S
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-omap2/timer-gp.h [moved from arch/arm/plat-omap/include/plat/timer-gp.h with 86% similarity]
arch/arm/mach-omap2/usb-fs.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/devices.h
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-s3c64xx/dev-audio.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-harmony-pcie.c [new file with mode: 0644]
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/clock.h
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/cpu-tegra.c [new file with mode: 0644]
arch/arm/mach-tegra/dma.c [new file with mode: 0644]
arch/arm/mach-tegra/fuse.c [new file with mode: 0644]
arch/arm/mach-tegra/fuse.h [new file with mode: 0644]
arch/arm/mach-tegra/gpio.c
arch/arm/mach-tegra/include/mach/clk.h
arch/arm/mach-tegra/include/mach/dma.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/gpio.h
arch/arm/mach-tegra/include/mach/hardware.h
arch/arm/mach-tegra/include/mach/io.h
arch/arm/mach-tegra/include/mach/iomap.h
arch/arm/mach-tegra/include/mach/irqs.h
arch/arm/mach-tegra/include/mach/legacy_irq.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/pinmux-t2.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/pinmux.h
arch/arm/mach-tegra/io.c
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/legacy_irq.c [new file with mode: 0644]
arch/arm/mach-tegra/pcie.c [new file with mode: 0644]
arch/arm/mach-tegra/pinmux-t2-tables.c [new file with mode: 0644]
arch/arm/mach-tegra/pinmux.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-tegra/tegra2_dvfs.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra2_dvfs.h [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/include/mach/devices.h
arch/arm/mach-ux500/pins-db8500.h
arch/arm/plat-nomadik/include/plat/ske.h [new file with mode: 0644]
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/counter_32k.c [new file with mode: 0644]
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/fb.h [new file with mode: 0644]
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/dma.h
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/gpmc-smsc911x.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/i2c.h
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/mcbsp.h
arch/arm/plat-omap/include/plat/mmc.h
arch/arm/plat-omap/include/plat/omap-serial.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap24xx.h
arch/arm/plat-omap/include/plat/omap4-keypad.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/powerdomain.h
arch/arm/plat-omap/include/plat/prcm.h
arch/arm/plat-omap/include/plat/sdrc.h
arch/arm/plat-omap/include/plat/sram.h
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/include/plat/usb.h
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/sram.h [new file with mode: 0644]
arch/arm/plat-s3c24xx/devs.c
arch/arm/plat-samsung/include/plat/devs.h
arch/blackfin/Kconfig.debug
arch/blackfin/configs/BF518F-EZBRD_defconfig
arch/blackfin/configs/BF526-EZBRD_defconfig
arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
arch/blackfin/configs/BF527-EZKIT-V2_defconfig
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF527-TLL6527M_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF538-EZKIT_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-ACVILON_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/BlackStamp_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/configs/CM-BF533_defconfig
arch/blackfin/configs/CM-BF537E_defconfig
arch/blackfin/configs/CM-BF537U_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/blackfin/configs/H8606_defconfig
arch/blackfin/configs/IP0X_defconfig
arch/blackfin/configs/PNAV-10_defconfig
arch/blackfin/configs/SRV1_defconfig
arch/blackfin/configs/TCM-BF518_defconfig
arch/blackfin/configs/TCM-BF537_defconfig
arch/blackfin/include/asm/bfin5xx_spi.h
arch/blackfin/include/asm/bfin_ppi.h
arch/blackfin/include/asm/bfin_twi.h [new file with mode: 0644]
arch/blackfin/include/asm/cdef_LPBlackfin.h
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/boards/tcm-bf518.c
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/boards/tll6527m.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-common/Makefile
arch/blackfin/mach-common/irqpanic.c [deleted file]
arch/m68k/include/asm/cacheflush_no.h
arch/m68k/include/asm/coldfire.h
arch/m68k/include/asm/gpio.h
arch/m68k/include/asm/m548xgpt.h [new file with mode: 0644]
arch/m68k/include/asm/m548xsim.h [new file with mode: 0644]
arch/m68k/include/asm/mcfcache.h
arch/m68k/include/asm/mcfsim.h
arch/m68k/include/asm/mcfslt.h [new file with mode: 0644]
arch/m68k/include/asm/mcfuart.h
arch/m68k/kernel/asm-offsets.c
arch/m68knommu/Kconfig
arch/m68knommu/Makefile
arch/m68knommu/kernel/.gitignore [new file with mode: 0644]
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/ptrace.c
arch/m68knommu/kernel/setup.c
arch/m68knommu/kernel/time.c
arch/m68knommu/kernel/traps.c
arch/m68knommu/platform/5206/Makefile
arch/m68knommu/platform/5206e/Makefile
arch/m68knommu/platform/520x/Makefile
arch/m68knommu/platform/523x/Makefile
arch/m68knommu/platform/5249/Makefile
arch/m68knommu/platform/5272/Makefile
arch/m68knommu/platform/5272/config.c
arch/m68knommu/platform/5272/intc.c
arch/m68knommu/platform/527x/Makefile
arch/m68knommu/platform/528x/Makefile
arch/m68knommu/platform/5307/Makefile
arch/m68knommu/platform/532x/Makefile
arch/m68knommu/platform/5407/Makefile
arch/m68knommu/platform/548x/Makefile [new file with mode: 0644]
arch/m68knommu/platform/548x/config.c [new file with mode: 0644]
arch/m68knommu/platform/68328/entry.S
arch/m68knommu/platform/68328/head-de2.S
arch/m68knommu/platform/68328/head-ram.S
arch/m68knommu/platform/68328/ints.c
arch/m68knommu/platform/68360/entry.S
arch/m68knommu/platform/68360/ints.c
arch/m68knommu/platform/68VZ328/config.c
arch/m68knommu/platform/coldfire/Makefile
arch/m68knommu/platform/coldfire/entry.S
arch/m68knommu/platform/coldfire/intc-2.c
arch/m68knommu/platform/coldfire/intc-simr.c
arch/m68knommu/platform/coldfire/intc.c
arch/m68knommu/platform/coldfire/sltimers.c [new file with mode: 0644]
arch/microblaze/Kconfig
arch/microblaze/Kconfig.debug
arch/microblaze/Makefile
arch/microblaze/include/asm/byteorder.h
arch/microblaze/include/asm/checksum.h
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/elf.h
arch/microblaze/include/asm/gpio.h
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/page.h
arch/microblaze/include/asm/pci.h
arch/microblaze/include/asm/pgalloc.h
arch/microblaze/include/asm/pgtable.h
arch/microblaze/include/asm/prom.h
arch/microblaze/include/asm/pvr.h
arch/microblaze/include/asm/seccomp.h [new file with mode: 0644]
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/thread_info.h
arch/microblaze/include/asm/unaligned.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/cpu/mb.c
arch/microblaze/kernel/cpu/pvr.c
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/exceptions.c
arch/microblaze/kernel/heartbeat.c
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/kgdb.c
arch/microblaze/kernel/microblaze_ksyms.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/syscall_table.S
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/vmlinux.lds.S
arch/microblaze/lib/Makefile
arch/microblaze/lib/ashldi3.c [new file with mode: 0644]
arch/microblaze/lib/ashrdi3.c [new file with mode: 0644]
arch/microblaze/lib/divsi3.S [new file with mode: 0644]
arch/microblaze/lib/libgcc.h [new file with mode: 0644]
arch/microblaze/lib/lshrdi3.c [new file with mode: 0644]
arch/microblaze/lib/memcpy.c
arch/microblaze/lib/memmove.c
arch/microblaze/lib/memset.c
arch/microblaze/lib/modsi3.S [new file with mode: 0644]
arch/microblaze/lib/muldi3.S [new file with mode: 0644]
arch/microblaze/lib/mulsi3.S [new file with mode: 0644]
arch/microblaze/lib/udivsi3.S [new file with mode: 0644]
arch/microblaze/lib/umodsi3.S [new file with mode: 0644]
arch/microblaze/pci/pci-common.c
arch/microblaze/platform/generic/system.dts
arch/microblaze/platform/platform.c
arch/mips/Kconfig
arch/mips/alchemy/devboards/db1200/platform.c
arch/mips/include/asm/irq.h
arch/mips/include/asm/prom.h [new file with mode: 0644]
arch/mips/kernel/Makefile
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/prom.c [new file with mode: 0644]
arch/mips/kernel/setup.c
arch/mn10300/kernel/vmlinux.lds.S
arch/powerpc/boot/dts/mpc8610_hpcd.dts
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/include/asm/fsl_guts.h [moved from arch/powerpc/include/asm/immap_86xx.h with 66% similarity]
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/prom.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/s390/Kbuild [new file with mode: 0644]
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/cpu.h
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/page.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/s390_ext.h
arch/s390/include/asm/scatterlist.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/syscall.h
arch/s390/include/asm/sysinfo.h
arch/s390/include/asm/system.h
arch/s390/include/asm/tlb.h
arch/s390/include/asm/topology.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/process.c
arch/s390/kernel/processor.c
arch/s390/kernel/s390_ext.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/sysinfo.c
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vtime.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/mm/Makefile
arch/s390/mm/cmm.c
arch/s390/mm/fault.c
arch/s390/mm/gup.c [new file with mode: 0644]
arch/s390/mm/hugetlbpage.c
arch/s390/mm/init.c
arch/s390/mm/pgtable.c
arch/sh/Kconfig
arch/sh/boards/Kconfig
arch/sh/boards/Makefile
arch/sh/boards/board-sh2007.c [new file with mode: 0644]
arch/sh/boards/board-sh7757lcr.c [new file with mode: 0644]
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-sdk7786/Makefile
arch/sh/boards/mach-sdk7786/gpio.c [new file with mode: 0644]
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/boards/mach-sdk7786/sram.c [new file with mode: 0644]
arch/sh/boards/mach-x3proto/Makefile
arch/sh/boards/mach-x3proto/gpio.c [new file with mode: 0644]
arch/sh/boards/mach-x3proto/ilsel.c
arch/sh/boards/mach-x3proto/setup.c
arch/sh/boot/compressed/head_32.S
arch/sh/cchips/hd6446x/Makefile
arch/sh/configs/ap325rxa_defconfig
arch/sh/configs/cayman_defconfig
arch/sh/configs/dreamcast_defconfig
arch/sh/configs/ecovec24-romimage_defconfig
arch/sh/configs/edosk7760_defconfig
arch/sh/configs/espt_defconfig
arch/sh/configs/hp6xx_defconfig
arch/sh/configs/kfr2r09-romimage_defconfig
arch/sh/configs/kfr2r09_defconfig
arch/sh/configs/landisk_defconfig
arch/sh/configs/lboxre2_defconfig
arch/sh/configs/magicpanelr2_defconfig
arch/sh/configs/microdev_defconfig
arch/sh/configs/migor_defconfig
arch/sh/configs/polaris_defconfig
arch/sh/configs/r7780mp_defconfig
arch/sh/configs/r7785rp_defconfig
arch/sh/configs/rts7751r2d1_defconfig
arch/sh/configs/rts7751r2dplus_defconfig
arch/sh/configs/sdk7780_defconfig
arch/sh/configs/se7343_defconfig
arch/sh/configs/se7712_defconfig
arch/sh/configs/se7721_defconfig
arch/sh/configs/se7722_defconfig
arch/sh/configs/se7724_defconfig
arch/sh/configs/se7750_defconfig
arch/sh/configs/se7751_defconfig
arch/sh/configs/se7780_defconfig
arch/sh/configs/sh03_defconfig
arch/sh/configs/sh2007_defconfig [new file with mode: 0644]
arch/sh/configs/sh7710voipgw_defconfig
arch/sh/configs/sh7757lcr_defconfig [new file with mode: 0644]
arch/sh/configs/sh7763rdp_defconfig
arch/sh/configs/sh7785lcr_defconfig
arch/sh/configs/shx3_defconfig
arch/sh/configs/snapgear_defconfig
arch/sh/configs/systemh_defconfig
arch/sh/configs/titan_defconfig
arch/sh/configs/ul2_defconfig
arch/sh/drivers/dma/dma-api.c
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-sdk7786.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-sh4.c
arch/sh/drivers/pci/ops-sh7786.c
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/pci/pci-sh7780.h
arch/sh/drivers/pci/pci.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/drivers/pci/pcie-sh7786.h
arch/sh/include/asm/Kbuild
arch/sh/include/asm/elf.h
arch/sh/include/asm/fixmap.h
arch/sh/include/asm/gpio.h
arch/sh/include/asm/irq.h
arch/sh/include/asm/kprobes.h
arch/sh/include/asm/pci.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/ptrace_32.h [new file with mode: 0644]
arch/sh/include/asm/ptrace_64.h [new file with mode: 0644]
arch/sh/include/asm/sizes.h
arch/sh/include/asm/sram.h [new file with mode: 0644]
arch/sh/include/asm/system.h
arch/sh/include/asm/system_32.h
arch/sh/include/asm/tlbflush.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/include/cpu-sh3/cpu/mmu_context.h
arch/sh/include/cpu-sh4/cpu/freq.h
arch/sh/include/cpu-sh4/cpu/sh7757.h
arch/sh/include/cpu-sh4/cpu/shx3.h [new file with mode: 0644]
arch/sh/include/mach-common/mach/sh2007.h [new file with mode: 0644]
arch/sh/include/mach-sdk7786/mach/fpga.h
arch/sh/include/mach-x3proto/mach/hardware.h [new file with mode: 0644]
arch/sh/include/mach-x3proto/mach/ilsel.h [moved from arch/sh/include/asm/ilsel.h with 100% similarity]
arch/sh/kernel/Makefile
arch/sh/kernel/clkdev.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/sh/kernel/cpu/sh4a/intc-shx3.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/perf_event.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
arch/sh/kernel/cpu/sh4a/pinmux-shx3.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/cpu/sh4a/setup-shx3.c
arch/sh/kernel/head_32.S
arch/sh/kernel/io_trapped.c
arch/sh/kernel/irq.c
arch/sh/kernel/kdebugfs.c [new file with mode: 0644]
arch/sh/kernel/kprobes.c
arch/sh/kernel/ptrace.c [new file with mode: 0644]
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/reboot.c
arch/sh/kernel/setup.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/lib/Makefile
arch/sh/math-emu/math.c
arch/sh/mm/Kconfig
arch/sh/mm/Makefile
arch/sh/mm/asids-debugfs.c
arch/sh/mm/cache-debugfs.c
arch/sh/mm/consistent.c
arch/sh/mm/init.c
arch/sh/mm/nommu.c
arch/sh/mm/pmb.c
arch/sh/mm/sram.c [new file with mode: 0644]
arch/sh/mm/tlb-debugfs.c
arch/sh/mm/tlbflush_32.c
arch/sh/mm/tlbflush_64.c
arch/sh/tools/mach-types
arch/sparc/Kconfig
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/floppy_32.h
arch/sparc/include/asm/openprom.h
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/include/asm/prom.h
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/btext.c
arch/sparc/kernel/devices.c
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/prom.h
arch/sparc/kernel/prom_common.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/starfire.c
arch/sparc/kernel/tadpole.c
arch/sparc/mm/init_64.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc/prom/init_32.c
arch/sparc/prom/init_64.c
arch/sparc/prom/memory.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/ranges.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/x86/include/asm/olpc.h
arch/x86/kernel/acpi/sleep.c
block/blk-core.c
block/blk-merge.c
block/blk.h
block/genhd.c
drivers/Makefile
drivers/base/platform.c
drivers/block/xsysace.c
drivers/char/hvc_iucv.c
drivers/char/keyboard.c
drivers/char/sysrq.c
drivers/clocksource/sh_cmt.c
drivers/firewire/Kconfig
drivers/firewire/Makefile
drivers/firewire/init_ohci1394_dma.c [moved from drivers/ieee1394/init_ohci1394_dma.c with 84% similarity]
drivers/gpio/xilinx_gpio.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/coretemp.c
drivers/hwmon/gpio-fan.c [new file with mode: 0644]
drivers/hwmon/hp_accel.c
drivers/hwmon/lis3lv02d.c
drivers/hwmon/lis3lv02d.h
drivers/hwmon/lis3lv02d_i2c.c
drivers/hwmon/lis3lv02d_spi.c
drivers/hwmon/ltc4261.c [new file with mode: 0644]
drivers/hwmon/pkgtemp.c
drivers/hwmon/via-cputemp.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-intel-mid.c [new file with mode: 0644]
drivers/i2c/busses/i2c-sh7760.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/ieee1394/Kconfig [deleted file]
drivers/ieee1394/Makefile [deleted file]
drivers/ieee1394/config_roms.c [deleted file]
drivers/ieee1394/config_roms.h [deleted file]
drivers/ieee1394/csr.c [deleted file]
drivers/ieee1394/csr.h [deleted file]
drivers/ieee1394/csr1212.c [deleted file]
drivers/ieee1394/csr1212.h [deleted file]
drivers/ieee1394/dma.c [deleted file]
drivers/ieee1394/dma.h [deleted file]
drivers/ieee1394/dv1394-private.h [deleted file]
drivers/ieee1394/dv1394.c [deleted file]
drivers/ieee1394/dv1394.h [deleted file]
drivers/ieee1394/eth1394.c [deleted file]
drivers/ieee1394/eth1394.h [deleted file]
drivers/ieee1394/highlevel.c [deleted file]
drivers/ieee1394/highlevel.h [deleted file]
drivers/ieee1394/hosts.c [deleted file]
drivers/ieee1394/hosts.h [deleted file]
drivers/ieee1394/ieee1394-ioctl.h [deleted file]
drivers/ieee1394/ieee1394.h [deleted file]
drivers/ieee1394/ieee1394_core.c [deleted file]
drivers/ieee1394/ieee1394_core.h [deleted file]
drivers/ieee1394/ieee1394_hotplug.h [deleted file]
drivers/ieee1394/ieee1394_transactions.c [deleted file]
drivers/ieee1394/ieee1394_transactions.h [deleted file]
drivers/ieee1394/ieee1394_types.h [deleted file]
drivers/ieee1394/iso.c [deleted file]
drivers/ieee1394/iso.h [deleted file]
drivers/ieee1394/nodemgr.c [deleted file]
drivers/ieee1394/nodemgr.h [deleted file]
drivers/ieee1394/ohci1394.c [deleted file]
drivers/ieee1394/ohci1394.h [deleted file]
drivers/ieee1394/pcilynx.c [deleted file]
drivers/ieee1394/pcilynx.h [deleted file]
drivers/ieee1394/raw1394-private.h [deleted file]
drivers/ieee1394/raw1394.c [deleted file]
drivers/ieee1394/raw1394.h [deleted file]
drivers/ieee1394/sbp2.c [deleted file]
drivers/ieee1394/sbp2.h [deleted file]
drivers/ieee1394/video1394.c [deleted file]
drivers/ieee1394/video1394.h [deleted file]
drivers/input/evdev.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/fm801-gp.c
drivers/input/input.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/nomadik-ske-keypad.c [new file with mode: 0644]
drivers/input/keyboard/omap4-keypad.c [new file with mode: 0644]
drivers/input/keyboard/tnetv107x-keypad.c [new file with mode: 0644]
drivers/input/keyboard/twl4030_keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ab8500-ponkey.c [new file with mode: 0644]
drivers/input/misc/ati_remote2.c
drivers/input/misc/powermate.c
drivers/input/misc/twl4030-vibra.c
drivers/input/mouse/elantech.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/mouse/trackpoint.c
drivers/input/mousedev.c
drivers/input/serio/Kconfig
drivers/input/serio/Makefile
drivers/input/serio/i8042.c
drivers/input/serio/ps2mult.c [new file with mode: 0644]
drivers/input/serio/serio.c
drivers/input/sparse-keymap.c
drivers/input/tablet/Kconfig
drivers/input/tablet/Makefile
drivers/input/tablet/hanwang.c [new file with mode: 0644]
drivers/input/tablet/wacom.h
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/bu21013_ts.c [new file with mode: 0644]
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/hp680_ts_input.c
drivers/input/touchscreen/intel-mid-touch.c [new file with mode: 0644]
drivers/input/touchscreen/lpc32xx_ts.c [new file with mode: 0644]
drivers/input/touchscreen/s3c2410_ts.c
drivers/input/touchscreen/stmpe-ts.c
drivers/input/touchscreen/tnetv107x-ts.c [new file with mode: 0644]
drivers/input/touchscreen/tps6507x-ts.c
drivers/input/touchscreen/tsc2007.c
drivers/input/touchscreen/wacom_w8001.c
drivers/input/touchscreen/wm97xx-core.c
drivers/media/IR/ir-keytable.c
drivers/mfd/ab8500-core.c
drivers/mfd/sh_mobile_sdhi.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-codec.c
drivers/mmc/host/omap_hsmmc.c
drivers/mtd/devices/m25p80.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/ofpart.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/bfin_mac.c
drivers/net/bfin_mac.h
drivers/net/davinci_cpdma.c [new file with mode: 0644]
drivers/net/davinci_cpdma.h [new file with mode: 0644]
drivers/net/davinci_emac.c
drivers/net/davinci_mdio.c [new file with mode: 0644]
drivers/net/xilinx_emaclite.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/address.c
drivers/of/base.c
drivers/of/device.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_i2c.c
drivers/of/pdt.c [new file with mode: 0644]
drivers/of/platform.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hdaps.c [moved from drivers/hwmon/hdaps.c with 99% similarity]
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ibm_rtl.c [new file with mode: 0644]
drivers/platform/x86/ideapad-laptop.c [moved from drivers/platform/x86/ideapad_acpi.c with 53% similarity]
drivers/platform/x86/intel_pmic_gpio.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/platform/x86/xo1-rfkill.c [new file with mode: 0644]
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_diag.h
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/sclp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/chsc_sch.c
drivers/s390/cio/css.c
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/io_sch.h
drivers/s390/crypto/ap_bus.c
drivers/s390/kvm/kvm_virtio.c
drivers/sbus/char/jsflash.c
drivers/serial/68328serial.h
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/of_serial.c
drivers/serial/omap-serial.c [new file with mode: 0644]
drivers/serial/sh-sci.h
drivers/sh/Kconfig
drivers/sh/Makefile
drivers/sh/clk/Makefile [new file with mode: 0644]
drivers/sh/clk/core.c [moved from drivers/sh/clk.c with 74% similarity]
drivers/sh/clk/cpg.c [moved from drivers/sh/clk-cpg.c with 96% similarity]
drivers/sh/intc.c [deleted file]
drivers/sh/intc/Kconfig [new file with mode: 0644]
drivers/sh/intc/Makefile [new file with mode: 0644]
drivers/sh/intc/access.c [new file with mode: 0644]
drivers/sh/intc/balancing.c [new file with mode: 0644]
drivers/sh/intc/chip.c [new file with mode: 0644]
drivers/sh/intc/core.c [new file with mode: 0644]
drivers/sh/intc/dynamic.c [new file with mode: 0644]
drivers/sh/intc/handle.c [new file with mode: 0644]
drivers/sh/intc/internals.h [new file with mode: 0644]
drivers/sh/intc/userimask.c [new file with mode: 0644]
drivers/sh/intc/virq-debugfs.c [new file with mode: 0644]
drivers/sh/intc/virq.c [new file with mode: 0644]
drivers/sh/pfc.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi_tegra.c [new file with mode: 0644]
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/mrst-touchscreen/Kconfig [deleted file]
drivers/staging/mrst-touchscreen/Makefile [deleted file]
drivers/staging/mrst-touchscreen/TODO [deleted file]
drivers/staging/mrst-touchscreen/intel-mid-touch.c [deleted file]
drivers/staging/xgifb/TODO
drivers/usb/gadget/omap_udc.c
drivers/usb/host/r8a66597-hcd.c
drivers/uwb/Kconfig
drivers/uwb/Makefile
drivers/uwb/i1480/Makefile
drivers/uwb/i1480/i1480-wlp.h [deleted file]
drivers/uwb/i1480/i1480u-wlp/Makefile [deleted file]
drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h [deleted file]
drivers/uwb/i1480/i1480u-wlp/lc.c [deleted file]
drivers/uwb/i1480/i1480u-wlp/netdev.c [deleted file]
drivers/uwb/i1480/i1480u-wlp/rx.c [deleted file]
drivers/uwb/i1480/i1480u-wlp/sysfs.c [deleted file]
drivers/uwb/i1480/i1480u-wlp/tx.c [deleted file]
drivers/uwb/wlp/Makefile [deleted file]
drivers/uwb/wlp/driver.c [deleted file]
drivers/uwb/wlp/eda.c [deleted file]
drivers/uwb/wlp/messages.c [deleted file]
drivers/uwb/wlp/sysfs.c [deleted file]
drivers/uwb/wlp/txrx.c [deleted file]
drivers/uwb/wlp/wlp-internal.h [deleted file]
drivers/uwb/wlp/wlp-lc.c [deleted file]
drivers/uwb/wlp/wss-lc.c [deleted file]
drivers/video/Kconfig
drivers/video/aty/atyfb_base.c
drivers/video/sh_mobile_hdmi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/xilinxfb.c
drivers/watchdog/omap_wdt.c
fs/coda/cache.c
fs/coda/cnode.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/coda/psdev.c
fs/coda/symlink.c
fs/coda/upcall.c
fs/exofs/dir.c
fs/exofs/inode.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/nfs/Kconfig
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/nfsroot.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/sysctl.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/partitions/check.c
include/asm-generic/pgtable.h
include/linux/bfin_mac.h [new file with mode: 0644]
include/linux/blkdev.h
include/linux/coda_fs_i.h
include/linux/coda_linux.h
include/linux/coda_psdev.h
include/linux/davinci_emac.h
include/linux/elevator.h
include/linux/gameport.h
include/linux/genhd.h
include/linux/gpio-fan.h [new file with mode: 0644]
include/linux/i2c/twl.h
include/linux/input.h
include/linux/input/bu21013.h [new file with mode: 0644]
include/linux/lis3lv02d.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_idmap.h
include/linux/nfs_mount.h
include/linux/nfs_xdr.h
include/linux/of_device.h
include/linux/of_fdt.h
include/linux/of_irq.h
include/linux/of_pdt.h [new file with mode: 0644]
include/linux/page-flags.h
include/linux/pci_ids.h
include/linux/serial_core.h
include/linux/serio.h
include/linux/sh_clk.h
include/linux/sh_intc.h
include/linux/sh_pfc.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/xdr.h
include/linux/wlp.h [deleted file]
include/media/rc-map.h
include/sound/core.h
include/sound/emu10k1.h
include/sound/jack.h
include/sound/max98088.h [new file with mode: 0644]
include/sound/pcm.h
include/sound/sh_fsi.h
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc-of-simple.h [deleted file]
include/sound/soc.h
include/sound/tlv.h
include/sound/tlv320aic3x.h
include/sound/wm8962.h [new file with mode: 0644]
include/video/sh_mobile_hdmi.h
init/do_mounts.c
kernel/workqueue.c
mm/rmap.c
net/iucv/iucv.c
net/sunrpc/auth.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/xdr.c
sound/core/init.c
sound/core/oss/mixer_oss.c
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/drivers/Kconfig
sound/drivers/Makefile
sound/drivers/aloop.c [new file with mode: 0644]
sound/drivers/virmidi.c
sound/i2c/other/ak4xxx-adda.c
sound/isa/Kconfig
sound/isa/Makefile
sound/isa/ad1816a/ad1816a.c
sound/isa/azt2320.c
sound/isa/galaxy/Makefile [new file with mode: 0644]
sound/isa/galaxy/azt1605.c [new file with mode: 0644]
sound/isa/galaxy/azt2316.c [new file with mode: 0644]
sound/isa/galaxy/galaxy.c [new file with mode: 0644]
sound/isa/gus/gusmax.c
sound/isa/sb/sb8.c
sound/isa/sgalaxy.c [deleted file]
sound/oss/Kconfig
sound/oss/Makefile
sound/oss/au1550_ac97.c
sound/oss/dmasound/dmasound_core.c
sound/oss/msnd_pinnacle.c
sound/oss/sh_dac_audio.c [deleted file]
sound/oss/soundcard.c
sound/oss/swarm_cs4297a.c
sound/oss/vwsnd.c
sound/pci/Kconfig
sound/pci/au88x0/au88x0_mixer.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/emu10k1/emumpu401.c
sound/pci/hda/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_atihdmi.c [deleted file]
sound/pci/hda/patch_ca0110.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_intelhdmi.c [deleted file]
sound/pci/hda/patch_nvhdmi.c [deleted file]
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/delta.h
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_mixer.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/oxygen_regs.h
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/xonar_cs43xx.c
sound/pci/oxygen/xonar_pcm179x.c
sound/pci/oxygen/xonar_wm87x6.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/ppc/tumbler.c
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel-pcm.h
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/atmel_ssc_dai.h
sound/soc/atmel/playpaq_wm8510.c
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/atmel/snd-soc-afeb9260.c
sound/soc/au1x/db1200.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/au1x/psc.h
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-ac97-pcm.h
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ac97.h
sound/soc/blackfin/bf5xx-ad1836.c
sound/soc/blackfin/bf5xx-ad193x.c
sound/soc/blackfin/bf5xx-ad1980.c
sound/soc/blackfin/bf5xx-ad73311.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bf5xx-i2s-pcm.h
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-i2s.h [deleted file]
sound/soc/blackfin/bf5xx-ssm2602.c
sound/soc/blackfin/bf5xx-tdm-pcm.c
sound/soc/blackfin/bf5xx-tdm-pcm.h
sound/soc/blackfin/bf5xx-tdm.c
sound/soc/blackfin/bf5xx-tdm.h
sound/soc/codecs/88pm860x-codec.c [new file with mode: 0644]
sound/soc/codecs/88pm860x-codec.h [new file with mode: 0644]
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ac97.h [deleted file]
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad1836.h
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad193x.h
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad1980.h
sound/soc/codecs/ad73311.c
sound/soc/codecs/ad73311.h
sound/soc/codecs/ads117x.c
sound/soc/codecs/ads117x.h
sound/soc/codecs/ak4104.c
sound/soc/codecs/ak4104.h [deleted file]
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4535.h
sound/soc/codecs/ak4642.c
sound/soc/codecs/ak4642.h [deleted file]
sound/soc/codecs/ak4671.c
sound/soc/codecs/ak4671.h
sound/soc/codecs/cq93vc.c
sound/soc/codecs/cq93vc.h [deleted file]
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4270.h [deleted file]
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l51.h
sound/soc/codecs/cx20442.c
sound/soc/codecs/cx20442.h
sound/soc/codecs/da7210.c
sound/soc/codecs/da7210.h [deleted file]
sound/soc/codecs/jz4740.c
sound/soc/codecs/jz4740.h [deleted file]
sound/soc/codecs/max98088.c [new file with mode: 0644]
sound/soc/codecs/max98088.h [new file with mode: 0644]
sound/soc/codecs/pcm3008.c
sound/soc/codecs/pcm3008.h
sound/soc/codecs/spdif_transciever.c
sound/soc/codecs/spdif_transciever.h [deleted file]
sound/soc/codecs/ssm2602.c
sound/soc/codecs/ssm2602.h
sound/soc/codecs/stac9766.c
sound/soc/codecs/stac9766.h
sound/soc/codecs/tlv320aic23.c
sound/soc/codecs/tlv320aic23.h
sound/soc/codecs/tlv320aic26.c
sound/soc/codecs/tlv320aic26.h
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.h
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tlv320dac33.h
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl4030.h [deleted file]
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.h
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda134x.h
sound/soc/codecs/uda1380.c
sound/soc/codecs/uda1380.h
sound/soc/codecs/wl1273.c [new file with mode: 0644]
sound/soc/codecs/wl1273.h [new file with mode: 0644]
sound/soc/codecs/wm2000.h
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8350.h
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8400.h
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8510.h
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8523.h
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8580.h
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8711.h
sound/soc/codecs/wm8727.c
sound/soc/codecs/wm8727.h [deleted file]
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8728.h
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8731.h
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8741.h
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8750.h
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8753.h
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8776.h
sound/soc/codecs/wm8804.c [new file with mode: 0644]
sound/soc/codecs/wm8804.h [new file with mode: 0644]
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8900.h
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8903.h
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8904.h
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8940.h
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8955.h
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8960.h
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8961.h
sound/soc/codecs/wm8962.c [new file with mode: 0644]
sound/soc/codecs/wm8962.h [new file with mode: 0644]
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8971.h
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8974.h
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8978.h
sound/soc/codecs/wm8985.c [new file with mode: 0644]
sound/soc/codecs/wm8985.h [new file with mode: 0644]
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8988.h
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8990.h
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8993.h
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9081.h
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm9090.h
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9705.h
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9712.h
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm9713.h
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-i2s.h
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/davinci/davinci-sffsdr.c
sound/soc/davinci/davinci-vcif.c
sound/soc/davinci/davinci-vcif.h [deleted file]
sound/soc/ep93xx/Kconfig
sound/soc/ep93xx/Makefile
sound/soc/ep93xx/ep93xx-ac97.c [new file with mode: 0644]
sound/soc/ep93xx/ep93xx-i2s.c
sound/soc/ep93xx/ep93xx-i2s.h [deleted file]
sound/soc/ep93xx/ep93xx-pcm.c
sound/soc/ep93xx/ep93xx-pcm.h
sound/soc/ep93xx/simone.c [new file with mode: 0644]
sound/soc/ep93xx/snappercl15.c
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/efika-audio-fabric.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_dma.h
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.h
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_dma.h
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/fsl/mpc5200_psc_ac97.h
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/p1022_ds.c [new file with mode: 0644]
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/fsl/soc-of-simple.c [deleted file]
sound/soc/imx/Kconfig
sound/soc/imx/Makefile
sound/soc/imx/eukrea-tlv320.c
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-pcm-fiq.c
sound/soc/imx/imx-ssi.c
sound/soc/imx/imx-ssi.h
sound/soc/imx/phycore-ac97.c
sound/soc/imx/wm1133-ev1.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-i2s.h
sound/soc/jz4740/jz4740-pcm.c
sound/soc/jz4740/jz4740-pcm.h
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-dma.h [deleted file]
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/kirkwood/kirkwood-i2s.h [deleted file]
sound/soc/kirkwood/kirkwood-openrd.c
sound/soc/nuc900/nuc900-ac97.c
sound/soc/nuc900/nuc900-audio.c
sound/soc/nuc900/nuc900-audio.h
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/am3517evm.c
sound/soc/omap/ams-delta.c
sound/soc/omap/igep0020.c
sound/soc/omap/mcpdm.c
sound/soc/omap/mcpdm.h
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-mcpdm.h [deleted file]
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-pcm.h
sound/soc/omap/omap2evm.c
sound/soc/omap/omap3beagle.c
sound/soc/omap/omap3evm.c
sound/soc/omap/omap3pandora.c
sound/soc/omap/osk5912.c
sound/soc/omap/overo.c
sound/soc/omap/rx51.c
sound/soc/omap/sdp3430.c
sound/soc/omap/sdp4430.c
sound/soc/omap/zoom2.c
sound/soc/pxa/Kconfig
sound/soc/pxa/Makefile
sound/soc/pxa/corgi.c
sound/soc/pxa/e740_wm9705.c
sound/soc/pxa/e750_wm9705.c
sound/soc/pxa/e800_wm9712.c
sound/soc/pxa/em-x270.c
sound/soc/pxa/imote2.c
sound/soc/pxa/magician.c
sound/soc/pxa/mioa701_wm9713.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa-ssp.h
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-ac97.h
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-i2s.h
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/pxa2xx-pcm.h [deleted file]
sound/soc/pxa/raumfeld.c
sound/soc/pxa/saarb.c [new file with mode: 0644]
sound/soc/pxa/spitz.c
sound/soc/pxa/tavorevb3.c [new file with mode: 0644]
sound/soc/pxa/tosa.c
sound/soc/pxa/z2.c
sound/soc/pxa/zylonite.c
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/Makefile
sound/soc/s3c24xx/aquila_wm8994.c [new file with mode: 0644]
sound/soc/s3c24xx/goni_wm8994.c [new file with mode: 0644]
sound/soc/s3c24xx/jive_wm8750.c
sound/soc/s3c24xx/ln2440sbc_alc650.c
sound/soc/s3c24xx/neo1973_gta02_wm8753.c
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/s3c24xx/rx1950_uda1380.c [new file with mode: 0644]
sound/soc/s3c24xx/s3c-ac97.c
sound/soc/s3c24xx/s3c-ac97.h
sound/soc/s3c24xx/s3c-dma.c
sound/soc/s3c24xx/s3c-dma.h
sound/soc/s3c24xx/s3c-i2s-v2.c
sound/soc/s3c24xx/s3c-i2s-v2.h
sound/soc/s3c24xx/s3c-pcm.c
sound/soc/s3c24xx/s3c-pcm.h
sound/soc/s3c24xx/s3c2412-i2s.c
sound/soc/s3c24xx/s3c2412-i2s.h
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s3c24xx/s3c24xx-i2s.h
sound/soc/s3c24xx/s3c24xx_simtec.c
sound/soc/s3c24xx/s3c24xx_simtec.h
sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
sound/soc/s3c24xx/s3c24xx_uda134x.c
sound/soc/s3c24xx/s3c64xx-i2s-v4.c
sound/soc/s3c24xx/s3c64xx-i2s.c
sound/soc/s3c24xx/s3c64xx-i2s.h
sound/soc/s3c24xx/smartq_wm8987.c
sound/soc/s3c24xx/smdk2443_wm9710.c
sound/soc/s3c24xx/smdk64xx_wm8580.c
sound/soc/s3c24xx/smdk_spdif.c [new file with mode: 0644]
sound/soc/s3c24xx/smdk_wm9713.c
sound/soc/s3c24xx/spdif.c [new file with mode: 0644]
sound/soc/s3c24xx/spdif.h [new file with mode: 0644]
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-i2s.h
sound/soc/s6000/s6000-pcm.c
sound/soc/s6000/s6000-pcm.h
sound/soc/s6000/s6105-ipcam.c
sound/soc/sh/Kconfig
sound/soc/sh/Makefile
sound/soc/sh/dma-sh7760.c
sound/soc/sh/fsi-ak4642.c
sound/soc/sh/fsi-da7210.c
sound/soc/sh/fsi-hdmi.c [new file with mode: 0644]
sound/soc/sh/fsi.c
sound/soc/sh/hac.c
sound/soc/sh/migor.c
sound/soc/sh/sh7760-ac97.c
sound/soc/sh/siu.h
sound/soc/sh/siu_dai.c
sound/soc/sh/siu_pcm.c
sound/soc/sh/ssi.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-jack.c
sound/soc/txx9/txx9aclc-ac97.c
sound/soc/txx9/txx9aclc-generic.c
sound/soc/txx9/txx9aclc.c
sound/soc/txx9/txx9aclc.h
sound/synth/emux/emux_hwdep.c
sound/usb/Kconfig
sound/usb/caiaq/audio.c
sound/usb/caiaq/control.c
sound/usb/caiaq/device.c
sound/usb/caiaq/device.h
sound/usb/caiaq/input.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/helper.c
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/urb.c
sound/usb/usbaudio.h
sound/usb/usx2y/usx2yhwdeppcm.c

diff --git a/Documentation/ABI/obsolete/dv1394 b/Documentation/ABI/obsolete/dv1394
deleted file mode 100644 (file)
index 2ee3686..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-What:          dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
-Contact:       linux1394-devel@lists.sourceforge.net
-Description:
-       New application development should use raw1394 + userspace libraries
-       instead, notably libiec61883 which is functionally equivalent.
-
-Users:
-       ffmpeg/libavformat (used by a variety of media players)
-       dvgrab v1.x (replaced by dvgrab2 on top of raw1394 and resp. libraries)
diff --git a/Documentation/ABI/removed/dv1394 b/Documentation/ABI/removed/dv1394
new file mode 100644 (file)
index 0000000..c2310b6
--- /dev/null
@@ -0,0 +1,14 @@
+What:          dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/dv1394/* were character device files, one for each FireWire
+       controller and for NTSC and PAL respectively, from which DV data
+       could be received by read() or transmitted by write().  A few
+       ioctl()s allowed limited control.
+       This special-purpose interface has been superseded by libraw1394 +
+       libiec61883 which are functionally equivalent, support HDV, and
+       transparently work on top of the newer firewire kernel drivers.
+
+Users:
+       ffmpeg/libavformat (if configured for DV1394)
diff --git a/Documentation/ABI/removed/raw1394 b/Documentation/ABI/removed/raw1394
new file mode 100644 (file)
index 0000000..490aa1e
--- /dev/null
@@ -0,0 +1,15 @@
+What:          raw1394 (a.k.a. "Raw IEEE1394 I/O support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/raw1394 was a character device file that allowed low-level
+       access to FireWire buses.  Its major drawbacks were its inability
+       to implement sensible device security policies, and its low level
+       of abstraction that required userspace clients do duplicate much
+       of the kernel's ieee1394 core functionality.
+       Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
+       firewire-core.
+
+Users:
+       libraw1394 (works with firewire-cdev too, transparent to library ABI
+       users)
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
deleted file mode 100644 (file)
index 1b62962..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-What:          legacy isochronous ABI of raw1394 (1st generation iso ABI)
-Date:          June 2007 (scheduled), removed in kernel v2.6.23
-Contact:       linux1394-devel@lists.sourceforge.net
-Description:
-       The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
-       been deprecated for quite some time.  They are very inefficient as they
-       come with high interrupt load and several layers of callbacks for each
-       packet.  Because of these deficiencies, the video1394 and dv1394 drivers
-       and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
-
-Users:
-       libraw1394 users via the long deprecated API raw1394_iso_write,
-       raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
-
-       libdc1394, which optionally uses these old libraw1394 calls
-       alternatively to the more efficient video1394 ABI
diff --git a/Documentation/ABI/removed/video1394 b/Documentation/ABI/removed/video1394
new file mode 100644 (file)
index 0000000..c39c25a
--- /dev/null
@@ -0,0 +1,16 @@
+What:          video1394 (a.k.a. "OHCI-1394 Video support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/video1394/* were character device files, one for each FireWire
+       controller, which were used for isochronous I/O.  It was added as an
+       alternative to raw1394's isochronous I/O functionality which had
+       performance issues in its first generation.  Any video1394 user had
+       to use raw1394 + libraw1394 too because video1394 did not provide
+       asynchronous I/O for device discovery and configuration.
+       Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
+       firewire-core.
+
+Users:
+       libdc1394 (works with firewire-cdev too, transparent to library ABI
+       users)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl b/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl
new file mode 100644 (file)
index 0000000..b82deea
--- /dev/null
@@ -0,0 +1,22 @@
+What:           state
+Date:           Sep 2010
+KernelVersion:  2.6.37
+Contact:        Vernon Mauery <vernux@us.ibm.com>
+Description:    The state file allows a means by which to change in and
+                out of Premium Real-Time Mode (PRTM), as well as the
+                ability to query the current state.
+                    0 => PRTM off
+                    1 => PRTM enabled
+Users:          The ibm-prtm userspace daemon uses this interface.
+
+
+What:           version
+Date:           Sep 2010
+KernelVersion:  2.6.37
+Contact:        Vernon Mauery <vernux@us.ibm.com>
+Description:    The version file provides a means by which to query
+                the RTL table version that lives in the Extended
+                BIOS Data Area (EBDA).
+Users:          The ibm-prtm userspace daemon uses this interface.
+
+
index 9961f15..e833c8c 100644 (file)
@@ -502,16 +502,6 @@ Who:       Thomas Gleixner <tglx@linutronix.de>
 
 ----------------------------
 
-What:  old ieee1394 subsystem (CONFIG_IEEE1394)
-When:  2.6.37
-Files: drivers/ieee1394/ except init_ohci1394_dma.c
-Why:   superseded by drivers/firewire/ (CONFIG_FIREWIRE) which offers more
-       features, better performance, and better security, all with smaller
-       and more modern code base
-Who:   Stefan Richter <stefanr@s5r6.in-berlin.de>
-
-----------------------------
-
 What:  The acpi_sleep=s4_nonvs command line option
 When:  2.6.37
 Files: arch/x86/kernel/acpi/sleep.c
index 2f68cd6..3225a56 100644 (file)
@@ -14,3 +14,5 @@ nfsroot.txt
        - short guide on setting up a diskless box with NFS root filesystem.
 rpc-cache.txt
        - introduction to the caching mechanisms in the sunrpc layer.
+idmapper.txt
+       - information for configuring request-keys to be used by idmapper
diff --git a/Documentation/filesystems/nfs/idmapper.txt b/Documentation/filesystems/nfs/idmapper.txt
new file mode 100644 (file)
index 0000000..c385204
--- /dev/null
@@ -0,0 +1,67 @@
+
+=========
+ID Mapper
+=========
+Id mapper is used by NFS to translate user and group ids into names, and to
+translate user and group names into ids.  Part of this translation involves
+performing an upcall to userspace to request the information.  Id mapper will
+user request-key to perform this upcall and cache the result.  The program
+/usr/sbin/nfs.upcall should be called by request-key, and will perform the
+translation and initialize a key with the resulting information.
+
+ NFS_USE_NEW_IDMAPPER must be selected when configuring the kernel to use this
+ feature.
+
+===========
+Configuring
+===========
+The file /etc/request-key.conf will need to be modified so /sbin/request-key can
+direct the upcall.  The following line should be added:
+
+#OP    TYPE    DESCRIPTION     CALLOUT INFO    PROGRAM ARG1 ARG2 ARG3 ...
+#======        ======= =============== =============== ===============================
+create id_resolver     *       *               /usr/sbin/nfs.upcall %k %d 600
+
+This will direct all id_resolver requests to the program /usr/sbin/nfs.upcall.
+The last parameter, 600, defines how many seconds into the future the key will
+expire.  This parameter is optional for /usr/sbin/nfs.upcall.  When the timeout
+is not specified, nfs.upcall will default to 600 seconds.
+
+id mapper uses for key descriptions:
+         uid:  Find the UID for the given user
+         gid:  Find the GID for the given group
+        user:  Find the user  name for the given UID
+       group:  Find the group name for the given GID
+
+You can handle any of these individually, rather than using the generic upcall
+program.  If you would like to use your own program for a uid lookup then you
+would edit your request-key.conf so it look similar to this:
+
+#OP    TYPE    DESCRIPTION     CALLOUT INFO    PROGRAM ARG1 ARG2 ARG3 ...
+#======        ======= =============== =============== ===============================
+create id_resolver     uid:*   *               /some/other/program  %k %d 600
+create id_resolver     *       *               /usr/sbin/nfs.upcall %k %d 600
+
+Notice that the new line was added above the line for the generic program.
+request-key will find the first matching line and corresponding program.  In
+this case, /some/other/program will handle all uid lookups and
+/usr/sbin/nfs.upcall will handle gid, user, and group lookups.
+
+See <file:Documentation/keys-request-keys.txt> for more information about the
+request-key function.
+
+
+==========
+nfs.upcall
+==========
+nfs.upcall is designed to be called by request-key, and should not be run "by
+hand".  This program takes two arguments, a serialized key and a key
+description.  The serialized key is first converted into a key_serial_t, and
+then passed as an argument to keyctl_instantiate (both are part of keyutils.h).
+
+The actual lookups are performed by functions found in nfsidmap.h.  nfs.upcall
+determines the correct function to call by looking at the first part of the
+description string.  For example, a uid lookup description will appear as
+"uid:user@domain".
+
+nfs.upcall will return 0 if the key was instantiated, and non-zero otherwise.
index f2430a7..90c71c6 100644 (file)
@@ -159,6 +159,28 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
                 Default: any
 
 
+nfsrootdebug
+
+  This parameter enables debugging messages to appear in the kernel
+  log at boot time so that administrators can verify that the correct
+  NFS mount options, server address, and root path are passed to the
+  NFS client.
+
+
+rdinit=<executable file>
+
+  To specify which file contains the program that starts system
+  initialization, administrators can use this command line parameter.
+  The default value of this parameter is "/init".  If the specified
+  file exists and the kernel can execute it, root filesystem related
+  kernel command line parameters, including `nfsroot=', are ignored.
+
+  A description of the process of mounting the root file system can be
+  found in:
+
+    Documentation/early-userspace/README
+
+
 
 
 3.) Boot Loader
diff --git a/Documentation/hwmon/ltc4261 b/Documentation/hwmon/ltc4261
new file mode 100644 (file)
index 0000000..eba2e2c
--- /dev/null
@@ -0,0 +1,63 @@
+Kernel driver ltc4261
+=====================
+
+Supported chips:
+  * Linear Technology LTC4261
+    Prefix: 'ltc4261'
+    Addresses scanned: -
+    Datasheet:
+        http://cds.linear.com/docs/Datasheet/42612fb.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC4261/LTC4261-2 negative voltage Hot Swap controllers allow a board
+to be safely inserted and removed from a live backplane.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4261 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4261 at address 0x10
+on I2C bus #1:
+$ modprobe ltc4261
+$ echo ltc4261 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADC
+registers. If a set of voltage divider resistors is installed, calculate the
+real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
+value of the divider resistor against the measured voltage and R2 is the value
+of the divider resistor against Ground.
+
+Current reading provided by this driver is reported as obtained from the ADC
+Current Sense register. The reported value assumes that a 1 mOhm sense resistor
+is installed. If a different sense resistor is installed, calculate the real
+current by dividing the reported value by the sense resistor value in mOhm.
+
+The chip has two voltage sensors, but only one set of voltage alarm status bits.
+In many many designs, those alarms are associated with the ADIN2 sensor, due to
+the proximity of the ADIN2 pin to the OV pin. ADIN2 is, however, not available
+on all chip variants. To ensure that the alarm condition is reported to the user,
+report it with both voltage sensors.
+
+in1_input              ADIN2 voltage (mV)
+in1_min_alarm          ADIN/ADIN2 Undervoltage alarm
+in1_max_alarm          ADIN/ADIN2 Overvoltage alarm
+
+in2_input              ADIN voltage (mV)
+in2_min_alarm          ADIN/ADIN2 Undervoltage alarm
+in2_max_alarm          ADIN/ADIN2 Overvoltage alarm
+
+curr1_input            SENSE current (mA)
+curr1_alarm            SENSE overcurrent alarm
index 0b68155..4bc2f3c 100644 (file)
@@ -1541,12 +1541,15 @@ and is between 256 and 4096 characters. It is defined in the file
                        1 to enable accounting
                        Default value is 0.
 
-       nfsaddrs=       [NFS]
+       nfsaddrs=       [NFS] Deprecated.  Use ip= instead.
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
        nfsroot=        [NFS] nfs root filesystem for disk-less boxes.
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
+       nfsrootdebug    [NFS] enable nfsroot debugging messages.
+                       See Documentation/filesystems/nfs/nfsroot.txt.
+
        nfs.callback_tcpport=
                        [NFS] set the TCP port on which the NFSv4 callback
                        channel should listen.
@@ -2438,7 +2441,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        topology informations if the hardware supports these.
                        The scheduler will make use of these informations and
                        e.g. base its process migration decisions on it.
-                       Default is off.
+                       Default is on.
 
        tp720=          [HW,PS2]
 
index 7f4dceb..d0eb696 100644 (file)
@@ -300,6 +300,74 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
            control correctly. If you have problems regarding this, try
            another ALSA compliant mixer (alsamixer works).
 
+  Module snd-azt1605
+  ------------------
+
+    Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
+    chipset.
+
+    port       - port # for BASE (0x220,0x240,0x260,0x280)
+    wss_port   - port # for WSS (0x530,0x604,0xe80,0xf40)
+    irq                - IRQ # for WSS (7,9,10,11)
+    dma1       - DMA # for WSS playback (0,1,3)
+    dma2       - DMA # for WSS capture (0,1), -1 = disabled (default)
+    mpu_port   - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+    mpu_irq    - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
+    fm_port    - port # for OPL3 (0x388), -1 = disabled (default)
+
+    This module supports multiple cards. It does not support autoprobe: port,
+    wss_port, irq and dma1 have to be specified. The other values are
+    optional.
+
+    "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+    or the value stored in the card's EEPROM for cards that have an EEPROM and
+    their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+    be choosen freely from the options enumerated above.
+
+    If dma2 is specified and different from dma1, the card will operate in
+    full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
+    enable capture since only channels 0 and 1 are available for capture.
+
+    Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+    mpu_port=0x330 mpu_irq=9 fm_port=0x388".
+
+    Whatever IRQ and DMA channels you pick, be sure to reserve them for
+    legacy ISA in your BIOS.
+
+  Module snd-azt2316
+  ------------------
+
+    Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
+    chipset.
+
+    port       - port # for BASE (0x220,0x240,0x260,0x280)
+    wss_port   - port # for WSS (0x530,0x604,0xe80,0xf40)
+    irq                - IRQ # for WSS (7,9,10,11)
+    dma1       - DMA # for WSS playback (0,1,3)
+    dma2       - DMA # for WSS capture (0,1), -1 = disabled (default)
+    mpu_port   - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+    mpu_irq    - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
+    fm_port    - port # for OPL3 (0x388), -1 = disabled (default)
+
+    This module supports multiple cards. It does not support autoprobe: port,
+    wss_port, irq and dma1 have to be specified. The other values are
+    optional.
+
+    "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+    or the value stored in the card's EEPROM for cards that have an EEPROM and
+    their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+    be choosen freely from the options enumerated above.
+
+    If dma2 is specified and different from dma1, the card will operate in
+    full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
+    enable capture since only channels 0 and 1 are available for capture.
+
+    Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+    mpu_port=0x330 mpu_irq=9 fm_port=0x388".
+
+    Whatever IRQ and DMA channels you pick, be sure to reserve them for
+    legacy ISA in your BIOS.
+
   Module snd-aw2
   --------------
 
@@ -1641,20 +1709,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
 
-  Module snd-sgalaxy
-  ------------------
-
-    Module for Aztech Sound Galaxy sound card.
-
-    sbport     - Port # for SB16 interface (0x220,0x240)
-    wssport    - Port # for WSS interface (0x530,0xe80,0xf40,0x604)
-    irq                - IRQ # (7,9,10,11)
-    dma1       - DMA #
-
-    This module supports multiple cards.
-
-    The power-management is supported.
-
   Module snd-sscape
   -----------------
 
index 278cc21..c82beb0 100644 (file)
@@ -57,9 +57,11 @@ dead.  However, this detection isn't perfect on some devices.  In such
 a case, you can change the default method via `position_fix` option.
 
 `position_fix=1` means to use LPIB method explicitly.
-`position_fix=2` means to use the position-buffer.  0 is the default
-value, the automatic check and fallback to LPIB as described in the
-above.  If you get a problem of repeated sounds, this option might
+`position_fix=2` means to use the position-buffer.
+`position_fix=3` means to use a combination of both methods, needed
+for some VIA and ATI controllers.  0 is the default value for all other
+controllers, the automatic check and fallback to LPIB as described in
+the above.  If you get a problem of repeated sounds, this option might
 help.
 
 In addition to that, every controller is known to be broken regarding
index 69aa8fe..146b8a0 100644 (file)
@@ -1562,9 +1562,8 @@ F:        net/ceph
 F:     include/linux/ceph
 
 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
-M:     David Vrabel <david.vrabel@csr.com>
 L:     linux-usb@vger.kernel.org
-S:     Supported
+S:     Orphan
 F:     Documentation/usb/WUSB-Design-overview.txt
 F:     Documentation/usb/wusb-cbaf
 F:     drivers/usb/host/hwa-hc.c
@@ -2646,10 +2645,10 @@ F:      drivers/net/greth*
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 M:     Frank Seidel <frank@f-seidel.de>
-L:     lm-sensors@lm-sensors.org
+L:     platform-driver-x86@vger.kernel.org
 W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 S:     Maintained
-F:     drivers/hwmon/hdaps.c
+F:     drivers/platform/x86/hdaps.c
 
 HWPOISON MEMORY FAILURE HANDLING
 M:     Andi Kleen <andi@firstfloor.org>
@@ -3766,6 +3765,13 @@ L:       linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/sym53c8xx_2/
 
+LTC4261 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ltc4261
+F:     drivers/hwmon/ltc4261.c
+
 LTP (Linux Test Project)
 M:     Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
 M:     Garrett Cooper <yanegomi@gmail.com>
@@ -5389,8 +5395,8 @@ F:        drivers/*/*s3c2410*
 F:     drivers/*/*/*s3c2410*
 
 TI DAVINCI MACHINE SUPPORT
-P:     Kevin Hilman
-M:     davinci-linux-open-source@linux.davincidsp.com
+M:     Kevin Hilman <khilman@deeprootsystems.com>
+L:     davinci-linux-open-source@linux.davincidsp.com (subscribers-only)
 Q:     http://patchwork.kernel.org/project/linux-davinci/list/
 S:     Supported
 F:     arch/arm/mach-davinci
@@ -5991,13 +5997,9 @@ F:       Documentation/filesystems/ufs.txt
 F:     fs/ufs/
 
 ULTRA-WIDEBAND (UWB) SUBSYSTEM:
-M:     David Vrabel <david.vrabel@csr.com>
 L:     linux-usb@vger.kernel.org
-S:     Supported
+S:     Orphan
 F:     drivers/uwb/
-X:     drivers/uwb/wlp/
-X:     drivers/uwb/i1480/i1480u-wlp/
-X:     drivers/uwb/i1480/i1480-wlp.h
 F:     include/linux/uwb.h
 F:     include/linux/uwb/
 
@@ -6533,15 +6535,6 @@ F:       include/linux/wimax/debug.h
 F:     include/net/wimax.h
 F:     net/wimax/
 
-WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
-M:     David Vrabel <david.vrabel@csr.com>
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     include/linux/wlp.h
-F:     drivers/uwb/wlp/
-F:     drivers/uwb/i1480/i1480u-wlp/
-F:     drivers/uwb/i1480/i1480-wlp.h
-
 WISTRON LAPTOP BUTTON DRIVER
 M:     Miloslav Trmac <mitr@volny.cz>
 S:     Maintained
index b64e465..bf7273f 100644 (file)
@@ -573,6 +573,7 @@ config ARCH_TEGRA
        select HAVE_CLK
        select COMMON_CLKDEV
        select ARCH_HAS_BARRIERS if CACHE_L2X0
+       select ARCH_HAS_CPUFREQ
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
          Tegra 6xx and Tegra 2 series).
@@ -831,7 +832,7 @@ config ARCH_OMAP
        select GENERIC_CLOCKEVENTS
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
-         Support for TI's OMAP platform (OMAP1 and OMAP2).
+         Support for TI's OMAP platform (OMAP1/2/3/4).
 
 config PLAT_SPEAR
        bool "ST SPEAr"
index ba66705..cdc40c4 100644 (file)
@@ -17,6 +17,8 @@ CONFIG_MODVERSIONS=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_ARCH_DAVINCI_DA830=y
 CONFIG_ARCH_DAVINCI_DA850=y
+CONFIG_MACH_MITYOMAPL138=y
+CONFIG_MACH_OMAPL138_HAWKBOARD=y
 CONFIG_DAVINCI_RESET_CLOCKS=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -79,6 +81,7 @@ CONFIG_I2C_DAVINCI=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_FB=y
 CONFIG_FB_DA8XX=y
diff --git a/arch/arm/configs/n8x0_defconfig b/arch/arm/configs/n8x0_defconfig
deleted file mode 100644 (file)
index 56aebb6..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-CONFIG_OMAP_RESET_CLOCKS=y
-# CONFIG_OMAP_MUX is not set
-# CONFIG_OMAP_MCBSP is not set
-CONFIG_OMAP_MBOX_FWK=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_MACH_NOKIA_N8X0=y
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 console=ttyS2,115200n8 debug earlyprintk rootwait"
-CONFIG_FPE_NWFPE=y
-CONFIG_VFP=y
-CONFIG_PM=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_OMAP2=y
-CONFIG_MTD_ONENAND_OTP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_MENELAUS=y
-CONFIG_REGULATOR=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG_WHITELIST is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-# CONFIG_MUSB_PIO_ONLY is not set
-CONFIG_USB_MUSB_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_ETH=m
-CONFIG_USB_ETH_EEM=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_CRC_CCITT=y
similarity index 90%
rename from arch/arm/configs/omap3_defconfig
rename to arch/arm/configs/omap2plus_defconfig
index 5db9a6b..ccedde1 100644 (file)
@@ -53,18 +53,18 @@ CONFIG_MACH_SBC3530=y
 CONFIG_MACH_OMAP_3630SDP=y
 CONFIG_MACH_OMAP_4430SDP=y
 CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_LOCAL_TIMERS is not set
 CONFIG_AEABI=y
 CONFIG_LEDS=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyS2,115200"
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
 CONFIG_KEXEC=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 CONFIG_FPE_NWFPE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -87,23 +87,23 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_NETFILTER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP=m
 CONFIG_BT_BNEP_MC_FILTER=y
 CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIUART=m
 CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_BCSP=y
 CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=y
-CONFIG_BT_HCIBPA10X=y
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
 CONFIG_MAC80211_RC_PID=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_LEDS=y
@@ -137,9 +137,11 @@ CONFIG_SMSC_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
-CONFIG_LIBERTAS=y
-CONFIG_LIBERTAS_USB=y
-CONFIG_LIBERTAS_SDIO=y
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
 CONFIG_LIBERTAS_DEBUG=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_ALI_M5632=y
@@ -201,8 +203,8 @@ CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
+CONFIG_SOUND=m
+CONFIG_SND=m
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 CONFIG_SND_VERBOSE_PRINTK=y
@@ -218,9 +220,9 @@ CONFIG_USB_DEVICEFS=y
 CONFIG_USB_SUSPEND=y
 # CONFIG_USB_OTG_WHITELIST is not set
 CONFIG_USB_MON=y
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
 CONFIG_USB_MUSB_DEBUG=y
 CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
@@ -276,12 +278,11 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_PROVE_LOCKING=y
-CONFIG_LOCK_STAT=y
+# CONFIG_LOCK_STAT is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_LL=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig
deleted file mode 100644 (file)
index 14c1e18..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_ELF_CORE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP4=y
-# CONFIG_ARCH_OMAP2PLUS_TYPICAL is not set
-# CONFIG_ARCH_OMAP2 is not set
-# CONFIG_ARCH_OMAP3 is not set
-# CONFIG_OMAP_MUX is not set
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_DM_TIMER=y
-CONFIG_MACH_OMAP_4430SDP=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-# CONFIG_LOCAL_TIMERS is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS2,115200n8 initrd=0x81600000,20M ramdisk_size=20480"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_KS8851=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_TWL4030_CORE=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_TWL4030=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_TWL4030=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_QFMT_V2=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/omap_generic_2420_defconfig b/arch/arm/configs/omap_generic_2420_defconfig
deleted file mode 100644 (file)
index ac08e51..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-# CONFIG_OMAP_MUX is not set
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_FPE_NWFPE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_INOTIFY=y
-CONFIG_ROMFS_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRC_CCITT=y
index 71f90f8..b77b860 100644 (file)
@@ -20,23 +20,23 @@ config ARCH_DAVINCI_DM644x
        select ARCH_DAVINCI_DMx
 
 config ARCH_DAVINCI_DM355
-        bool "DaVinci 355 based system"
+       bool "DaVinci 355 based system"
        select AINTC
        select ARCH_DAVINCI_DMx
 
 config ARCH_DAVINCI_DM646x
-        bool "DaVinci 646x based system"
+       bool "DaVinci 646x based system"
        select AINTC
        select ARCH_DAVINCI_DMx
 
 config ARCH_DAVINCI_DA830
-        bool "DA830/OMAP-L137 based system"
+       bool "DA830/OMAP-L137/AM17x based system"
        select CP_INTC
        select ARCH_DAVINCI_DA8XX
        select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1
 
 config ARCH_DAVINCI_DA850
-       bool "DA850/OMAP-L138 based system"
+       bool "DA850/OMAP-L138/AM18x based system"
        select CP_INTC
        select ARCH_DAVINCI_DA8XX
        select ARCH_HAS_CPUFREQ
@@ -115,21 +115,21 @@ config MACH_DAVINCI_DM365_EVM
          for development is a DM365 EVM
 
 config MACH_DAVINCI_DA830_EVM
-       bool "TI DA830/OMAP-L137 Reference Platform"
+       bool "TI DA830/OMAP-L137/AM17x Reference Platform"
        default ARCH_DAVINCI_DA830
        depends on ARCH_DAVINCI_DA830
        select GPIO_PCF857X
        help
-         Say Y here to select the TI DA830/OMAP-L137 Evaluation Module.
+         Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
 choice
-       prompt "Select DA830/OMAP-L137 UI board peripheral"
+       prompt "Select DA830/OMAP-L137/AM17x UI board peripheral"
        depends on MACH_DAVINCI_DA830_EVM
        help
-         The presence of UI card on the DA830/OMAP-L137 EVM is detected
-         automatically based on successful probe of the I2C based GPIO
-         expander on that board. This option selected in this menu has
-         an effect only in case of a successful UI card detection.
+         The presence of UI card on the DA830/OMAP-L137/AM17x EVM is
+         detected automatically based on successful probe of the I2C
+         based GPIO expander on that board. This option selected in this
+         menu has an effect only in case of a successful UI card detection.
 
 config DA830_UI_LCD
        bool "LCD"
@@ -140,23 +140,23 @@ config DA830_UI_LCD
 config DA830_UI_NAND
        bool "NAND flash"
        help
-         Say Y here to use the NAND flash.  Do not forget to setup
+         Say Y here to use the NAND flash. Do not forget to setup
          the switch correctly.
 endchoice
 
 config MACH_DAVINCI_DA850_EVM
-       bool "TI DA850/OMAP-L138 Reference Platform"
+       bool "TI DA850/OMAP-L138/AM18x Reference Platform"
        default ARCH_DAVINCI_DA850
        depends on ARCH_DAVINCI_DA850
        select GPIO_PCA953X
        help
-         Say Y here to select the TI DA850/OMAP-L138 Evaluation Module.
+         Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module.
 
 choice
        prompt "Select peripherals connected to expander on UI board"
        depends on MACH_DAVINCI_DA850_EVM
        help
-         The presence of User Interface (UI) card on the DA850/OMAP-L138
+         The presence of User Interface (UI) card on the DA850/OMAP-L138/AM18x
          EVM is detected automatically based on successful probe of the I2C
          based GPIO expander on that card. This option selected in this
          menu has an effect only in case of a successful UI card detection.
@@ -165,13 +165,13 @@ config DA850_UI_NONE
        bool "No peripheral is enabled"
        help
          Say Y if you do not want to enable any of the peripherals connected
-         to TCA6416 expander on DA850/OMAP-L138 EVM UI card
+         to TCA6416 expander on DA850/OMAP-L138/AM18x EVM UI card
 
 config DA850_UI_RMII
        bool "RMII Ethernet PHY"
        help
-         Say Y if you want to use the RMII PHY on the DA850/OMAP-L138 EVM.
-         This PHY is found on the UI daughter card that is supplied with
+         Say Y if you want to use the RMII PHY on the DA850/OMAP-L138/AM18x
+         EVM. This PHY is found on the UI daughter card that is supplied with
          the EVM.
          NOTE: Please take care while choosing this option, MII PHY will
          not be functional if RMII mode is selected.
@@ -185,6 +185,22 @@ config MACH_TNETV107X
        help
          Say Y here to select the TI TNETV107X Evaluation Module.
 
+config MACH_MITYOMAPL138
+       bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
+       depends on ARCH_DAVINCI_DA850
+       help
+         Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
+         System on Module.  Information on this SoM may be found at
+         http://www.mitydsp.com
+
+config MACH_OMAPL138_HAWKBOARD
+       bool "TI AM1808 / OMAPL-138 Hawkboard platform"
+       depends on ARCH_DAVINCI_DA850
+       help
+         Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform .
+         Information of this board may be found at
+         http://www.hawkboard.org/
+
 config DAVINCI_MUX
        bool "DAVINCI multiplexing support"
        depends on ARCH_DAVINCI
@@ -195,20 +211,20 @@ config DAVINCI_MUX
          say Y.
 
 config DAVINCI_MUX_DEBUG
-        bool "Multiplexing debug output"
-        depends on DAVINCI_MUX
-        help
-          Makes the multiplexing functions print out a lot of debug info.
-          This is useful if you want to find out the correct values of the
-          multiplexing registers.
+       bool "Multiplexing debug output"
+       depends on DAVINCI_MUX
+       help
+         Makes the multiplexing functions print out a lot of debug info.
+         This is useful if you want to find out the correct values of the
+         multiplexing registers.
 
 config DAVINCI_MUX_WARNINGS
-        bool "Warn about pins the bootloader didn't set up"
-        depends on DAVINCI_MUX
-        help
-          Choose Y here to warn whenever driver initialization logic needs
-          to change the pin multiplexing setup.  When there are no warnings
-          printed, it's safe to deselect DAVINCI_MUX for your product.
+       bool "Warn about pins the bootloader didn't set up"
+       depends on DAVINCI_MUX
+       help
+         Choose Y here to warn whenever driver initialization logic needs
+         to change the pin multiplexing setup. When there are no warnings
+         printed, it's safe to deselect DAVINCI_MUX for your product.
 
 config DAVINCI_RESET_CLOCKS
        bool "Reset unused clocks during boot"
index eab4c0f..0b87a1c 100644 (file)
@@ -5,7 +5,7 @@
 
 # Common objects
 obj-y                  := time.o clock.o serial.o io.o psc.o \
-                          gpio.o dma.o usb.o common.o sram.o
+                          gpio.o dma.o usb.o common.o sram.o aemif.o
 
 obj-$(CONFIG_DAVINCI_MUX)              += mux.o
 
@@ -33,6 +33,8 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM)  += board-dm365-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA830_EVM)   += board-da830-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA850_EVM)   += board-da850-evm.o
 obj-$(CONFIG_MACH_TNETV107X)           += board-tnetv107x-evm.o
+obj-$(CONFIG_MACH_MITYOMAPL138)                += board-mityomapl138.o
+obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD)  += board-omapl138-hawk.o
 
 # Power Management
 obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
new file mode 100644 (file)
index 0000000..9c3f500
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * AEMIF support for DaVinci SoCs
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/time.h>
+
+#include <mach/aemif.h>
+
+/* Timing value configuration */
+
+#define TA(x)          ((x) << 2)
+#define RHOLD(x)       ((x) << 4)
+#define RSTROBE(x)     ((x) << 7)
+#define RSETUP(x)      ((x) << 13)
+#define WHOLD(x)       ((x) << 17)
+#define WSTROBE(x)     ((x) << 20)
+#define WSETUP(x)      ((x) << 26)
+
+#define TA_MAX         0x3
+#define RHOLD_MAX      0x7
+#define RSTROBE_MAX    0x3f
+#define RSETUP_MAX     0xf
+#define WHOLD_MAX      0x7
+#define WSTROBE_MAX    0x3f
+#define WSETUP_MAX     0xf
+
+#define TIMING_MASK    (TA(TA_MAX) | \
+                               RHOLD(RHOLD_MAX) | \
+                               RSTROBE(RSTROBE_MAX) |  \
+                               RSETUP(RSETUP_MAX) | \
+                               WHOLD(WHOLD_MAX) | \
+                               WSTROBE(WSTROBE_MAX) | \
+                               WSETUP(WSETUP_MAX))
+
+/*
+ * aemif_calc_rate - calculate timing data.
+ * @wanted: The cycle time needed in nanoseconds.
+ * @clk: The input clock rate in kHz.
+ * @max: The maximum divider value that can be programmed.
+ *
+ * On success, returns the calculated timing value minus 1 for easy
+ * programming into AEMIF timing registers, else negative errno.
+ */
+static int aemif_calc_rate(int wanted, unsigned long clk, int max)
+{
+       int result;
+
+       result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
+
+       pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted);
+
+       /* It is generally OK to have a more relaxed timing than requested... */
+       if (result < 0)
+               result = 0;
+
+       /* ... But configuring tighter timings is not an option. */
+       else if (result > max)
+               result = -EINVAL;
+
+       return result;
+}
+
+/**
+ * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
+ * @t: timing values to be progammed
+ * @base: The virtual base address of the AEMIF interface
+ * @cs: chip-select to program the timing values for
+ *
+ * This function programs the given timing values (in real clock) into the
+ * AEMIF registers taking the AEMIF clock into account.
+ *
+ * This function does not use any locking while programming the AEMIF
+ * because it is expected that there is only one user of a given
+ * chip-select.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+                                       void __iomem *base, unsigned cs)
+{
+       unsigned set, val;
+       unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
+       unsigned offset = A1CR_OFFSET + cs * 4;
+       struct clk *aemif_clk;
+       unsigned long clkrate;
+
+       if (!t)
+               return 0;       /* Nothing to do */
+
+       aemif_clk = clk_get(NULL, "aemif");
+       if (IS_ERR(aemif_clk))
+               return PTR_ERR(aemif_clk);
+
+       clkrate = clk_get_rate(aemif_clk);
+
+       clkrate /= 1000;        /* turn clock into kHz for ease of use */
+
+       ta      = aemif_calc_rate(t->ta, clkrate, TA_MAX);
+       rhold   = aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX);
+       rstrobe = aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX);
+       rsetup  = aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX);
+       whold   = aemif_calc_rate(t->whold, clkrate, WHOLD_MAX);
+       wstrobe = aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX);
+       wsetup  = aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX);
+
+       if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
+                       whold < 0 || wstrobe < 0 || wsetup < 0) {
+               pr_err("%s: cannot get suitable timings\n", __func__);
+               return -EINVAL;
+       }
+
+       set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
+               WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
+
+       val = __raw_readl(base + offset);
+       val &= ~TIMING_MASK;
+       val |= set;
+       __raw_writel(val, base + offset);
+
+       return 0;
+}
+EXPORT_SYMBOL(davinci_aemif_setup_timing);
index 7f3cdbf..b52a3a1 100644 (file)
 #include <mach/nand.h>
 #include <mach/da8xx.h>
 #include <mach/usb.h>
+#include <mach/aemif.h>
 
-#define DA830_EVM_PHY_MASK             0x0
-#define DA830_EVM_MDIO_FREQUENCY       2200000 /* PHY bus frequency */
-
+#define DA830_EVM_PHY_ID               ""
 /*
  * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
  */
@@ -360,6 +359,16 @@ static struct nand_bbt_descr da830_evm_nand_bbt_mirror_descr = {
        .pattern        = da830_evm_nand_mirror_pattern
 };
 
+static struct davinci_aemif_timing da830_evm_nandflash_timing = {
+       .wsetup         = 24,
+       .wstrobe        = 21,
+       .whold          = 14,
+       .rsetup         = 19,
+       .rstrobe        = 50,
+       .rhold          = 0,
+       .ta             = 20,
+};
+
 static struct davinci_nand_pdata da830_evm_nand_pdata = {
        .parts          = da830_evm_nand_partitions,
        .nr_parts       = ARRAY_SIZE(da830_evm_nand_partitions),
@@ -368,6 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
        .options        = NAND_USE_FLASH_BBT,
        .bbt_td         = &da830_evm_nand_bbt_main_descr,
        .bbt_md         = &da830_evm_nand_bbt_mirror_descr,
+       .timing         = &da830_evm_nandflash_timing,
 };
 
 static struct resource da830_evm_nand_resources[] = {
@@ -546,9 +556,8 @@ static __init void da830_evm_init(void)
 
        da830_evm_usb_init();
 
-       soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY;
        soc_info->emac_pdata->rmii_en = 1;
+       soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID;
 
        ret = davinci_cfg_reg_list(da830_cpgmac_pins);
        if (ret)
@@ -586,6 +595,9 @@ static __init void da830_evm_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 static int __init da830_evm_console_init(void)
 {
+       if (!machine_is_davinci_da830_evm())
+               return 0;
+
        return add_preferred_console("ttyS", 2, "115200");
 }
 console_initcall(da830_evm_console_init);
@@ -596,7 +608,7 @@ static void __init da830_evm_map_io(void)
        da830_init();
 }
 
-MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
+MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
        .boot_params    = (DA8XX_DDR_BASE + 0x100),
        .map_io         = da830_evm_map_io,
        .init_irq       = cp_intc_init,
index b26f5cb..c6e11c6 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps6507x.h>
-#include <linux/mfd/tps6507x.h>
 #include <linux/input/tps6507x-ts.h>
 
 #include <asm/mach-types.h>
 #include <mach/da8xx.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
+#include <mach/aemif.h>
 
-#define DA850_EVM_PHY_MASK             0x1
-#define DA850_EVM_MDIO_FREQUENCY       2200000 /* PHY bus frequency */
-
+#define DA850_EVM_PHY_ID               "0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
 
@@ -110,7 +108,7 @@ static struct platform_device da850_pm_device = {
  * to boot, using TI's tools to install the secondary boot loader
  * (UBL) and U-Boot.
  */
-struct mtd_partition da850_evm_nandflash_partition[] = {
+static struct mtd_partition da850_evm_nandflash_partition[] = {
        {
                .name           = "u-boot env",
                .offset         = 0,
@@ -143,12 +141,23 @@ struct mtd_partition da850_evm_nandflash_partition[] = {
        },
 };
 
+static struct davinci_aemif_timing da850_evm_nandflash_timing = {
+       .wsetup         = 24,
+       .wstrobe        = 21,
+       .whold          = 14,
+       .rsetup         = 19,
+       .rstrobe        = 50,
+       .rhold          = 0,
+       .ta             = 20,
+};
+
 static struct davinci_nand_pdata da850_evm_nandflash_data = {
        .parts          = da850_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(da850_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
        .ecc_bits       = 4,
        .options        = NAND_USE_FLASH_BBT,
+       .timing         = &da850_evm_nandflash_timing,
 };
 
 static struct resource da850_evm_nandflash_resource[] = {
@@ -196,6 +205,30 @@ static void __init da850_evm_init_nor(void)
        iounmap(aemif_addr);
 }
 
+static const short da850_evm_nand_pins[] = {
+       DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
+       DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
+       DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
+       DA850_NEMA_WE, DA850_NEMA_OE,
+       -1
+};
+
+static const short da850_evm_nor_pins[] = {
+       DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
+       DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
+       DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
+       DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
+       DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
+       DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
+       DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
+       DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
+       DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
+       DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
+       DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
+       DA850_EMA_A_22, DA850_EMA_A_23,
+       -1
+};
+
 static u32 ui_card_detected;
 
 #if defined(CONFIG_MMC_DAVINCI) || \
@@ -205,17 +238,17 @@ static u32 ui_card_detected;
 #define HAS_MMC 0
 #endif
 
-static __init void da850_evm_setup_nor_nand(void)
+static inline void da850_evm_setup_nor_nand(void)
 {
        int ret = 0;
 
        if (ui_card_detected & !HAS_MMC) {
-               ret = davinci_cfg_reg_list(da850_nand_pins);
+               ret = davinci_cfg_reg_list(da850_evm_nand_pins);
                if (ret)
                        pr_warning("da850_evm_init: nand mux setup failed: "
                                        "%d\n", ret);
 
-               ret = davinci_cfg_reg_list(da850_nor_pins);
+               ret = davinci_cfg_reg_list(da850_evm_nor_pins);
                if (ret)
                        pr_warning("da850_evm_init: nor mux setup failed: %d\n",
                                ret);
@@ -406,7 +439,7 @@ static int da850_lcd_hw_init(void)
 /* TPS65070 voltage regulator support */
 
 /* 3.3V */
-struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
        {
                .supply = "usb0_vdda33",
        },
@@ -416,7 +449,7 @@ struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
 };
 
 /* 3.3V or 1.8V */
-struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
        {
                .supply = "dvdd3318_a",
        },
@@ -429,14 +462,14 @@ struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
 };
 
 /* 1.2V */
-struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
        {
                .supply = "cvdd",
        },
 };
 
 /* 1.8V LDO */
-struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
+static struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
        {
                .supply = "sata_vddr",
        },
@@ -452,7 +485,7 @@ struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
 };
 
 /* 1.2V LDO */
-struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
+static struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
        {
                .supply = "sata_vdd",
        },
@@ -475,7 +508,7 @@ static struct tps6507x_reg_platform_data tps6507x_platform_data = {
        .defdcdc_default = true,
 };
 
-struct regulator_init_data tps65070_regulator_data[] = {
+static struct regulator_init_data tps65070_regulator_data[] = {
        /* dcdc1 */
        {
                .constraints = {
@@ -576,6 +609,23 @@ static const short da850_evm_lcdc_pins[] = {
        -1
 };
 
+static const short da850_evm_mii_pins[] = {
+       DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+       DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+       DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+       DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+       DA850_MDIO_D,
+       -1
+};
+
+static const short da850_evm_rmii_pins[] = {
+       DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+       DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
+       DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
+       DA850_MDIO_D,
+       -1
+};
+
 static int __init da850_evm_config_emac(void)
 {
        void __iomem *cfg_chip3_base;
@@ -593,12 +643,12 @@ static int __init da850_evm_config_emac(void)
 
        if (rmii_en) {
                val |= BIT(8);
-               ret = davinci_cfg_reg_list(da850_rmii_pins);
+               ret = davinci_cfg_reg_list(da850_evm_rmii_pins);
                pr_info("EMAC: RMII PHY configured, MII PHY will not be"
                                                        " functional\n");
        } else {
                val &= ~BIT(8);
-               ret = davinci_cfg_reg_list(da850_cpgmac_pins);
+               ret = davinci_cfg_reg_list(da850_evm_mii_pins);
                pr_info("EMAC: MII PHY configured, RMII PHY will not be"
                                                        " functional\n");
        }
@@ -625,8 +675,7 @@ static int __init da850_evm_config_emac(void)
        /* Enable/Disable MII MDIO clock */
        gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
 
-       soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY;
+       soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
 
        ret = da8xx_register_emac();
        if (ret)
@@ -787,7 +836,7 @@ static __init void da850_evm_init(void)
        if (ret)
                pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
 
-       ret = da850_register_cpufreq();
+       ret = da850_register_cpufreq("pll0_sysclk3");
        if (ret)
                pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
                                ret);
@@ -806,6 +855,9 @@ static __init void da850_evm_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 static int __init da850_evm_console_init(void)
 {
+       if (!machine_is_davinci_da850_evm())
+               return 0;
+
        return add_preferred_console("ttyS", 2, "115200");
 }
 console_initcall(da850_evm_console_init);
@@ -816,7 +868,7 @@ static void __init da850_evm_map_io(void)
        da850_init();
 }
 
-MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
+MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
        .boot_params    = (DA8XX_DDR_BASE + 0x100),
        .map_io         = da850_evm_map_io,
        .init_irq       = cp_intc_init,
index 944a0cb..c67f684 100644 (file)
@@ -54,9 +54,7 @@ static inline int have_tvp7002(void)
        return 0;
 }
 
-#define DM365_EVM_PHY_MASK             (0x2)
-#define DM365_EVM_MDIO_FREQUENCY       (2200000) /* PHY bus frequency */
-
+#define DM365_EVM_PHY_ID               "0:01"
 /*
  * A MAX-II CPLD is used for various board control functions.
  */
@@ -175,7 +173,9 @@ static struct at24_platform_data eeprom_info = {
        .context        = (void *)0x7f00,
 };
 
-static struct snd_platform_data dm365_evm_snd_data;
+static struct snd_platform_data dm365_evm_snd_data = {
+       .asp_chan_q = EVENTQ_3,
+};
 
 static struct i2c_board_info i2c_info[] = {
        {
@@ -533,8 +533,7 @@ fail:
 
                /* ... and ENET ... */
                dm365evm_emac_configure();
-               soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK;
-               soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY;
+               soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID;
                resets &= ~BIT(3);
 
                /* ... and AIC33 */
index d59fba1..0ca90b8 100644 (file)
 #include <mach/nand.h>
 #include <mach/mmc.h>
 #include <mach/usb.h>
+#include <mach/aemif.h>
 
-#define DM644X_EVM_PHY_MASK            (0x2)
-#define DM644X_EVM_MDIO_FREQUENCY      (2200000) /* PHY bus frequency */
-
+#define DM644X_EVM_PHY_ID              "0:01"
 #define LXT971_PHY_ID  (0x001378e2)
 #define LXT971_PHY_MASK        (0xfffffff0)
 
@@ -137,11 +136,22 @@ static struct mtd_partition davinci_evm_nandflash_partition[] = {
         */
 };
 
+static struct davinci_aemif_timing davinci_evm_nandflash_timing = {
+       .wsetup         = 20,
+       .wstrobe        = 40,
+       .whold          = 20,
+       .rsetup         = 10,
+       .rstrobe        = 40,
+       .rhold          = 10,
+       .ta             = 40,
+};
+
 static struct davinci_nand_pdata davinci_evm_nandflash_data = {
        .parts          = davinci_evm_nandflash_partition,
        .nr_parts       = ARRAY_SIZE(davinci_evm_nandflash_partition),
        .ecc_mode       = NAND_ECC_HW,
        .options        = NAND_USE_FLASH_BBT,
+       .timing         = &davinci_evm_nandflash_timing,
 };
 
 static struct resource davinci_evm_nandflash_resource[] = {
@@ -695,9 +705,7 @@ static __init void davinci_evm_init(void)
        davinci_serial_init(&uart_config);
        dm644x_init_asp(&dm644x_evm_snd_data);
 
-       soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY;
-
+       soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
        /* Register the fixup for PHY on DaVinci */
        phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
                                        davinci_phy_fixup);
index 6890488..f6ac9ba 100644 (file)
@@ -42,6 +42,7 @@
 #include <mach/nand.h>
 #include <mach/clock.h>
 #include <mach/cdce949.h>
+#include <mach/aemif.h>
 
 #include "clock.h"
 
@@ -71,6 +72,16 @@ static struct mtd_partition davinci_nand_partitions[] = {
        }
 };
 
+static struct davinci_aemif_timing dm6467tevm_nandflash_timing = {
+       .wsetup         = 29,
+       .wstrobe        = 24,
+       .whold          = 14,
+       .rsetup         = 19,
+       .rstrobe        = 33,
+       .rhold          = 0,
+       .ta             = 29,
+};
+
 static struct davinci_nand_pdata davinci_nand_data = {
        .mask_cle               = 0x80000,
        .mask_ale               = 0x40000,
@@ -718,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = {
        .enabled_uarts = (1 << 0),
 };
 
-#define DM646X_EVM_PHY_MASK            (0x2)
-#define DM646X_EVM_MDIO_FREQUENCY      (2200000) /* PHY bus frequency */
-
+#define DM646X_EVM_PHY_ID              "0:01"
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
@@ -763,6 +772,9 @@ static __init void evm_init(void)
        dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
        dm646x_init_mcasp1(&dm646x_evm_snd_data[1]);
 
+       if (machine_is_davinci_dm6467tevm())
+               davinci_nand_data.timing = &dm6467tevm_nandflash_timing;
+
        platform_device_register(&davinci_nand_device);
 
        dm646x_init_edma(dm646x_edma_rsv);
@@ -770,8 +782,7 @@ static __init void evm_init(void)
        if (HAS_ATA)
                davinci_init_ide();
 
-       soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY;
+       soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
 }
 
 #define DM646X_EVM_REF_FREQ            27000000
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
new file mode 100644 (file)
index 0000000..0bb5f0c
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Critical Link MityOMAP-L138 SoM
+ *
+ * Copyright (C) 2010 Critical Link LLC - http://www.criticallink.com
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/machine.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/etherdevice.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/common.h>
+#include <mach/cp_intc.h>
+#include <mach/da8xx.h>
+#include <mach/nand.h>
+#include <mach/mux.h>
+
+#define MITYOMAPL138_PHY_ID            "0:03"
+
+#define FACTORY_CONFIG_MAGIC   0x012C0138
+#define FACTORY_CONFIG_VERSION 0x00010001
+
+/* Data Held in On-Board I2C device */
+struct factory_config {
+       u32     magic;
+       u32     version;
+       u8      mac[6];
+       u32     fpga_type;
+       u32     spare;
+       u32     serialnumber;
+       char    partnum[32];
+};
+
+static struct factory_config factory_config;
+
+static void read_factory_config(struct memory_accessor *a, void *context)
+{
+       int ret;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+       ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
+       if (ret != sizeof(struct factory_config)) {
+               pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
+                               ret);
+               return;
+       }
+
+       if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
+               pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
+                               factory_config.magic);
+               return;
+       }
+
+       if (factory_config.version != FACTORY_CONFIG_VERSION) {
+               pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
+                               factory_config.version);
+               return;
+       }
+
+       pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
+       pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum);
+       if (is_valid_ether_addr(factory_config.mac))
+               memcpy(soc_info->emac_pdata->mac_addr,
+                       factory_config.mac, ETH_ALEN);
+       else
+               pr_warning("MityOMAPL138: Invalid MAC found "
+                               "in factory config block\n");
+}
+
+static struct at24_platform_data mityomapl138_fd_chip = {
+       .byte_len       = 256,
+       .page_size      = 8,
+       .flags          = AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
+       .setup          = read_factory_config,
+       .context        = NULL,
+};
+
+static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = {
+       .bus_freq       = 100,  /* kHz */
+       .bus_delay      = 0,    /* usec */
+};
+
+/* TPS65023 voltage regulator support */
+/* 1.2V Core */
+static struct regulator_consumer_supply tps65023_dcdc1_consumers[] = {
+       {
+               .supply = "cvdd",
+       },
+};
+
+/* 1.8V */
+static struct regulator_consumer_supply tps65023_dcdc2_consumers[] = {
+       {
+               .supply = "usb0_vdda18",
+       },
+       {
+               .supply = "usb1_vdda18",
+       },
+       {
+               .supply = "ddr_dvdd18",
+       },
+       {
+               .supply = "sata_vddr",
+       },
+};
+
+/* 1.2V */
+static struct regulator_consumer_supply tps65023_dcdc3_consumers[] = {
+       {
+               .supply = "sata_vdd",
+       },
+       {
+               .supply = "usb_cvdd",
+       },
+       {
+               .supply = "pll0_vdda",
+       },
+       {
+               .supply = "pll1_vdda",
+       },
+};
+
+/* 1.8V Aux LDO, not used */
+static struct regulator_consumer_supply tps65023_ldo1_consumers[] = {
+       {
+               .supply = "1.8v_aux",
+       },
+};
+
+/* FPGA VCC Aux (2.5 or 3.3) LDO */
+static struct regulator_consumer_supply tps65023_ldo2_consumers[] = {
+       {
+               .supply = "vccaux",
+       },
+};
+
+static struct regulator_init_data tps65023_regulator_data[] = {
+       /* dcdc1 */
+       {
+               .constraints = {
+                       .min_uV = 1150000,
+                       .max_uV = 1350000,
+                       .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                                         REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1,
+               },
+               .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers),
+               .consumer_supplies = tps65023_dcdc1_consumers,
+       },
+       /* dcdc2 */
+       {
+               .constraints = {
+                       .min_uV = 1800000,
+                       .max_uV = 1800000,
+                       .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1,
+               },
+               .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers),
+               .consumer_supplies = tps65023_dcdc2_consumers,
+       },
+       /* dcdc3 */
+       {
+               .constraints = {
+                       .min_uV = 1200000,
+                       .max_uV = 1200000,
+                       .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1,
+               },
+               .num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers),
+               .consumer_supplies = tps65023_dcdc3_consumers,
+       },
+       /* ldo1 */
+       {
+               .constraints = {
+                       .min_uV = 1800000,
+                       .max_uV = 1800000,
+                       .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1,
+               },
+               .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers),
+               .consumer_supplies = tps65023_ldo1_consumers,
+       },
+       /* ldo2 */
+       {
+               .constraints = {
+                       .min_uV = 2500000,
+                       .max_uV = 3300000,
+                       .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+                                         REGULATOR_CHANGE_STATUS,
+                       .boot_on = 1,
+               },
+               .num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers),
+               .consumer_supplies = tps65023_ldo2_consumers,
+       },
+};
+
+static struct i2c_board_info __initdata mityomap_tps65023_info[] = {
+       {
+               I2C_BOARD_INFO("tps65023", 0x48),
+               .platform_data = &tps65023_regulator_data[0],
+       },
+       {
+               I2C_BOARD_INFO("24c02", 0x50),
+               .platform_data = &mityomapl138_fd_chip,
+       },
+};
+
+static int __init pmic_tps65023_init(void)
+{
+       return i2c_register_board_info(1, mityomap_tps65023_info,
+                                       ARRAY_SIZE(mityomap_tps65023_info));
+}
+
+/*
+ * MityDSP-L138 includes a 256 MByte large-page NAND flash
+ * (128K blocks).
+ */
+static struct mtd_partition mityomapl138_nandflash_partition[] = {
+       {
+               .name           = "rootfs",
+               .offset         = 0,
+               .size           = SZ_128M,
+               .mask_flags     = 0, /* MTD_WRITEABLE, */
+       },
+       {
+               .name           = "homefs",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+               .mask_flags     = 0,
+       },
+};
+
+static struct davinci_nand_pdata mityomapl138_nandflash_data = {
+       .parts          = mityomapl138_nandflash_partition,
+       .nr_parts       = ARRAY_SIZE(mityomapl138_nandflash_partition),
+       .ecc_mode       = NAND_ECC_HW,
+       .options        = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
+       .ecc_bits       = 1, /* 4 bit mode is not supported with 16 bit NAND */
+};
+
+static struct resource mityomapl138_nandflash_resource[] = {
+       {
+               .start  = DA8XX_AEMIF_CS3_BASE,
+               .end    = DA8XX_AEMIF_CS3_BASE + SZ_512K + 2 * SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device mityomapl138_nandflash_device = {
+       .name           = "davinci_nand",
+       .id             = 0,
+       .dev            = {
+               .platform_data  = &mityomapl138_nandflash_data,
+       },
+       .num_resources  = ARRAY_SIZE(mityomapl138_nandflash_resource),
+       .resource       = mityomapl138_nandflash_resource,
+};
+
+static struct platform_device *mityomapl138_devices[] __initdata = {
+       &mityomapl138_nandflash_device,
+};
+
+static void __init mityomapl138_setup_nand(void)
+{
+       platform_add_devices(mityomapl138_devices,
+                                ARRAY_SIZE(mityomapl138_devices));
+}
+
+static struct davinci_uart_config mityomapl138_uart_config __initdata = {
+       .enabled_uarts = 0x7,
+};
+
+static const short mityomap_mii_pins[] = {
+       DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+       DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+       DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+       DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+       DA850_MDIO_D,
+       -1
+};
+
+static const short mityomap_rmii_pins[] = {
+       DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+       DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
+       DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
+       DA850_MDIO_D,
+       -1
+};
+
+static void __init mityomapl138_config_emac(void)
+{
+       void __iomem *cfg_chip3_base;
+       int ret;
+       u32 val;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+       soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */
+
+       cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+       val = __raw_readl(cfg_chip3_base);
+
+       if (soc_info->emac_pdata->rmii_en) {
+               val |= BIT(8);
+               ret = davinci_cfg_reg_list(mityomap_rmii_pins);
+               pr_info("RMII PHY configured\n");
+       } else {
+               val &= ~BIT(8);
+               ret = davinci_cfg_reg_list(mityomap_mii_pins);
+               pr_info("MII PHY configured\n");
+       }
+
+       if (ret) {
+               pr_warning("mii/rmii mux setup failed: %d\n", ret);
+               return;
+       }
+
+       /* configure the CFGCHIP3 register for RMII or MII */
+       __raw_writel(val, cfg_chip3_base);
+
+       soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID;
+
+       ret = da8xx_register_emac();
+       if (ret)
+               pr_warning("emac registration failed: %d\n", ret);
+}
+
+static struct davinci_pm_config da850_pm_pdata = {
+       .sleepcount = 128,
+};
+
+static struct platform_device da850_pm_device = {
+       .name   = "pm-davinci",
+       .dev = {
+               .platform_data  = &da850_pm_pdata,
+       },
+       .id     = -1,
+};
+
+static void __init mityomapl138_init(void)
+{
+       int ret;
+
+       /* for now, no special EDMA channels are reserved */
+       ret = da850_register_edma(NULL);
+       if (ret)
+               pr_warning("edma registration failed: %d\n", ret);
+
+       ret = da8xx_register_watchdog();
+       if (ret)
+               pr_warning("watchdog registration failed: %d\n", ret);
+
+       davinci_serial_init(&mityomapl138_uart_config);
+
+       ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata);
+       if (ret)
+               pr_warning("i2c0 registration failed: %d\n", ret);
+
+       ret = pmic_tps65023_init();
+       if (ret)
+               pr_warning("TPS65023 PMIC init failed: %d\n", ret);
+
+       mityomapl138_setup_nand();
+
+       mityomapl138_config_emac();
+
+       ret = da8xx_register_rtc();
+       if (ret)
+               pr_warning("rtc setup failed: %d\n", ret);
+
+       ret = da850_register_cpufreq("pll0_sysclk3");
+       if (ret)
+               pr_warning("cpufreq registration failed: %d\n", ret);
+
+       ret = da8xx_register_cpuidle();
+       if (ret)
+               pr_warning("cpuidle registration failed: %d\n", ret);
+
+       ret = da850_register_pm(&da850_pm_device);
+       if (ret)
+               pr_warning("da850_evm_init: suspend registration failed: %d\n",
+                               ret);
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static int __init mityomapl138_console_init(void)
+{
+       if (!machine_is_mityomapl138())
+               return 0;
+
+       return add_preferred_console("ttyS", 1, "115200");
+}
+console_initcall(mityomapl138_console_init);
+#endif
+
+static void __init mityomapl138_map_io(void)
+{
+       da850_init();
+}
+
+MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
+       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .map_io         = mityomapl138_map_io,
+       .init_irq       = cp_intc_init,
+       .timer          = &davinci_timer,
+       .init_machine   = mityomapl138_init,
+MACHINE_END
index a4def88..6c389ff 100644 (file)
@@ -39,9 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
-#define NEUROS_OSD2_PHY_MASK           0x2
-#define NEUROS_OSD2_MDIO_FREQUENCY     2200000 /* PHY bus frequency */
-
+#define NEUROS_OSD2_PHY_ID             "0:01"
 #define LXT971_PHY_ID                  0x001378e2
 #define LXT971_PHY_MASK                        0xfffffff0
 
@@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void)
        davinci_serial_init(&uart_config);
        dm644x_init_asp(&dm644x_ntosd2_snd_data);
 
-       soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY;
+       soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
 
        davinci_setup_usb(1000, 8);
        /*
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
new file mode 100644 (file)
index 0000000..0b8dbdb
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Hawkboard.org based on TI's OMAP-L138 Platform
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/cp_intc.h>
+#include <mach/da8xx.h>
+
+static struct davinci_uart_config omapl138_hawk_uart_config __initdata = {
+       .enabled_uarts = 0x7,
+};
+
+static __init void omapl138_hawk_init(void)
+{
+       int ret;
+
+       davinci_serial_init(&omapl138_hawk_uart_config);
+
+       ret = da8xx_register_watchdog();
+       if (ret)
+               pr_warning("omapl138_hawk_init: "
+                       "watchdog registration failed: %d\n",
+                       ret);
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static int __init omapl138_hawk_console_init(void)
+{
+       if (!machine_is_omapl138_hawkboard())
+               return 0;
+
+       return add_preferred_console("ttyS", 2, "115200");
+}
+console_initcall(omapl138_hawk_console_init);
+#endif
+
+static void __init omapl138_hawk_map_io(void)
+{
+       da850_init();
+}
+
+MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
+       .boot_params    = (DA8XX_DDR_BASE + 0x100),
+       .map_io         = omapl138_hawk_map_io,
+       .init_irq       = cp_intc_init,
+       .timer          = &davinci_timer,
+       .init_machine   = omapl138_hawk_init,
+MACHINE_END
index 9bdf8aa..61ac96d 100644 (file)
@@ -42,9 +42,7 @@
 #include <mach/mux.h>
 #include <mach/usb.h>
 
-#define SFFSDR_PHY_MASK                (0x2)
-#define SFFSDR_MDIO_FREQUENCY  (2200000) /* PHY bus frequency */
-
+#define SFFSDR_PHY_ID          "0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
        /* U-Boot Environment: Block 0
         * UBL:                Block 1
@@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void)
                             ARRAY_SIZE(davinci_sffsdr_devices));
        sffsdr_init_i2c();
        davinci_serial_init(&uart_config);
-       soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK;
-       soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY;
+       soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID;
        davinci_setup_usb(0, 0); /* We support only peripheral mode. */
 
        /* mux VLYNQ pins */
index b4de35b..a6db854 100644 (file)
@@ -23,6 +23,9 @@
 #include <linux/ratelimit.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
@@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = {
        .enabled_uarts  = BIT(1),
 };
 
+static const uint32_t keymap[] = {
+       KEY(0, 0, KEY_NUMERIC_1),
+       KEY(0, 1, KEY_NUMERIC_2),
+       KEY(0, 2, KEY_NUMERIC_3),
+       KEY(0, 3, KEY_FN_F1),
+       KEY(0, 4, KEY_MENU),
+
+       KEY(1, 0, KEY_NUMERIC_4),
+       KEY(1, 1, KEY_NUMERIC_5),
+       KEY(1, 2, KEY_NUMERIC_6),
+       KEY(1, 3, KEY_UP),
+       KEY(1, 4, KEY_FN_F2),
+
+       KEY(2, 0, KEY_NUMERIC_7),
+       KEY(2, 1, KEY_NUMERIC_8),
+       KEY(2, 2, KEY_NUMERIC_9),
+       KEY(2, 3, KEY_LEFT),
+       KEY(2, 4, KEY_ENTER),
+
+       KEY(3, 0, KEY_NUMERIC_STAR),
+       KEY(3, 1, KEY_NUMERIC_0),
+       KEY(3, 2, KEY_NUMERIC_POUND),
+       KEY(3, 3, KEY_DOWN),
+       KEY(3, 4, KEY_RIGHT),
+
+       KEY(4, 0, KEY_FN_F3),
+       KEY(4, 1, KEY_FN_F4),
+       KEY(4, 2, KEY_MUTE),
+       KEY(4, 3, KEY_HOME),
+       KEY(4, 4, KEY_BACK),
+
+       KEY(5, 0, KEY_VOLUMEDOWN),
+       KEY(5, 1, KEY_VOLUMEUP),
+       KEY(5, 2, KEY_F1),
+       KEY(5, 3, KEY_F2),
+       KEY(5, 4, KEY_F3),
+};
+
+static const struct matrix_keymap_data keymap_data = {
+       .keymap         = keymap,
+       .keymap_size    = ARRAY_SIZE(keymap),
+};
+
+static struct matrix_keypad_platform_data keypad_config = {
+       .keymap_data    = &keymap_data,
+       .num_row_gpios  = 6,
+       .num_col_gpios  = 5,
+       .debounce_ms    = 0, /* minimum */
+       .active_low     = 0, /* pull up realization */
+       .no_autorepeat  = 0,
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
        .serial_config          = &serial_config,
        .mmc_config[1]          = &mmc_config,  /* controller 1 */
        .nand_config[0]         = &nand_config, /* chip select 0 */
+       .keypad_config          = &keypad_config,
 };
 
 static __init void tnetv107x_evm_board_init(void)
index 054c303..01ba080 100644 (file)
@@ -236,7 +236,7 @@ static int __init clk_disable_unused(void)
                if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
                        continue;
 
-               pr_info("Clocks: disable unused %s\n", ck->name);
+               pr_debug("Clocks: disable unused %s\n", ck->name);
 
                davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
                                (ck->flags & PSC_SWRSTDISABLE) ?
@@ -287,6 +287,79 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
        return rate;
 }
 
+int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
+{
+       unsigned v;
+       struct pll_data *pll;
+       unsigned long input;
+       unsigned ratio = 0;
+
+       /* If this is the PLL base clock, wrong function to call */
+       if (clk->pll_data)
+               return -EINVAL;
+
+       /* There must be a parent... */
+       if (WARN_ON(!clk->parent))
+               return -EINVAL;
+
+       /* ... the parent must be a PLL... */
+       if (WARN_ON(!clk->parent->pll_data))
+               return -EINVAL;
+
+       /* ... and this clock must have a divider. */
+       if (WARN_ON(!clk->div_reg))
+               return -EINVAL;
+
+       pll = clk->parent->pll_data;
+
+       input = clk->parent->rate;
+
+       /* If pre-PLL, source clock is before the multiplier and divider(s) */
+       if (clk->flags & PRE_PLL)
+               input = pll->input_rate;
+
+       if (input > rate) {
+               /*
+                * Can afford to provide an output little higher than requested
+                * only if maximum rate supported by hardware on this sysclk
+                * is known.
+                */
+               if (clk->maxrate) {
+                       ratio = DIV_ROUND_CLOSEST(input, rate);
+                       if (input / ratio > clk->maxrate)
+                               ratio = 0;
+               }
+
+               if (ratio == 0)
+                       ratio = DIV_ROUND_UP(input, rate);
+
+               ratio--;
+       }
+
+       if (ratio > PLLDIV_RATIO_MASK)
+               return -EINVAL;
+
+       do {
+               v = __raw_readl(pll->base + PLLSTAT);
+       } while (v & PLLSTAT_GOSTAT);
+
+       v = __raw_readl(pll->base + clk->div_reg);
+       v &= ~PLLDIV_RATIO_MASK;
+       v |= ratio | PLLDIV_EN;
+       __raw_writel(v, pll->base + clk->div_reg);
+
+       v = __raw_readl(pll->base + PLLCMD);
+       v |= PLLCMD_GOSET;
+       __raw_writel(v, pll->base + PLLCMD);
+
+       do {
+               v = __raw_readl(pll->base + PLLSTAT);
+       } while (v & PLLSTAT_GOSTAT);
+
+       return 0;
+}
+EXPORT_SYMBOL(davinci_set_sysclk_rate);
+
 static unsigned long clk_leafclk_recalc(struct clk *clk)
 {
        if (WARN_ON(!clk->parent))
index 01e3648..1109998 100644 (file)
@@ -70,6 +70,9 @@
 #include <linux/list.h>
 #include <asm/clkdev.h>
 
+#define PLLSTAT_GOSTAT BIT(0)
+#define PLLCMD_GOSET   BIT(0)
+
 struct pll_data {
        u32 phys_base;
        void __iomem *base;
@@ -86,6 +89,7 @@ struct clk {
        struct module           *owner;
        const char              *name;
        unsigned long           rate;
+       unsigned long           maxrate;        /* H/W supported max rate */
        u8                      usecount;
        u8                      lpsc;
        u8                      gpsc;
@@ -118,6 +122,7 @@ struct clk {
 int davinci_clk_init(struct clk_lookup *clocks);
 int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
                                unsigned int mult, unsigned int postdiv);
+int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
 
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
index d3fa6de..343de73 100644 (file)
@@ -34,6 +34,8 @@
 struct davinci_cpufreq {
        struct device *dev;
        struct clk *armclk;
+       struct clk *asyncclk;
+       unsigned long asyncrate;
 };
 static struct davinci_cpufreq cpufreq;
 
@@ -104,15 +106,27 @@ static int davinci_target(struct cpufreq_policy *policy,
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
        /* if moving to higher frequency, up the voltage beforehand */
-       if (pdata->set_voltage && freqs.new > freqs.old)
-               pdata->set_voltage(idx);
+       if (pdata->set_voltage && freqs.new > freqs.old) {
+               ret = pdata->set_voltage(idx);
+               if (ret)
+                       goto out;
+       }
 
        ret = clk_set_rate(armclk, idx);
+       if (ret)
+               goto out;
+
+       if (cpufreq.asyncclk) {
+               ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
+               if (ret)
+                       goto out;
+       }
 
        /* if moving to lower freq, lower the voltage after lowering freq */
        if (pdata->set_voltage && freqs.new < freqs.old)
                pdata->set_voltage(idx);
 
+out:
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
        return ret;
@@ -185,6 +199,7 @@ static struct cpufreq_driver davinci_driver = {
 static int __init davinci_cpufreq_probe(struct platform_device *pdev)
 {
        struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
+       struct clk *asyncclk;
 
        if (!pdata)
                return -EINVAL;
@@ -199,6 +214,12 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev)
                return PTR_ERR(cpufreq.armclk);
        }
 
+       asyncclk = clk_get(cpufreq.dev, "async");
+       if (!IS_ERR(asyncclk)) {
+               cpufreq.asyncclk = asyncclk;
+               cpufreq.asyncrate = clk_get_rate(asyncclk);
+       }
+
        return cpufreq_register_driver(&davinci_driver);
 }
 
@@ -206,6 +227,9 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev)
 {
        clk_put(cpufreq.armclk);
 
+       if (cpufreq.asyncclk)
+               clk_put(cpufreq.asyncclk);
+
        return cpufreq_unregister_driver(&davinci_driver);
 }
 
index 68ed58a..63916b9 100644 (file)
@@ -86,6 +86,8 @@ static struct clk pll0_sysclk3 = {
        .parent         = &pll0_clk,
        .flags          = CLK_PLL,
        .div_reg        = PLLDIV3,
+       .set_rate       = davinci_set_sysclk_rate,
+       .maxrate        = 100000000,
 };
 
 static struct clk pll0_sysclk4 = {
@@ -323,12 +325,19 @@ static struct clk lcdc_clk = {
        .gpsc           = 1,
 };
 
-static struct clk mmcsd_clk = {
-       .name           = "mmcsd",
+static struct clk mmcsd0_clk = {
+       .name           = "mmcsd0",
        .parent         = &pll0_sysclk2,
        .lpsc           = DA8XX_LPSC0_MMC_SD,
 };
 
+static struct clk mmcsd1_clk = {
+       .name           = "mmcsd1",
+       .parent         = &pll0_sysclk2,
+       .lpsc           = DA850_LPSC1_MMC_SD1,
+       .gpsc           = 1,
+};
+
 static struct clk aemif_clk = {
        .name           = "aemif",
        .parent         = &pll0_sysclk3,
@@ -375,7 +384,8 @@ static struct clk_lookup da850_clks[] = {
        CLK("davinci_emac.1",   NULL,           &emac_clk),
        CLK("davinci-mcasp.0",  NULL,           &mcasp_clk),
        CLK("da8xx_lcdc.0",     NULL,           &lcdc_clk),
-       CLK("davinci_mmc.0",    NULL,           &mmcsd_clk),
+       CLK("davinci_mmc.0",    NULL,           &mmcsd0_clk),
+       CLK("davinci_mmc.1",    NULL,           &mmcsd1_clk),
        CLK(NULL,               "aemif",        &aemif_clk),
        CLK(NULL,               NULL,           NULL),
 };
@@ -572,15 +582,9 @@ const short da850_cpgmac_pins[] __initdata = {
        DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
        DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
        DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
-       DA850_MDIO_D,
-       -1
-};
-
-const short da850_rmii_pins[] __initdata = {
-       DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
-       DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
-       DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
-       DA850_MDIO_D,
+       DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+       DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER,
+       DA850_RMII_MHZ_50_CLK,
        -1
 };
 
@@ -607,27 +611,19 @@ const short da850_mmcsd0_pins[] __initdata = {
        -1
 };
 
-const short da850_nand_pins[] __initdata = {
-       DA850_EMA_D_7, DA850_EMA_D_6, DA850_EMA_D_5, DA850_EMA_D_4,
-       DA850_EMA_D_3, DA850_EMA_D_2, DA850_EMA_D_1, DA850_EMA_D_0,
-       DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
-       DA850_NEMA_WE, DA850_NEMA_OE,
-       -1
-};
-
-const short da850_nor_pins[] __initdata = {
+const short da850_emif25_pins[] __initdata = {
        DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
-       DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
-       DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
-       DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
-       DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
-       DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
-       DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
-       DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
-       DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
-       DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
-       DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
-       DA850_EMA_A_22, DA850_EMA_A_23,
+       DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE,
+       DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
+       DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
+       DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
+       DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
+       DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3,
+       DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7,
+       DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11,
+       DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15,
+       DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19,
+       DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23,
        -1
 };
 
@@ -851,7 +847,7 @@ static const struct da850_opp da850_opp_300 = {
        .prediv         = 1,
        .mult           = 25,
        .postdiv        = 2,
-       .cvdd_min       = 1140000,
+       .cvdd_min       = 1200000,
        .cvdd_max       = 1320000,
 };
 
@@ -860,7 +856,7 @@ static const struct da850_opp da850_opp_200 = {
        .prediv         = 1,
        .mult           = 25,
        .postdiv        = 3,
-       .cvdd_min       = 1050000,
+       .cvdd_min       = 1100000,
        .cvdd_max       = 1160000,
 };
 
@@ -869,7 +865,7 @@ static const struct da850_opp da850_opp_96 = {
        .prediv         = 1,
        .mult           = 20,
        .postdiv        = 5,
-       .cvdd_min       = 950000,
+       .cvdd_min       = 1000000,
        .cvdd_max       = 1050000,
 };
 
@@ -929,10 +925,16 @@ static struct platform_device da850_cpufreq_device = {
        .dev = {
                .platform_data  = &cpufreq_info,
        },
+       .id = -1,
 };
 
-int __init da850_register_cpufreq(void)
+int __init da850_register_cpufreq(char *async_clk)
 {
+       /* cpufreq driver can help keep an "async" clock constant */
+       if (async_clk)
+               clk_add_alias("async", da850_cpufreq_device.name,
+                                                       async_clk, NULL);
+
        return platform_device_register(&da850_cpufreq_device);
 }
 
@@ -983,7 +985,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
        return 0;
 }
 #else
-int __init da850_register_cpufreq(void)
+int __init da850_register_cpufreq(char *async_clk)
 {
        return 0;
 }
index 52bc7b1..9eec630 100644 (file)
@@ -24,6 +24,7 @@
 #include "clock.h"
 
 #define DA8XX_TPCC_BASE                        0x01c00000
+#define DA850_MMCSD1_BASE              0x01e1b000
 #define DA850_TPCC1_BASE               0x01e30000
 #define DA8XX_TPTC0_BASE               0x01c08000
 #define DA8XX_TPTC1_BASE               0x01c08400
@@ -41,7 +42,6 @@
 #define DA8XX_EMAC_CTRL_REG_OFFSET     0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET      0x2000
 #define DA8XX_EMAC_RAM_OFFSET          0x0000
-#define DA8XX_MDIO_REG_OFFSET          0x4000
 #define DA8XX_EMAC_CTRL_RAM_SIZE       SZ_8K
 
 void __iomem *da8xx_syscfg0_base;
@@ -351,7 +351,7 @@ int __init da8xx_register_watchdog(void)
 static struct resource da8xx_emac_resources[] = {
        {
                .start  = DA8XX_EMAC_CPPI_PORT_BASE,
-               .end    = DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1,
+               .end    = DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -380,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = {
        .ctrl_reg_offset        = DA8XX_EMAC_CTRL_REG_OFFSET,
        .ctrl_mod_reg_offset    = DA8XX_EMAC_MOD_REG_OFFSET,
        .ctrl_ram_offset        = DA8XX_EMAC_RAM_OFFSET,
-       .mdio_reg_offset        = DA8XX_MDIO_REG_OFFSET,
        .ctrl_ram_size          = DA8XX_EMAC_CTRL_RAM_SIZE,
        .version                = EMAC_VERSION_2,
 };
@@ -395,9 +394,34 @@ static struct platform_device da8xx_emac_device = {
        .resource       = da8xx_emac_resources,
 };
 
+static struct resource da8xx_mdio_resources[] = {
+       {
+               .start  = DA8XX_EMAC_MDIO_BASE,
+               .end    = DA8XX_EMAC_MDIO_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device da8xx_mdio_device = {
+       .name           = "davinci_mdio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(da8xx_mdio_resources),
+       .resource       = da8xx_mdio_resources,
+};
+
 int __init da8xx_register_emac(void)
 {
-       return platform_device_register(&da8xx_emac_device);
+       int ret;
+
+       ret = platform_device_register(&da8xx_mdio_device);
+       if (ret < 0)
+               return ret;
+       ret = platform_device_register(&da8xx_emac_device);
+       if (ret < 0)
+               return ret;
+       ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev),
+                           NULL, &da8xx_emac_device.dev);
+       return ret;
 }
 
 static struct resource da830_mcasp1_resources[] = {
@@ -566,6 +590,44 @@ int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config)
        return platform_device_register(&da8xx_mmcsd0_device);
 }
 
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+static struct resource da850_mmcsd1_resources[] = {
+       {               /* registers */
+               .start  = DA850_MMCSD1_BASE,
+               .end    = DA850_MMCSD1_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {               /* interrupt */
+               .start  = IRQ_DA850_MMCSDINT0_1,
+               .end    = IRQ_DA850_MMCSDINT0_1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {               /* DMA RX */
+               .start  = EDMA_CTLR_CHAN(1, 28),
+               .end    = EDMA_CTLR_CHAN(1, 28),
+               .flags  = IORESOURCE_DMA,
+       },
+       {               /* DMA TX */
+               .start  = EDMA_CTLR_CHAN(1, 29),
+               .end    = EDMA_CTLR_CHAN(1, 29),
+               .flags  = IORESOURCE_DMA,
+       },
+};
+
+static struct platform_device da850_mmcsd1_device = {
+       .name           = "davinci_mmc",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(da850_mmcsd1_resources),
+       .resource       = da850_mmcsd1_resources,
+};
+
+int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
+{
+       da850_mmcsd1_device.dev.platform_data = config;
+       return platform_device_register(&da850_mmcsd1_device);
+}
+#endif
+
 static struct resource da8xx_rtc_resources[] = {
        {
                .start          = DA8XX_RTC_BASE,
index 2718a3a..c9a86d8 100644 (file)
 #define TNETV107X_TPTC0_BASE                   0x01c10000
 #define TNETV107X_TPTC1_BASE                   0x01c10400
 #define TNETV107X_WDOG_BASE                    0x08086700
+#define TNETV107X_TSC_BASE                     0x08088500
 #define TNETV107X_SDIO0_BASE                   0x08088700
 #define TNETV107X_SDIO1_BASE                   0x08088800
+#define TNETV107X_KEYPAD_BASE                  0x08088a00
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE                0x08200000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE     0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE     0x40000000
@@ -298,12 +300,55 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data)
        return platform_device_register(pdev);
 }
 
+static struct resource keypad_resources[] = {
+       {
+               .start  = TNETV107X_KEYPAD_BASE,
+               .end    = TNETV107X_KEYPAD_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_TNETV107X_KEYPAD,
+               .flags  = IORESOURCE_IRQ,
+               .name   = "press",
+       },
+       {
+               .start  = IRQ_TNETV107X_KEYPAD_FREE,
+               .flags  = IORESOURCE_IRQ,
+               .name   = "release",
+       },
+};
+
+static struct platform_device keypad_device = {
+       .name           = "tnetv107x-keypad",
+       .num_resources  = ARRAY_SIZE(keypad_resources),
+       .resource       = keypad_resources,
+};
+
+static struct resource tsc_resources[] = {
+       {
+               .start  = TNETV107X_TSC_BASE,
+               .end    = TNETV107X_TSC_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_TNETV107X_TSC,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device tsc_device = {
+       .name           = "tnetv107x-ts",
+       .num_resources  = ARRAY_SIZE(tsc_resources),
+       .resource       = tsc_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
        int i;
 
        platform_device_register(&edma_device);
        platform_device_register(&tnetv107x_wdt_device);
+       platform_device_register(&tsc_device);
 
        if (info->serial_config)
                davinci_serial_init(info->serial_config);
@@ -317,4 +362,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
        for (i = 0; i < 4; i++)
                if (info->nand_config[i])
                        nand_init(i, info->nand_config[i]);
+
+       if (info->keypad_config) {
+               keypad_device.dev.platform_data = info->keypad_config;
+               platform_device_register(&keypad_device);
+       }
 }
index 8b7201e..22ebc64 100644 (file)
@@ -213,7 +213,7 @@ void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
                                IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c);
 
                        /* Configure pull down control */
-                       __raw_writel((__raw_readl(pupdctl1) & ~0x400),
+                       __raw_writel((__raw_readl(pupdctl1) & ~0xfc0),
                                        pupdctl1);
 
                        mmcsd1_resources[0].start = DM365_MMCSD1_BASE;
@@ -295,6 +295,18 @@ static void davinci_init_wdt(void)
 
 /*-------------------------------------------------------------------------*/
 
+struct platform_device davinci_pcm_device = {
+       .name           = "davinci-pcm-audio",
+       .id             = -1,
+};
+
+static void davinci_init_pcm(void)
+{
+       platform_device_register(&davinci_pcm_device);
+}
+
+/*-------------------------------------------------------------------------*/
+
 struct davinci_timer_instance davinci_timer_instance[2] = {
        {
                .base           = DAVINCI_TIMER0_BASE,
@@ -315,6 +327,7 @@ static int __init davinci_init_devices(void)
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
+       davinci_init_pcm();
        davinci_init_wdt();
 
        return 0;
index 7781e35..a12065e 100644 (file)
@@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = {
        .ctrl_reg_offset        = DM365_EMAC_CNTRL_OFFSET,
        .ctrl_mod_reg_offset    = DM365_EMAC_CNTRL_MOD_OFFSET,
        .ctrl_ram_offset        = DM365_EMAC_CNTRL_RAM_OFFSET,
-       .mdio_reg_offset        = DM365_EMAC_MDIO_OFFSET,
        .ctrl_ram_size          = DM365_EMAC_CNTRL_RAM_SIZE,
        .version                = EMAC_VERSION_2,
 };
@@ -699,7 +698,7 @@ static struct emac_platform_data dm365_emac_pdata = {
 static struct resource dm365_emac_resources[] = {
        {
                .start  = DM365_EMAC_BASE,
-               .end    = DM365_EMAC_BASE + 0x47ff,
+               .end    = DM365_EMAC_BASE + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -734,6 +733,21 @@ static struct platform_device dm365_emac_device = {
        .resource       = dm365_emac_resources,
 };
 
+static struct resource dm365_mdio_resources[] = {
+       {
+               .start  = DM365_EMAC_MDIO_BASE,
+               .end    = DM365_EMAC_MDIO_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm365_mdio_device = {
+       .name           = "davinci_mdio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(dm365_mdio_resources),
+       .resource       = dm365_mdio_resources,
+};
+
 static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
        [IRQ_VDINT0]                    = 2,
        [IRQ_VDINT1]                    = 6,
@@ -1219,7 +1233,12 @@ static int __init dm365_init_devices(void)
 
        davinci_cfg_reg(DM365_INT_EDMA_CC);
        platform_device_register(&dm365_edma_device);
+
+       platform_device_register(&dm365_mdio_device);
        platform_device_register(&dm365_emac_device);
+       clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev),
+                     NULL, &dm365_emac_device.dev);
+
        /* Add isif clock alias */
        clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
        platform_device_register(&dm365_vpss_device);
index 5e5b0a7..0608dd7 100644 (file)
@@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = {
        .ctrl_reg_offset        = DM644X_EMAC_CNTRL_OFFSET,
        .ctrl_mod_reg_offset    = DM644X_EMAC_CNTRL_MOD_OFFSET,
        .ctrl_ram_offset        = DM644X_EMAC_CNTRL_RAM_OFFSET,
-       .mdio_reg_offset        = DM644X_EMAC_MDIO_OFFSET,
        .ctrl_ram_size          = DM644X_EMAC_CNTRL_RAM_SIZE,
        .version                = EMAC_VERSION_1,
 };
@@ -330,7 +329,7 @@ static struct emac_platform_data dm644x_emac_pdata = {
 static struct resource dm644x_emac_resources[] = {
        {
                .start  = DM644X_EMAC_BASE,
-               .end    = DM644X_EMAC_BASE + 0x47ff,
+               .end    = DM644X_EMAC_BASE + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -350,6 +349,21 @@ static struct platform_device dm644x_emac_device = {
        .resource       = dm644x_emac_resources,
 };
 
+static struct resource dm644x_mdio_resources[] = {
+       {
+               .start  = DM644X_EMAC_MDIO_BASE,
+               .end    = DM644X_EMAC_MDIO_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm644x_mdio_device = {
+       .name           = "davinci_mdio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(dm644x_mdio_resources),
+       .resource       = dm644x_mdio_resources,
+};
+
 /*
  * Device specific mux setup
  *
@@ -776,7 +790,12 @@ static int __init dm644x_init_devices(void)
        clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
        clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
        platform_device_register(&dm644x_edma_device);
+
+       platform_device_register(&dm644x_mdio_device);
        platform_device_register(&dm644x_emac_device);
+       clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev),
+                     NULL, &dm644x_emac_device.dev);
+
        platform_device_register(&dm644x_vpss_device);
        platform_device_register(&dm644x_ccdc_dev);
        platform_device_register(&vpfe_capture_dev);
index 26e8a9c..1e0f809 100644 (file)
@@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = {
        .ctrl_reg_offset        = DM646X_EMAC_CNTRL_OFFSET,
        .ctrl_mod_reg_offset    = DM646X_EMAC_CNTRL_MOD_OFFSET,
        .ctrl_ram_offset        = DM646X_EMAC_CNTRL_RAM_OFFSET,
-       .mdio_reg_offset        = DM646X_EMAC_MDIO_OFFSET,
        .ctrl_ram_size          = DM646X_EMAC_CNTRL_RAM_SIZE,
        .version                = EMAC_VERSION_2,
 };
@@ -366,7 +365,7 @@ static struct emac_platform_data dm646x_emac_pdata = {
 static struct resource dm646x_emac_resources[] = {
        {
                .start  = DM646X_EMAC_BASE,
-               .end    = DM646X_EMAC_BASE + 0x47ff,
+               .end    = DM646X_EMAC_BASE + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -401,6 +400,21 @@ static struct platform_device dm646x_emac_device = {
        .resource       = dm646x_emac_resources,
 };
 
+static struct resource dm646x_mdio_resources[] = {
+       {
+               .start  = DM646X_EMAC_MDIO_BASE,
+               .end    = DM646X_EMAC_MDIO_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm646x_mdio_device = {
+       .name           = "davinci_mdio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(dm646x_mdio_resources),
+       .resource       = dm646x_mdio_resources,
+};
+
 /*
  * Device specific mux setup
  *
@@ -896,7 +910,11 @@ static int __init dm646x_init_devices(void)
        if (!cpu_is_davinci_dm646x())
                return 0;
 
+       platform_device_register(&dm646x_mdio_device);
        platform_device_register(&dm646x_emac_device);
+       clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev),
+                     NULL, &dm646x_emac_device.dev);
+
        return 0;
 }
 postcore_initcall(dm646x_init_devices);
index 2ede598..6b96698 100644 (file)
@@ -354,10 +354,12 @@ static int irq2ctlr(int irq)
 static irqreturn_t dma_irq_handler(int irq, void *data)
 {
        int i;
-       unsigned ctlr;
+       int ctlr;
        unsigned int cnt = 0;
 
        ctlr = irq2ctlr(irq);
+       if (ctlr < 0)
+               return IRQ_NONE;
 
        dev_dbg(data, "dma_irq_handler\n");
 
@@ -408,10 +410,12 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
 static irqreturn_t dma_ccerr_handler(int irq, void *data)
 {
        int i;
-       unsigned ctlr;
+       int ctlr;
        unsigned int cnt = 0;
 
        ctlr = irq2ctlr(irq);
+       if (ctlr < 0)
+               return IRQ_NONE;
 
        dev_dbg(data, "dma_ccerr_handler\n");
 
diff --git a/arch/arm/mach-davinci/include/mach/aemif.h b/arch/arm/mach-davinci/include/mach/aemif.h
new file mode 100644 (file)
index 0000000..05b2934
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * TI DaVinci AEMIF support
+ *
+ * Copyright 2010 (C) Texas Instruments, Inc. http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+#ifndef _MACH_DAVINCI_AEMIF_H
+#define _MACH_DAVINCI_AEMIF_H
+
+#define NRCSR_OFFSET           0x00
+#define AWCCR_OFFSET           0x04
+#define A1CR_OFFSET            0x10
+
+#define ACR_ASIZE_MASK         0x3
+#define ACR_EW_MASK            BIT(30)
+#define ACR_SS_MASK            BIT(31)
+
+/* All timings in nanoseconds */
+struct davinci_aemif_timing {
+       u8      wsetup;
+       u8      wstrobe;
+       u8      whold;
+
+       u8      rsetup;
+       u8      rstrobe;
+       u8      rhold;
+
+       u8      ta;
+};
+
+int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+                                       void __iomem *base, unsigned cs);
+#endif
index 3c07059..4247b3f 100644 (file)
@@ -76,9 +76,10 @@ int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
 int da8xx_register_emac(void);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
 int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
+int da850_register_mmcsd1(struct davinci_mmc_config *config);
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
 int da8xx_register_rtc(void);
-int da850_register_cpufreq(void);
+int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
@@ -121,11 +122,9 @@ extern const short da850_uart2_pins[];
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
 extern const short da850_cpgmac_pins[];
-extern const short da850_rmii_pins[];
 extern const short da850_mcasp_pins[];
 extern const short da850_lcdcntl_pins[];
 extern const short da850_mmcsd0_pins[];
-extern const short da850_nand_pins[];
-extern const short da850_nor_pins[];
+extern const short da850_emif25_pins[];
 
 #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
index ea5df3b..2563bf4 100644 (file)
 #include <media/davinci/vpfe_capture.h>
 
 #define DM365_EMAC_BASE                        (0x01D07000)
+#define DM365_EMAC_MDIO_BASE           (DM365_EMAC_BASE + 0x4000)
 #define DM365_EMAC_CNTRL_OFFSET                (0x0000)
 #define DM365_EMAC_CNTRL_MOD_OFFSET    (0x3000)
 #define DM365_EMAC_CNTRL_RAM_OFFSET    (0x1000)
-#define DM365_EMAC_MDIO_OFFSET         (0x4000)
 #define DM365_EMAC_CNTRL_RAM_SIZE      (0x2000)
 
 /* Base of key scan register bank */
index 6fca568..5a1b26d 100644 (file)
 #include <media/davinci/vpfe_capture.h>
 
 #define DM644X_EMAC_BASE               (0x01C80000)
+#define DM644X_EMAC_MDIO_BASE          (DM644X_EMAC_BASE + 0x4000)
 #define DM644X_EMAC_CNTRL_OFFSET       (0x0000)
 #define DM644X_EMAC_CNTRL_MOD_OFFSET   (0x1000)
 #define DM644X_EMAC_CNTRL_RAM_OFFSET   (0x2000)
-#define DM644X_EMAC_MDIO_OFFSET                (0x4000)
 #define DM644X_EMAC_CNTRL_RAM_SIZE     (0x2000)
 
 #define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000
index 0a27ee9..7a27f3f 100644 (file)
 #include <linux/davinci_emac.h>
 
 #define DM646X_EMAC_BASE               (0x01C80000)
+#define DM646X_EMAC_MDIO_BASE          (DM646X_EMAC_BASE + 0x4000)
 #define DM646X_EMAC_CNTRL_OFFSET       (0x0000)
 #define DM646X_EMAC_CNTRL_MOD_OFFSET   (0x1000)
 #define DM646X_EMAC_CNTRL_RAM_OFFSET   (0x2000)
-#define DM646X_EMAC_MDIO_OFFSET                (0x4000)
 #define DM646X_EMAC_CNTRL_RAM_SIZE     (0x2000)
 
 #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000
index b2ad809..0251510 100644 (file)
@@ -30,9 +30,6 @@
 
 #include <linux/mtd/nand.h>
 
-#define NRCSR_OFFSET           0x00
-#define AWCCR_OFFSET           0x04
-#define A1CR_OFFSET            0x10
 #define NANDFCR_OFFSET         0x60
 #define NANDFSR_OFFSET         0x64
 #define NANDF1ECC_OFFSET       0x70
@@ -83,6 +80,9 @@ struct davinci_nand_pdata {           /* platform_data */
        /* Main and mirror bbt descriptor overrides */
        struct nand_bbt_descr   *bbt_td;
        struct nand_bbt_descr   *bbt_md;
+
+       /* Access timings */
+       struct davinci_aemif_timing     *timing;
 };
 
 #endif /* __ARCH_ARM_DAVINCI_NAND_H */
index 983da6e..62b0858 100644 (file)
 #define DA8XX_LPSC1_UART2              13
 #define DA8XX_LPSC1_LCDC               16
 #define DA8XX_LPSC1_PWM                        17
+#define DA850_LPSC1_MMC_SD1            18
 #define DA8XX_LPSC1_ECAP               20
 #define DA830_LPSC1_EQEP               21
 #define DA850_LPSC1_TPTC2              21
index c720647..5a681d8 100644 (file)
@@ -33,6 +33,8 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/serial_8250.h>
+#include <linux/input/matrix_keypad.h>
+
 #include <mach/mmc.h>
 #include <mach/nand.h>
 #include <mach/serial.h>
@@ -41,6 +43,7 @@ struct tnetv107x_device_info {
        struct davinci_uart_config      *serial_config;
        struct davinci_mmc_config       *mmc_config[2];  /* 2 controllers */
        struct davinci_nand_pdata       *nand_config[4]; /* 4 chipsels */
+       struct matrix_keypad_platform_data *keypad_config;
 };
 
 extern struct platform_device tnetv107x_wdt_device;
index 15a6192..47723e8 100644 (file)
@@ -88,6 +88,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                /* DA8xx boards */
                DEBUG_LL_DA8XX(davinci_da830_evm,       2);
                DEBUG_LL_DA8XX(davinci_da850_evm,       2);
+               DEBUG_LL_DA8XX(mityomapl138,            1);
+               DEBUG_LL_DA8XX(omapl138_hawkboard,      2);
 
                /* TNETV107x boards */
                DEBUG_LL_TNETV107X(tnetv107x,           1);
index 864e604..daeae06 100644 (file)
@@ -104,7 +104,7 @@ static u32 pll_ext_freq[] = {
 };
 
 /* PSC control registers */
-static u32 psc_regs[] __initconst = { TNETV107X_PSC_BASE };
+static u32 psc_regs[] = { TNETV107X_PSC_BASE };
 
 /* Host map for interrupt controller */
 static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
@@ -581,7 +581,14 @@ static struct davinci_id ids[] = {
                .part_no        = 0xb8a1,
                .manufacturer   = 0x017,
                .cpu_id         = DAVINCI_CPU_ID_TNETV107X,
-               .name           = "tnetv107x rev1.0",
+               .name           = "tnetv107x rev 1.0",
+       },
+       {
+               .variant        = 0x1,
+               .part_no        = 0xb8a1,
+               .manufacturer   = 0x017,
+               .cpu_id         = DAVINCI_CPU_ID_TNETV107X,
+               .name           = "tnetv107x rev 1.1/1.2",
        },
 };
 
index 4cb55d3..ffdf87b 100644 (file)
@@ -776,9 +776,15 @@ static struct platform_device ep93xx_i2s_device = {
        .resource       = ep93xx_i2s_resource,
 };
 
+static struct platform_device ep93xx_pcm_device = {
+       .name           = "ep93xx-pcm-audio",
+       .id             = -1,
+};
+
 void __init ep93xx_register_i2s(void)
 {
        platform_device_register(&ep93xx_i2s_device);
+       platform_device_register(&ep93xx_pcm_device);
 }
 
 #define EP93XX_SYSCON_DEVCFG_I2S_MASK  (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
@@ -826,6 +832,40 @@ void ep93xx_i2s_release(void)
 }
 EXPORT_SYMBOL(ep93xx_i2s_release);
 
+/*************************************************************************
+ * EP93xx AC97 audio peripheral handling
+ *************************************************************************/
+static struct resource ep93xx_ac97_resources[] = {
+       {
+               .start  = EP93XX_AAC_PHYS_BASE,
+               .end    = EP93XX_AAC_PHYS_BASE + 0xb0 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = IRQ_EP93XX_AACINTR,
+               .end    = IRQ_EP93XX_AACINTR,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device ep93xx_ac97_device = {
+       .name           = "ep93xx-ac97",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(ep93xx_ac97_resources),
+       .resource       = ep93xx_ac97_resources,
+};
+
+void __init ep93xx_register_ac97(void)
+{
+       /*
+        * Make sure that the AC97 pins are not used by I2S.
+        */
+       ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
+
+       platform_device_register(&ep93xx_ac97_device);
+       platform_device_register(&ep93xx_pcm_device);
+}
+
 extern void ep93xx_gpio_init(void);
 
 void __init ep93xx_init_devices(void)
index c54b3e5..9ac4d10 100644 (file)
 #define EP93XX_GPIO_B_INT_STATUS       EP93XX_GPIO_REG(0xbc)
 #define EP93XX_GPIO_EEDRIVE            EP93XX_GPIO_REG(0xc8)
 
+#define EP93XX_AAC_PHYS_BASE           EP93XX_APB_PHYS(0x00080000)
 #define EP93XX_AAC_BASE                        EP93XX_APB_IOMEM(0x00080000)
 
 #define EP93XX_SPI_PHYS_BASE           EP93XX_APB_PHYS(0x000a0000)
index 3330b36..5066045 100644 (file)
@@ -61,6 +61,7 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev);
 void ep93xx_register_i2s(void);
 int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
 void ep93xx_i2s_release(void);
+void ep93xx_register_ac97(void);
 
 void ep93xx_init_devices(void);
 extern struct sys_timer ep93xx_timer;
index f22ce8d..d96dc1c 100644 (file)
@@ -61,6 +61,7 @@ static void __init simone_init_machine(void)
        ep93xx_register_fb(&simone_fb_info);
        ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
                            ARRAY_SIZE(simone_i2c_board_info));
+       ep93xx_register_ac97();
 }
 
 MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
index 1c82d42..51ff23b 100644 (file)
@@ -903,10 +903,16 @@ static struct platform_device kirkwood_i2s_device = {
        },
 };
 
+static struct platform_device kirkwood_pcm_device = {
+       .name           = "kirkwood-pcm-audio",
+       .id             = -1,
+};
+
 void __init kirkwood_audio_init(void)
 {
        kirkwood_clk_ctrl |= CGC_AUDIO;
        platform_device_register(&kirkwood_i2s_device);
+       platform_device_register(&kirkwood_pcm_device);
 }
 
 /*****************************************************************************
index 5e28644..5ea66f1 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
+#include <linux/gpio-fan.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -137,6 +138,46 @@ static struct platform_device netspace_v2_leds = {
 };
 
 /*****************************************************************************
+ * GPIO fan
+ ****************************************************************************/
+
+/* Designed for fan 40x40x16: ADDA AD0412LB-D50 6000rpm@12v */
+static struct gpio_fan_speed netspace_max_v2_fan_speed[] = {
+       {    0,  0 },
+       { 1500, 15 },
+       { 1700, 14 },
+       { 1800, 13 },
+       { 2100, 12 },
+       { 3100, 11 },
+       { 3300, 10 },
+       { 4300,  9 },
+       { 5500,  8 },
+};
+
+static unsigned netspace_max_v2_fan_ctrl[] = { 22, 7, 33, 23 };
+
+static struct gpio_fan_alarm netspace_max_v2_fan_alarm = {
+       .gpio           = 25,
+       .active_low     = 1,
+};
+
+static struct gpio_fan_platform_data netspace_max_v2_fan_data = {
+       .num_ctrl       = ARRAY_SIZE(netspace_max_v2_fan_ctrl),
+       .ctrl           = netspace_max_v2_fan_ctrl,
+       .alarm          = &netspace_max_v2_fan_alarm,
+       .num_speed      = ARRAY_SIZE(netspace_max_v2_fan_speed),
+       .speed          = netspace_max_v2_fan_speed,
+};
+
+static struct platform_device netspace_max_v2_gpio_fan = {
+       .name   = "gpio-fan",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &netspace_max_v2_fan_data,
+       },
+};
+
+/*****************************************************************************
  * General Setup
  ****************************************************************************/
 
@@ -205,6 +246,8 @@ static void __init netspace_v2_init(void)
        platform_device_register(&netspace_v2_leds);
        platform_device_register(&netspace_v2_gpio_leds);
        platform_device_register(&netspace_v2_gpio_buttons);
+       if (machine_is_netspace_max_v2())
+               platform_device_register(&netspace_max_v2_gpio_fan);
 
        if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
            gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
index facfaeb..9a304d8 100644 (file)
@@ -12,7 +12,7 @@ obj-$(CONFIG_OMAP_MPU_TIMER)  += time.o
 obj-$(CONFIG_OMAP_32K_TIMER)   += timer32k.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
 
 # DSP
 obj-$(CONFIG_OMAP_MBOX_FWK)    += mailbox_mach.o
index 73c8639..1d4163b 100644 (file)
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 
+#include <media/soc_camera.h>
+
 #include <asm/serial.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -32,6 +35,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/camera.h>
 
 #include <mach/ams-delta-fiq.h>
 
@@ -213,10 +217,56 @@ static struct platform_device ams_delta_led_device = {
        .id     = -1
 };
 
+static struct i2c_board_info ams_delta_camera_board_info[] = {
+       {
+               I2C_BOARD_INFO("ov6650", 0x60),
+       },
+};
+
+#ifdef CONFIG_LEDS_TRIGGERS
+DEFINE_LED_TRIGGER(ams_delta_camera_led_trigger);
+
+static int ams_delta_camera_power(struct device *dev, int power)
+{
+       /*
+        * turn on camera LED
+        */
+       if (power)
+               led_trigger_event(ams_delta_camera_led_trigger, LED_FULL);
+       else
+               led_trigger_event(ams_delta_camera_led_trigger, LED_OFF);
+       return 0;
+}
+#else
+#define ams_delta_camera_power NULL
+#endif
+
+static struct soc_camera_link __initdata ams_delta_iclink = {
+       .bus_id         = 0,    /* OMAP1 SoC camera bus */
+       .i2c_adapter_id = 1,
+       .board_info     = &ams_delta_camera_board_info[0],
+       .module_name    = "ov6650",
+       .power          = ams_delta_camera_power,
+};
+
+static struct platform_device ams_delta_camera_device = {
+       .name   = "soc-camera-pdrv",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &ams_delta_iclink,
+       },
+};
+
+static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
+       .camexclk_khz   = 12000,        /* default 12MHz clock, no extra DPLL */
+       .lclk_khz_max   = 1334,         /* results in 5fps CIF, 10fps QCIF */
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
        &ams_delta_kp_device,
        &ams_delta_lcd_device,
        &ams_delta_led_device,
+       &ams_delta_camera_device,
 };
 
 static void __init ams_delta_init(void)
@@ -225,6 +275,20 @@ static void __init ams_delta_init(void)
        omap_cfg_reg(UART1_TX);
        omap_cfg_reg(UART1_RTS);
 
+       /* parallel camera interface */
+       omap_cfg_reg(H19_1610_CAM_EXCLK);
+       omap_cfg_reg(J15_1610_CAM_LCLK);
+       omap_cfg_reg(L18_1610_CAM_VS);
+       omap_cfg_reg(L15_1610_CAM_HS);
+       omap_cfg_reg(L19_1610_CAM_D0);
+       omap_cfg_reg(K14_1610_CAM_D1);
+       omap_cfg_reg(K15_1610_CAM_D2);
+       omap_cfg_reg(K19_1610_CAM_D3);
+       omap_cfg_reg(K18_1610_CAM_D4);
+       omap_cfg_reg(J14_1610_CAM_D5);
+       omap_cfg_reg(J19_1610_CAM_D6);
+       omap_cfg_reg(J18_1610_CAM_D7);
+
        iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 
        omap_board_config = ams_delta_config;
@@ -236,6 +300,11 @@ static void __init ams_delta_init(void)
        ams_delta_latch2_write(~0, 0);
 
        omap1_usb_init(&ams_delta_usb_config);
+       omap1_set_camera_info(&ams_delta_camera_platform_data);
+#ifdef CONFIG_LEDS_TRIGGERS
+       led_trigger_register_simple("ams_delta_camera",
+                       &ams_delta_camera_led_trigger);
+#endif
        platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
 #ifdef CONFIG_AMS_DELTA_FIQ
index b30c499..f2fc43d 100644 (file)
@@ -58,8 +58,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .dma_mask                       = 0xffffffff,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index 54b0f06..2098525 100644 (file)
@@ -40,8 +40,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .dma_mask                       = 0xffffffff,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index 86afb29..071af3e 100644 (file)
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/htcpld.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,6 +46,7 @@
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/usb.h>
+#include <plat/mmc.h>
 
 #include <mach/irqs.h>
 
 #define       OMAP_LCDC_CTRL_LCD_EN           (1 << 0)
 #define       OMAP_LCDC_STAT_DONE             (1 << 0)
 
-static struct omap_lcd_config htcherald_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
+/* GPIO definitions for the power button and keyboard slide switch */
+#define HTCHERALD_GPIO_POWER 139
+#define HTCHERALD_GPIO_SLIDE 174
+#define HTCHERALD_GIRQ_BTNS 141
 
-static struct omap_board_config_kernel htcherald_config[] __initdata = {
-       { OMAP_TAG_LCD, &htcherald_lcd_config },
-};
+/* GPIO definitions for the touchscreen */
+#define HTCHERALD_GPIO_TS 76
+
+/* HTCPLD definitions */
+
+/*
+ * CPLD Logic
+ *
+ * Chip 3 - 0x03
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * DPAD light          x x x x  x x x 1
+ * SoundDev            x x x x  1 x x x
+ * Screen white        1 x x x  x x x x
+ * MMC power on        x x x x  x 1 x x
+ * Happy times (n)     0 x x x  x 1 x x
+ *
+ * Chip 4 - 0x04
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Keyboard light      x x x x  x x x 1
+ * LCD Bright (4)      x x x x  x 1 1 x
+ * LCD Bright (3)      x x x x  x 0 1 x
+ * LCD Bright (2)      x x x x  x 1 0 x
+ * LCD Bright (1)      x x x x  x 0 0 x
+ * LCD Off             x x x x  0 x x x
+ * LCD image (fb)      1 x x x  x x x x
+ * LCD image (white)   0 x x x  x x x x
+ * Caps lock LED       x x 1 x  x x x x
+ *
+ * Chip 5 - 0x05
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Red (solid)         x x x x  x 1 x x
+ * Red (flash)         x x x x  x x 1 x
+ * Green (GSM flash)   x x x x  1 x x x
+ * Green (GSM solid)   x x x 1  x x x x
+ * Green (wifi flash)  x x 1 x  x x x x
+ * Blue (bt flash)     x 1 x x  x x x x
+ * DPAD Int Enable     1 x x x  x x x 0
+ *
+ * (Combinations of the above can be made for different colors.)
+ * The direction pad interrupt enable must be set each time the
+ * interrupt is handled.
+ *
+ * Chip 6 - 0x06
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Vibrator            x x x x  1 x x x
+ * Alt LED             x x x 1  x x x x
+ * Screen white        1 x x x  x x x x
+ * Screen white        x x 1 x  x x x x
+ * Screen white        x 0 x x  x x x x
+ * Enable kbd dpad     x x x x  x x 0 x
+ * Happy Times         0 1 0 x  x x 0 x
+ */
+
+/*
+ * HTCPLD GPIO lines start 16 after OMAP_MAX_GPIO_LINES to account
+ * for the 16 MPUIO lines.
+ */
+#define HTCPLD_GPIO_START_OFFSET       (OMAP_MAX_GPIO_LINES + 16)
+#define HTCPLD_IRQ(chip, offset)       (OMAP_IRQ_END + 8 * (chip) + (offset))
+#define HTCPLD_BASE(chip, offset)      \
+       (HTCPLD_GPIO_START_OFFSET + 8 * (chip) + (offset))
+
+#define HTCPLD_GPIO_LED_DPAD           HTCPLD_BASE(0, 0)
+#define HTCPLD_GPIO_LED_KBD            HTCPLD_BASE(1, 0)
+#define HTCPLD_GPIO_LED_CAPS           HTCPLD_BASE(1, 5)
+#define HTCPLD_GPIO_LED_RED_FLASH      HTCPLD_BASE(2, 1)
+#define HTCPLD_GPIO_LED_RED_SOLID      HTCPLD_BASE(2, 2)
+#define HTCPLD_GPIO_LED_GREEN_FLASH    HTCPLD_BASE(2, 3)
+#define HTCPLD_GPIO_LED_GREEN_SOLID    HTCPLD_BASE(2, 4)
+#define HTCPLD_GPIO_LED_WIFI           HTCPLD_BASE(2, 5)
+#define HTCPLD_GPIO_LED_BT             HTCPLD_BASE(2, 6)
+#define HTCPLD_GPIO_LED_VIBRATE                HTCPLD_BASE(3, 3)
+#define HTCPLD_GPIO_LED_ALT            HTCPLD_BASE(3, 4)
+
+#define HTCPLD_GPIO_RIGHT_KBD          HTCPLD_BASE(6, 7)
+#define HTCPLD_GPIO_UP_KBD             HTCPLD_BASE(6, 6)
+#define HTCPLD_GPIO_LEFT_KBD           HTCPLD_BASE(6, 5)
+#define HTCPLD_GPIO_DOWN_KBD           HTCPLD_BASE(6, 4)
+
+#define HTCPLD_GPIO_RIGHT_DPAD         HTCPLD_BASE(7, 7)
+#define HTCPLD_GPIO_UP_DPAD            HTCPLD_BASE(7, 6)
+#define HTCPLD_GPIO_LEFT_DPAD          HTCPLD_BASE(7, 5)
+#define HTCPLD_GPIO_DOWN_DPAD          HTCPLD_BASE(7, 4)
+#define HTCPLD_GPIO_ENTER_DPAD         HTCPLD_BASE(7, 3)
+
+/*
+ * The htcpld chip requires a gpio write to a specific line
+ * to re-enable interrupts after one has occurred.
+ */
+#define HTCPLD_GPIO_INT_RESET_HI       HTCPLD_BASE(2, 7)
+#define HTCPLD_GPIO_INT_RESET_LO       HTCPLD_BASE(2, 0)
+
+/* Chip 5 */
+#define HTCPLD_IRQ_RIGHT_KBD           HTCPLD_IRQ(0, 7)
+#define HTCPLD_IRQ_UP_KBD              HTCPLD_IRQ(0, 6)
+#define HTCPLD_IRQ_LEFT_KBD            HTCPLD_IRQ(0, 5)
+#define HTCPLD_IRQ_DOWN_KBD            HTCPLD_IRQ(0, 4)
+
+/* Chip 6 */
+#define HTCPLD_IRQ_RIGHT_DPAD          HTCPLD_IRQ(1, 7)
+#define HTCPLD_IRQ_UP_DPAD             HTCPLD_IRQ(1, 6)
+#define HTCPLD_IRQ_LEFT_DPAD           HTCPLD_IRQ(1, 5)
+#define HTCPLD_IRQ_DOWN_DPAD           HTCPLD_IRQ(1, 4)
+#define HTCPLD_IRQ_ENTER_DPAD          HTCPLD_IRQ(1, 3)
 
 /* Keyboard definition */
 
@@ -140,6 +258,129 @@ static struct platform_device kp_device = {
        .resource       = kp_resources,
 };
 
+/* GPIO buttons for keyboard slide and power button */
+static struct gpio_keys_button herald_gpio_keys_table[] = {
+       {BTN_0,  HTCHERALD_GPIO_POWER, 1, "POWER", EV_KEY, 1, 20},
+       {SW_LID, HTCHERALD_GPIO_SLIDE, 0, "SLIDE", EV_SW,  1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_KBD,  1, "LEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_KBD, 1, "RIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_KBD,    1, "UP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_KBD,  1, "DOWN",  EV_KEY, 1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_DPAD,   1, "DLEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_DPAD,  1, "DRIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_DPAD,     1, "DUP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_DPAD,   1, "DDOWN",  EV_KEY, 1, 20},
+       {KEY_ENTER, HTCPLD_GPIO_ENTER_DPAD,  1, "DENTER", EV_KEY, 1, 20},
+};
+
+static struct gpio_keys_platform_data herald_gpio_keys_data = {
+       .buttons        = herald_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(herald_gpio_keys_table),
+       .rep            = 1,
+};
+
+static struct platform_device herald_gpiokeys_device = {
+       .name      = "gpio-keys",
+       .id             = -1,
+       .dev = {
+               .platform_data = &herald_gpio_keys_data,
+       },
+};
+
+/* LEDs for the Herald.  These connect to the HTCPLD GPIO device. */
+static struct gpio_led gpio_leds[] = {
+       {"dpad",        NULL, HTCPLD_GPIO_LED_DPAD,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"kbd",         NULL, HTCPLD_GPIO_LED_KBD,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"vibrate",     NULL, HTCPLD_GPIO_LED_VIBRATE,     0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_solid", NULL, HTCPLD_GPIO_LED_GREEN_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_flash", NULL, HTCPLD_GPIO_LED_GREEN_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_solid",   "mmc0", HTCPLD_GPIO_LED_RED_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_flash",   NULL, HTCPLD_GPIO_LED_RED_FLASH,   0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"wifi",        NULL, HTCPLD_GPIO_LED_WIFI,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"bt",          NULL, HTCPLD_GPIO_LED_BT,          0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"caps",        NULL, HTCPLD_GPIO_LED_CAPS,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"alt",         NULL, HTCPLD_GPIO_LED_ALT,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+};
+
+static struct gpio_led_platform_data gpio_leds_data = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+       .name           = "leds-gpio",
+       .id             = 0,
+       .dev    = {
+               .platform_data  = &gpio_leds_data,
+       },
+};
+
+/* HTC PLD chips */
+
+static struct resource htcpld_resources[] = {
+       [0] = {
+               .start  = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .end    = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct htcpld_chip_platform_data htcpld_chips[] = {
+       [0] = {
+               .addr           = 0x03,
+               .reset          = 0x04,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(0, 0),
+               .gpio_in_base   = HTCPLD_BASE(4, 0),
+       },
+       [1] = {
+               .addr           = 0x04,
+               .reset          = 0x8e,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(1, 0),
+               .gpio_in_base   = HTCPLD_BASE(5, 0),
+       },
+       [2] = {
+               .addr           = 0x05,
+               .reset          = 0x80,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(2, 0),
+               .gpio_in_base   = HTCPLD_BASE(6, 0),
+               .irq_base       = HTCPLD_IRQ(0, 0),
+               .num_irqs       = 8,
+       },
+       [3] = {
+               .addr           = 0x06,
+               .reset          = 0x40,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(3, 0),
+               .gpio_in_base   = HTCPLD_BASE(7, 0),
+               .irq_base       = HTCPLD_IRQ(1, 0),
+               .num_irqs       = 8,
+       },
+};
+
+struct htcpld_core_platform_data htcpld_pfdata = {
+       .int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
+       .int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
+       .i2c_adapter_id    = 1,
+
+       .chip              = htcpld_chips,
+       .num_chip          = ARRAY_SIZE(htcpld_chips),
+};
+
+static struct platform_device htcpld_device = {
+       .name           = "i2c-htcpld",
+       .id             = -1,
+       .resource       = htcpld_resources,
+       .num_resources  = ARRAY_SIZE(htcpld_resources),
+       .dev    = {
+               .platform_data  = &htcpld_pfdata,
+       },
+};
+
 /* USB Device */
 static struct omap_usb_config htcherald_usb_config __initdata = {
        .otg = 0,
@@ -150,14 +391,71 @@ static struct omap_usb_config htcherald_usb_config __initdata = {
 };
 
 /* LCD Device resources */
+static struct omap_lcd_config htcherald_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel htcherald_config[] __initdata = {
+       { OMAP_TAG_LCD, &htcherald_lcd_config },
+};
+
 static struct platform_device lcd_device = {
        .name           = "lcd_htcherald",
        .id             = -1,
 };
 
+/* MMC Card */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+static struct omap_mmc_platform_data htc_mmc1_data = {
+       .nr_slots                       = 1,
+       .switch_slot                    = NULL,
+       .slots[0]       = {
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
+               .name                   = "mmcblk",
+               .nomux                  = 1,
+               .wires                  = 4,
+               .switch_pin             = -1,
+       },
+};
+
+static struct omap_mmc_platform_data *htc_mmc_data[1];
+#endif
+
+
+/* Platform devices for the Herald */
 static struct platform_device *devices[] __initdata = {
        &kp_device,
        &lcd_device,
+       &htcpld_device,
+       &gpio_leds_device,
+       &herald_gpiokeys_device,
+};
+
+/*
+ * Touchscreen
+ */
+static const struct ads7846_platform_data htcherald_ts_platform_data = {
+       .model                  = 7846,
+       .keep_vref_on           = 1,
+       .x_plate_ohms           = 496,
+       .gpio_pendown           = HTCHERALD_GPIO_TS,
+       .pressure_max           = 100000,
+       .pressure_min           = 5000,
+       .x_min                  = 528,
+       .x_max                  = 3760,
+       .y_min                  = 624,
+       .y_max                  = 3760,
+};
+
+static struct spi_board_info __initdata htcherald_spi_board_info[] = {
+       {
+               .modalias               = "ads7846",
+               .platform_data          = &htcherald_ts_platform_data,
+               .irq                    = OMAP_GPIO_IRQ(HTCHERALD_GPIO_TS),
+               .max_speed_hz           = 2500000,
+               .bus_num                = 2,
+               .chip_select            = 1,
+       }
 };
 
 /*
@@ -278,6 +576,7 @@ static void __init htcherald_init(void)
 {
        printk(KERN_INFO "HTC Herald init.\n");
 
+       /* Do board initialization before we register all the devices */
        omap_gpio_init();
 
        omap_board_config = htcherald_config;
@@ -288,6 +587,16 @@ static void __init htcherald_init(void)
 
        htcherald_usb_enable();
        omap1_usb_init(&htcherald_usb_config);
+
+       spi_register_board_info(htcherald_spi_board_info,
+               ARRAY_SIZE(htcherald_spi_board_info));
+
+       omap_register_i2c_bus(1, 100, NULL, 0);
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+       htc_mmc_data[0] = &htc_mmc1_data;
+       omap1_init_mmc(htc_mmc_data, 1);
+#endif
 }
 
 static void __init htcherald_init_irq(void)
index 5b33ae8..e8ddd86 100644 (file)
@@ -44,8 +44,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .nr_slots                       = 1,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index aa07256..ea0d80a 100644 (file)
@@ -9,6 +9,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -25,6 +26,7 @@
 #include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/omap7xx.h>
+#include <plat/mcbsp.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -191,10 +193,76 @@ static inline void omap_init_spi100k(void)
 }
 #endif
 
+
+#define OMAP1_CAMERA_BASE      0xfffb6800
+#define OMAP1_CAMERA_IOSIZE    0x1c
+
+static struct resource omap1_camera_resources[] = {
+       [0] = {
+               .start  = OMAP1_CAMERA_BASE,
+               .end    = OMAP1_CAMERA_BASE + OMAP1_CAMERA_IOSIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = INT_CAMERA,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 omap1_camera_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device omap1_camera_device = {
+       .name           = "omap1-camera",
+       .id             = 0, /* This is used to put cameras on this interface */
+       .dev            = {
+               .dma_mask               = &omap1_camera_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .num_resources  = ARRAY_SIZE(omap1_camera_resources),
+       .resource       = omap1_camera_resources,
+};
+
+void __init omap1_camera_init(void *info)
+{
+       struct platform_device *dev = &omap1_camera_device;
+       int ret;
+
+       dev->dev.platform_data = info;
+
+       ret = platform_device_register(dev);
+       if (ret)
+               dev_err(&dev->dev, "unable to register device: %d\n", ret);
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 static inline void omap_init_sti(void) {}
 
+#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
+
+static struct platform_device omap_pcm = {
+       .name   = "omap-pcm-audio",
+       .id     = -1,
+};
+
+OMAP_MCBSP_PLATFORM_DEVICE(1);
+OMAP_MCBSP_PLATFORM_DEVICE(2);
+OMAP_MCBSP_PLATFORM_DEVICE(3);
+
+static void omap_init_audio(void)
+{
+       platform_device_register(&omap_mcbsp1);
+       platform_device_register(&omap_mcbsp2);
+       if (!cpu_is_omap7xx())
+               platform_device_register(&omap_mcbsp3);
+       platform_device_register(&omap_pcm);
+}
+
+#else
+static inline void omap_init_audio(void) {}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -227,8 +295,36 @@ static int __init omap1_init_devices(void)
        omap_init_rtc();
        omap_init_spi100k();
        omap_init_sti();
+       omap_init_audio();
 
        return 0;
 }
 arch_initcall(omap1_init_devices);
 
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+
+static struct resource wdt_resources[] = {
+       {
+               .start          = 0xfffeb000,
+               .end            = 0xfffeb07F,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap_wdt_device = {
+       .name      = "omap_wdt",
+       .id          = -1,
+       .num_resources  = ARRAY_SIZE(wdt_resources),
+       .resource       = wdt_resources,
+};
+
+static int __init omap_init_wdt(void)
+{
+       if (!cpu_is_omap16xx())
+               return;
+
+       platform_device_register(&omap_wdt_device);
+       return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/camera.h b/arch/arm/mach-omap1/include/mach/camera.h
new file mode 100644 (file)
index 0000000..fd54b45
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_ARCH_CAMERA_H_
+#define __ASM_ARCH_CAMERA_H_
+
+void omap1_camera_init(void *);
+
+static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)
+{
+       omap1_camera_init(info);
+}
+
+#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
new file mode 100644 (file)
index 0000000..8b66392
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Runtime PM support code for OMAP1
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap1_pm_runtime_suspend(struct device *dev)
+{
+       struct clk *iclk, *fclk;
+       int ret = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+
+       fclk = clk_get(dev, "fck");
+       if (!IS_ERR(fclk)) {
+               clk_disable(fclk);
+               clk_put(fclk);
+       }
+
+       iclk = clk_get(dev, "ick");
+       if (!IS_ERR(iclk)) {
+               clk_disable(iclk);
+               clk_put(iclk);
+       }
+
+       return 0;
+};
+
+static int omap1_pm_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       struct clk *iclk, *fclk;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       iclk = clk_get(dev, "ick");
+       if (!IS_ERR(iclk)) {
+               clk_enable(iclk);
+               clk_put(iclk);
+       }
+
+       fclk = clk_get(dev, "fck");
+       if (!IS_ERR(fclk)) {
+               clk_enable(fclk);
+               clk_put(fclk);
+       }
+
+       return pm_generic_runtime_resume(dev);
+};
+
+static int __init omap1_pm_runtime_init(void)
+{
+       const struct dev_pm_ops *pm;
+       struct dev_pm_ops *omap_pm;
+
+       pm = platform_bus_get_pm_ops();
+       if (!pm) {
+               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+       if (!omap_pm) {
+               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       omap_pm->runtime_suspend = omap1_pm_runtime_suspend;
+       omap_pm->runtime_resume = omap1_pm_runtime_resume;
+
+       platform_bus_set_pm_ops(omap_pm);
+
+       return 0;
+}
+core_initcall(omap1_pm_runtime_init);
+#endif /* CONFIG_PM_RUNTIME */
index b48bacf..ab784bf 100644 (file)
@@ -11,9 +11,8 @@ config ARCH_OMAP2PLUS_TYPICAL
        select PM_RUNTIME
        select VFP
        select NEON if ARCH_OMAP3 || ARCH_OMAP4
-       select SERIAL_8250
-       select SERIAL_CORE_CONSOLE
-       select SERIAL_8250_CONSOLE
+       select SERIAL_OMAP
+       select SERIAL_OMAP_CONSOLE
        select I2C
        select I2C_OMAP
        select MFD
@@ -35,7 +34,7 @@ config ARCH_OMAP3
        default y
        select CPU_V7
        select USB_ARCH_HAS_EHCI
-       select ARM_L1_CACHE_SHIFT_6
+       select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
 
 config ARCH_OMAP4
        bool "TI OMAP4"
@@ -43,6 +42,8 @@ config ARCH_OMAP4
        depends on ARCH_OMAP2PLUS
        select CPU_V7
        select ARM_GIC
+       select PL310_ERRATA_588369
+       select ARM_ERRATA_720789
 
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
@@ -99,20 +100,20 @@ config MACH_OMAP2_TUSB6010
 
 config MACH_OMAP_H4
        bool "OMAP 2420 H4 board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2420
        default y
        select OMAP_PACKAGE_ZAF
        select OMAP_DEBUG_DEVICES
 
 config MACH_OMAP_APOLLON
        bool "OMAP 2420 Apollon board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2420
        default y
        select OMAP_PACKAGE_ZAC
 
 config MACH_OMAP_2430SDP
        bool "OMAP 2430 SDP board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2430
        default y
        select OMAP_PACKAGE_ZAC
 
@@ -135,6 +136,26 @@ config MACH_OMAP_LDP
        default y
        select OMAP_PACKAGE_CBB
 
+config MACH_OMAP3530_LV_SOM
+       bool "OMAP3 Logic 3530 LV SOM board"
+       depends on ARCH_OMAP3
+       select OMAP_PACKAGE_CBB
+       default y
+       help
+        Support for the LogicPD OMAP3530 SOM Development kit
+        for full description please see the products webpage at
+        http://www.logicpd.com/products/development-kits/texas-instruments-zoom%E2%84%A2-omap35x-development-kit
+
+config MACH_OMAP3_TORPEDO
+       bool "OMAP3 Logic 35x Torpedo board"
+       depends on ARCH_OMAP3
+       select OMAP_PACKAGE_CBB
+       default y
+       help
+        Support for the LogicPD OMAP35x Torpedo Development kit
+        for full description please see the products webpage at
+        http://www.logicpd.com/products/development-kits/zoom-omap35x-torpedo-development-kit
+
 config MACH_OVERO
        bool "Gumstix Overo board"
        depends on ARCH_OMAP3
@@ -200,12 +221,18 @@ config MACH_OMAP_ZOOM2
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
+       select SERIAL_8250
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_8250_CONSOLE
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBP
+       select SERIAL_8250
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_8250_CONSOLE
 
 config MACH_CM_T35
        bool "CompuLab CM-T35 module"
@@ -214,12 +241,25 @@ config MACH_CM_T35
        select OMAP_PACKAGE_CUS
        select OMAP_MUX
 
+config MACH_CM_T3517
+       bool "CompuLab CM-T3517 module"
+       depends on ARCH_OMAP3
+       default y
+       select OMAP_PACKAGE_CBB
+       select OMAP_MUX
+
 config MACH_IGEP0020
        bool "IGEP v2 board"
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
 
+config MACH_IGEP0030
+       bool "IGEP OMAP3 module"
+       depends on ARCH_OMAP3
+       default y
+       select OMAP_PACKAGE_CBB
+
 config MACH_SBC3530
        bool "OMAP3 SBC STALKER board"
        depends on ARCH_OMAP3
index 88d3a1e..7352412 100644 (file)
@@ -3,9 +3,10 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
+        common.o
 
-omap-2-3-common                                = irq.o sdrc.o
+omap-2-3-common                                = irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common                           = omap_hwmod.o \
                                          omap_hwmod_common_data.o
 prcm-common                            = prcm.o powerdomain.o
@@ -15,7 +16,7 @@ clock-common                          = clock.o clock_common_data.o \
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
@@ -49,14 +50,18 @@ obj-$(CONFIG_ARCH_OMAP2)            += sdrc2xxx.o
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o cpuidle34xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o
+obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
 AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a
 
+ifeq ($(CONFIG_PM_VERBOSE),y)
+CFLAGS_pm_bus.o                                += -DDEBUG
+endif
+
 endif
 
 # PRCM
@@ -87,6 +92,7 @@ obj-$(CONFIG_ARCH_OMAP2430)           += opp2430_data.o
 obj-$(CONFIG_ARCH_OMAP2420)            += omap_hwmod_2420_data.o
 obj-$(CONFIG_ARCH_OMAP2430)            += omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += omap_hwmod_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)               += omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)                        += emu.o
@@ -115,6 +121,10 @@ obj-$(CONFIG_MACH_DEVKIT8000)      += board-devkit8000.o \
 obj-$(CONFIG_MACH_OMAP_LDP)            += board-ldp.o \
                                           board-flash.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o \
+                                          hsmmc.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o \
+                                          hsmmc.o
 obj-$(CONFIG_MACH_OVERO)               += board-overo.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_OMAP3EVM)            += board-omap3evm.o \
@@ -146,8 +156,11 @@ obj-$(CONFIG_MACH_OMAP_3630SDP)            += board-3630sdp.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_CM_T35)              += board-cm-t35.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_CM_T3517)            += board-cm-t3517.o
 obj-$(CONFIG_MACH_IGEP0020)            += board-igep0020.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_IGEP0030)            += board-igep0030.o \
+                                          hsmmc.o
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)     += board-omap3touchbook.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)                += board-4430sdp.o \
@@ -174,3 +187,6 @@ obj-y                                       += $(nand-m) $(nand-y)
 
 smc91x-$(CONFIG_SMC91X)                        := gpmc-smc91x.o
 obj-y                                  += $(smc91x-m) $(smc91x-y)
+
+smsc911x-$(CONFIG_SMSC911X)            := gpmc-smsc911x.o
+obj-y                                  += $(smsc911x-m) $(smsc911x-y)
index b857ce4..b527f8d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
 #include <linux/err.h>
@@ -190,7 +191,7 @@ static int __init omap2430_i2c_init(void)
 static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .ext_clock      = 1,
index a5b095c..4e3742c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
 #include <plat/display.h>
 
-#include <plat/control.h>
 #include <plat/gpmc-smc91x.h>
 
-#include <mach/board-flash.h>
-
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "control.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -76,7 +76,7 @@ static struct cpuidle_params omap3_cpuidle_params_table[] = {
        {1, 10000, 30000, 300000},
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_RIGHT),
        KEY(0, 2, KEY_A),
@@ -353,12 +353,12 @@ static struct omap2_hsmmc_info mmc[] = {
                /* 8 bits (default) requires S6.3 == ON,
                 * so the SIM card isn't used; else 4 bits.
                 */
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 4,
        },
        {
                .mmc            = 2,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 7,
        },
        {}      /* Terminator */
index fd27ac0..bbcf580 100644 (file)
@@ -21,8 +21,8 @@
 #include <plat/usb.h>
 
 #include <mach/board-zoom.h>
-#include <mach/board-flash.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
@@ -208,7 +208,6 @@ static struct flash_partitions sdp_flash_partitions[] = {
 static void __init omap_sdp_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-       omap_serial_init();
        zoom_peripherals_init();
        board_smc91x_init();
        board_flash_init(sdp_flash_partitions, chip_sel_sdp);
index 0b6a65f..69a4ae9 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/otg.h>
 #include <linux/spi/spi.h>
 #include <linux/i2c/twl.h>
+#include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
 #include <linux/leds.h>
 
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+
 #include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
 
 #define ETH_KS8851_IRQ                 34
 #define ETH_KS8851_POWER_ON            48
 #define ETH_KS8851_QUART               138
+#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO       184
+#define OMAP4_SFH7741_ENABLE_GPIO              188
 
 static struct gpio_led sdp4430_gpio_leds[] = {
        {
@@ -77,11 +81,47 @@ static struct gpio_led sdp4430_gpio_leds[] = {
 
 };
 
+static struct gpio_keys_button sdp4430_gpio_keys[] = {
+       {
+               .desc                   = "Proximity Sensor",
+               .type                   = EV_SW,
+               .code                   = SW_FRONT_PROXIMITY,
+               .gpio                   = OMAP4_SFH7741_SENSOR_OUTPUT_GPIO,
+               .active_low             = 0,
+       }
+};
+
 static struct gpio_led_platform_data sdp4430_led_data = {
        .leds   = sdp4430_gpio_leds,
        .num_leds       = ARRAY_SIZE(sdp4430_gpio_leds),
 };
 
+static int omap_prox_activate(struct device *dev)
+{
+       gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 1);
+       return 0;
+}
+
+static void omap_prox_deactivate(struct device *dev)
+{
+       gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 0);
+}
+
+static struct gpio_keys_platform_data sdp4430_gpio_keys_data = {
+       .buttons        = sdp4430_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(sdp4430_gpio_keys),
+       .enable         = omap_prox_activate,
+       .disable        = omap_prox_deactivate,
+};
+
+static struct platform_device sdp4430_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &sdp4430_gpio_keys_data,
+       },
+};
+
 static struct platform_device sdp4430_leds_gpio = {
        .name   = "leds-gpio",
        .id     = -1,
@@ -161,6 +201,7 @@ static struct platform_device sdp4430_lcd_device = {
 
 static struct platform_device *sdp4430_devices[] __initdata = {
        &sdp4430_lcd_device,
+       &sdp4430_gpio_keys_device,
        &sdp4430_leds_gpio,
 };
 
@@ -193,15 +234,16 @@ static struct omap_musb_board_data musb_board_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = -EINVAL,
        },
        {
                .mmc            = 2,
-               .wires          = 8,
+               .caps           =  MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
+               .ocr_mask       = MMC_VDD_29_30,
        },
        {}      /* Terminator */
 };
@@ -235,8 +277,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-       struct omap_mmc_platform_data *pdata = dev->platform_data;
+       struct omap_mmc_platform_data *pdata;
 
+       /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+       if (!dev) {
+               pr_err("Failed %s\n", __func__);
+               return;
+       }
+       pdata = dev->platform_data;
        pdata->init =   omap4_twl6030_hsmmc_late_init;
 }
 
@@ -412,6 +460,11 @@ static struct i2c_board_info __initdata sdp4430_i2c_3_boardinfo[] = {
                I2C_BOARD_INFO("tmp105", 0x48),
        },
 };
+static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("hmc5843", 0x1e),
+       },
+};
 static int __init omap4_i2c_init(void)
 {
        /*
@@ -423,14 +476,36 @@ static int __init omap4_i2c_init(void)
        omap_register_i2c_bus(2, 400, NULL, 0);
        omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
                                ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
-       omap_register_i2c_bus(4, 400, NULL, 0);
+       omap_register_i2c_bus(4, 400, sdp4430_i2c_4_boardinfo,
+                               ARRAY_SIZE(sdp4430_i2c_4_boardinfo));
        return 0;
 }
+
+static void __init omap_sfh7741prox_init(void)
+{
+       int  error;
+
+       error = gpio_request(OMAP4_SFH7741_ENABLE_GPIO, "sfh7741");
+       if (error < 0) {
+               pr_err("%s:failed to request GPIO %d, error %d\n",
+                       __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+               return;
+       }
+
+       error = gpio_direction_output(OMAP4_SFH7741_ENABLE_GPIO , 0);
+       if (error < 0) {
+               pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n",
+                        __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+               gpio_free(OMAP4_SFH7741_ENABLE_GPIO);
+       }
+}
+
 static void __init omap_4430sdp_init(void)
 {
        int status;
 
        omap4_i2c_init();
+       omap_sfh7741prox_init();
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
        omap_serial_init();
        omap4_twl6030_hsmmc_init(mmc);
index d547036..0739950 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/i2c/pca953x.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/display.h>
 
 #include "mux.h"
+#include "control.h"
 
-#define AM35XX_EVM_PHY_MASK            (0xF)
 #define AM35XX_EVM_MDIO_FREQUENCY      (1000000)
 
+static struct mdio_platform_data am3517_evm_mdio_pdata = {
+       .bus_freq       = AM35XX_EVM_MDIO_FREQUENCY,
+};
+
+static struct resource am3517_mdio_resources[] = {
+       {
+               .start  = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET,
+               .end    = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET +
+                         SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device am3517_mdio_device = {
+       .name           = "davinci_mdio",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(am3517_mdio_resources),
+       .resource       = am3517_mdio_resources,
+       .dev.platform_data = &am3517_evm_mdio_pdata,
+};
+
 static struct emac_platform_data am3517_evm_emac_pdata = {
-       .phy_mask       = AM35XX_EVM_PHY_MASK,
-       .mdio_max_freq  = AM35XX_EVM_MDIO_FREQUENCY,
        .rmii_en        = 1,
 };
 
 static struct resource am3517_emac_resources[] = {
        {
                .start  = AM35XX_IPSS_EMAC_BASE,
-               .end    = AM35XX_IPSS_EMAC_BASE + 0x3FFFF,
+               .end    = AM35XX_IPSS_EMAC_BASE + 0x2FFFF,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -106,14 +125,13 @@ static void am3517_disable_ethernet_int(void)
        regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
 }
 
-void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
+static void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 {
        unsigned int regval;
 
        pdata->ctrl_reg_offset          = AM35XX_EMAC_CNTRL_OFFSET;
        pdata->ctrl_mod_reg_offset      = AM35XX_EMAC_CNTRL_MOD_OFFSET;
        pdata->ctrl_ram_offset          = AM35XX_EMAC_CNTRL_RAM_OFFSET;
-       pdata->mdio_reg_offset          = AM35XX_EMAC_MDIO_OFFSET;
        pdata->ctrl_ram_size            = AM35XX_EMAC_CNTRL_RAM_SIZE;
        pdata->version                  = EMAC_VERSION_2;
        pdata->hw_ram_addr              = AM35XX_EMAC_HW_RAM_ADDR;
@@ -121,6 +139,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
        pdata->interrupt_disable        = am3517_disable_ethernet_int;
        am3517_emac_device.dev.platform_data    = pdata;
        platform_device_register(&am3517_emac_device);
+       platform_device_register(&am3517_mdio_device);
+       clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev),
+                     NULL, &am3517_emac_device.dev);
 
        regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
        regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
@@ -139,7 +160,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 static struct i2c_board_info __initdata am3517evm_i2c1_boardinfo[] = {
        {
                I2C_BOARD_INFO("s35390a", 0x30),
-               .type           = "s35390a",
        },
 };
 
@@ -347,7 +367,7 @@ static struct omap_dss_board_info am3517_evm_dss_data = {
        .default_device = &am3517_evm_lcd_device,
 };
 
-struct platform_device am3517_evm_dss_device = {
+static struct platform_device am3517_evm_dss_device = {
        .name           = "omapdss",
        .id             = -1,
        .dev            = {
index 68f07f5..2c6db1a 100644 (file)
@@ -39,9 +39,9 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
-#include <plat/control.h>
 
 #include "mux.h"
+#include "control.h"
 
 /* LED & Switch macros */
 #define LED0_GPIO13            13
index 934d938..63f764e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/i2c/at24.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
@@ -237,8 +238,6 @@ static inline void cm_t35_init_nand(void) {}
        defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 #include <linux/spi/ads7846.h>
 
-#include <plat/mcspi.h>
-
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode     = 0,
        .single_channel = 1,    /* 0: slave, 1: master */
@@ -558,7 +557,7 @@ static struct twl4030_usb_data cm_t35_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int cm_t35_keymap[] = {
+static uint32_t cm_t35_keymap[] = {
        KEY(0, 0, KEY_A),       KEY(0, 1, KEY_B),       KEY(0, 2, KEY_LEFT),
        KEY(1, 0, KEY_UP),      KEY(1, 1, KEY_ENTER),   KEY(1, 2, KEY_DOWN),
        KEY(2, 0, KEY_RIGHT),   KEY(2, 1, KEY_C),       KEY(2, 2, KEY_D),
@@ -579,14 +578,14 @@ static struct twl4030_keypad_data cm_t35_kp_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
 
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .transceiver    = 1,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
new file mode 100644 (file)
index 0000000..1dd303e
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * linux/arch/arm/mach-omap2/board-cm-t3517.c
+ *
+ * Support for the CompuLab CM-T3517 modules
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Author: Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/rtc-v3020.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/can/platform/ti_hecc.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/usb.h>
+#include <plat/nand.h>
+#include <plat/gpmc.h>
+
+#include <mach/am35xx.h>
+
+#include "mux.h"
+#include "control.h"
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led cm_t3517_leds[] = {
+       [0] = {
+               .gpio                   = 186,
+               .name                   = "cm-t3517:green",
+               .default_trigger        = "heartbeat",
+               .active_low             = 0,
+       },
+};
+
+static struct gpio_led_platform_data cm_t3517_led_pdata = {
+       .num_leds       = ARRAY_SIZE(cm_t3517_leds),
+       .leds           = cm_t3517_leds,
+};
+
+static struct platform_device cm_t3517_led_device = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &cm_t3517_led_pdata,
+       },
+};
+
+static void __init cm_t3517_init_leds(void)
+{
+       platform_device_register(&cm_t3517_led_device);
+}
+#else
+static inline void cm_t3517_init_leds(void) {}
+#endif
+
+#if defined(CONFIG_CAN_TI_HECC) || defined(CONFIG_CAN_TI_HECC_MODULE)
+static struct resource cm_t3517_hecc_resources[] = {
+       {
+               .start  = AM35XX_IPSS_HECC_BASE,
+               .end    = AM35XX_IPSS_HECC_BASE + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = INT_35XX_HECC0_IRQ,
+               .end    = INT_35XX_HECC0_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct ti_hecc_platform_data cm_t3517_hecc_pdata = {
+       .scc_hecc_offset        = AM35XX_HECC_SCC_HECC_OFFSET,
+       .scc_ram_offset         = AM35XX_HECC_SCC_RAM_OFFSET,
+       .hecc_ram_offset        = AM35XX_HECC_RAM_OFFSET,
+       .mbx_offset             = AM35XX_HECC_MBOX_OFFSET,
+       .int_line               = AM35XX_HECC_INT_LINE,
+       .version                = AM35XX_HECC_VERSION,
+};
+
+static struct platform_device cm_t3517_hecc_device = {
+       .name           = "ti_hecc",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(cm_t3517_hecc_resources),
+       .resource       = cm_t3517_hecc_resources,
+       .dev            = {
+               .platform_data  = &cm_t3517_hecc_pdata,
+       },
+};
+
+static void cm_t3517_init_hecc(void)
+{
+       platform_device_register(&cm_t3517_hecc_device);
+}
+#else
+static inline void cm_t3517_init_hecc(void) {}
+#endif
+
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
+#define RTC_IO_GPIO            (153)
+#define RTC_WR_GPIO            (154)
+#define RTC_RD_GPIO            (160)
+#define RTC_CS_GPIO            (163)
+
+struct v3020_platform_data cm_t3517_v3020_pdata = {
+       .use_gpio       = 1,
+       .gpio_cs        = RTC_CS_GPIO,
+       .gpio_wr        = RTC_WR_GPIO,
+       .gpio_rd        = RTC_RD_GPIO,
+       .gpio_io        = RTC_IO_GPIO,
+};
+
+static struct platform_device cm_t3517_rtc_device = {
+       .name           = "v3020",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &cm_t3517_v3020_pdata,
+       }
+};
+
+static void __init cm_t3517_init_rtc(void)
+{
+       platform_device_register(&cm_t3517_rtc_device);
+}
+#else
+static inline void cm_t3517_init_rtc(void) {}
+#endif
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+#define HSUSB1_RESET_GPIO      (146)
+#define HSUSB2_RESET_GPIO      (147)
+#define USB_HUB_RESET_GPIO     (152)
+
+static struct ehci_hcd_omap_platform_data cm_t3517_ehci_pdata __initdata = {
+       .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+       .phy_reset  = true,
+       .reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
+       .reset_gpio_port[1]  = HSUSB2_RESET_GPIO,
+       .reset_gpio_port[2]  = -EINVAL,
+};
+
+static int cm_t3517_init_usbh(void)
+{
+       int err;
+
+       err = gpio_request(USB_HUB_RESET_GPIO, "usb hub rst");
+       if (err) {
+               pr_err("CM-T3517: usb hub rst gpio request failed: %d\n", err);
+       } else {
+               gpio_direction_output(USB_HUB_RESET_GPIO, 0);
+               udelay(10);
+               gpio_set_value(USB_HUB_RESET_GPIO, 1);
+               msleep(1);
+       }
+
+       usb_ehci_init(&cm_t3517_ehci_pdata);
+
+       return 0;
+}
+#else
+static inline int cm_t3517_init_usbh(void)
+{
+       return 0;
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
+#define NAND_BLOCK_SIZE                SZ_128K
+
+static struct mtd_partition cm_t3517_nand_partitions[] = {
+       {
+               .name           = "xloader",
+               .offset         = 0,                    /* Offset = 0x00000 */
+               .size           = 4 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "uboot",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
+               .size           = 15 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "uboot environment",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
+               .size           = 2 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "linux",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .size           = 32 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "rootfs",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_nand_platform_data cm_t3517_nand_data = {
+       .parts                  = cm_t3517_nand_partitions,
+       .nr_parts               = ARRAY_SIZE(cm_t3517_nand_partitions),
+       .dma_channel            = -1,   /* disable DMA in OMAP NAND driver */
+       .cs                     = 0,
+};
+
+static void __init cm_t3517_init_nand(void)
+{
+       if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
+               pr_err("CM-T3517: NAND initialization failed\n");
+}
+#else
+static inline void cm_t3517_init_nand(void) {}
+#endif
+
+static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
+};
+
+static void __init cm_t3517_init_irq(void)
+{
+       omap_board_config = cm_t3517_config;
+       omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
+
+       omap2_init_common_hw(NULL, NULL);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct omap_board_mux board_mux[] __initdata = {
+       /* GPIO186 - Green LED */
+       OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* RTC GPIOs: IO, WR#, RD#, CS# */
+       OMAP3_MUX(MCBSP4_DR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(MCBSP4_DX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       /* HSUSB1 RESET */
+       OMAP3_MUX(UART2_TX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* HSUSB2 RESET */
+       OMAP3_MUX(UART2_RX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* CM-T3517 USB HUB nRESET */
+       OMAP3_MUX(MCBSP4_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static void __init cm_t3517_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap_serial_init();
+       cm_t3517_init_leds();
+       cm_t3517_init_nand();
+       cm_t3517_init_rtc();
+       cm_t3517_init_usbh();
+       cm_t3517_init_hecc();
+}
+
+MACHINE_START(CM_T3517, "Compulab CM-T3517")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .reserve        = omap_reserve,
+       .init_irq       = cm_t3517_init_irq,
+       .init_machine   = cm_t3517_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 2205c20..067f437 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -44,7 +45,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -58,6 +58,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE                SZ_128K
 
@@ -105,7 +106,7 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
@@ -198,7 +199,7 @@ static struct platform_device devkit8000_dss_device = {
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
        REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_1),
        KEY(1, 0, KEY_2),
        KEY(2, 0, KEY_3),
index ac834aa..fd38c05 100644 (file)
@@ -21,7 +21,8 @@
 #include <plat/nand.h>
 #include <plat/onenand.h>
 #include <plat/tc.h>
-#include <mach/board-flash.h>
+
+#include "board-flash.h"
 
 #define REG_FPGA_REV                   0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2     0x60
similarity index 88%
rename from arch/arm/mach-omap2/include/mach/board-flash.h
rename to arch/arm/mach-omap2/board-flash.h
index b2242ae..69befe0 100644 (file)
@@ -26,3 +26,5 @@ struct flash_partitions {
 
 extern void board_flash_init(struct flash_partitions [],
                                char chip_sel[][GPMC_CS_NUM]);
+extern void board_nand_init(struct mtd_partition *nand_parts,
+                                       u8 nr_parts, u8 cs);
index 69064b1..b1c2c9a 100644 (file)
@@ -48,10 +48,22 @@ static void __init omap_generic_init(void)
 
 static void __init omap_generic_map_io(void)
 {
-       omap2_set_globals_242x(); /* should be 242x, 243x, or 343x */
-       omap242x_map_common_io();
+       if (cpu_is_omap242x()) {
+               omap2_set_globals_242x();
+               omap242x_map_common_io();
+       } else if (cpu_is_omap243x()) {
+               omap2_set_globals_243x();
+               omap243x_map_common_io();
+       } else if (cpu_is_omap34xx()) {
+               omap2_set_globals_3xxx();
+               omap34xx_map_common_io();
+       } else if (cpu_is_omap44xx()) {
+               omap2_set_globals_443x();
+               omap44xx_map_common_io();
+       }
 }
 
+/* XXX This machine entry name should be updated */
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
        .boot_params    = 0x80000100,
index cc39fc8..929993b 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/control.h>
 #include <mach/gpio.h>
 #include <plat/usb.h>
 #include <plat/board.h>
@@ -42,6 +41,7 @@
 #include <plat/gpmc.h>
 
 #include "mux.h"
+#include "control.h"
 
 #define H4_FLASH_CS    0
 #define H4_SMC91X_CS   1
index b62a68b..5e035a5 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
 #define IGEP2_GPIO_USBH_NRESET  24
-#define IGEP2_GPIO_LED0_GREEN  26
-#define IGEP2_GPIO_LED0_RED    27
-#define IGEP2_GPIO_LED1_RED    28
-#define IGEP2_GPIO_DVI_PUP     170
-#define IGEP2_GPIO_WIFI_NPD    94
-#define IGEP2_GPIO_WIFI_NRESET         95
+#define IGEP2_GPIO_LED0_GREEN   26
+#define IGEP2_GPIO_LED0_RED     27
+#define IGEP2_GPIO_LED1_RED     28
+#define IGEP2_GPIO_DVI_PUP      170
+
+#define IGEP2_RB_GPIO_WIFI_NPD     94
+#define IGEP2_RB_GPIO_WIFI_NRESET  95
+#define IGEP2_RB_GPIO_BT_NRESET    137
+#define IGEP2_RC_GPIO_WIFI_NPD     138
+#define IGEP2_RC_GPIO_WIFI_NRESET  139
+#define IGEP2_RC_GPIO_BT_NRESET    137
+
+/*
+ * IGEP2 Hardware Revision Table
+ *
+ *  --------------------------------------------------------------------------
+ * | Id. | Hw Rev.            | HW0 (28) | WIFI_NPD | WIFI_NRESET | BT_NRESET |
+ *  --------------------------------------------------------------------------
+ * |  0  | B                  |   high   |  gpio94  |   gpio95    |     -     |
+ * |  0  | B/C (B-compatible) |   high   |  gpio94  |   gpio95    |  gpio137  |
+ * |  1  | C                  |   low    |  gpio138 |   gpio139   |  gpio137  |
+ *  --------------------------------------------------------------------------
+ */
+
+#define IGEP2_BOARD_HWREV_B    0
+#define IGEP2_BOARD_HWREV_C    1
+
+static u8 hwrev;
+
+static void __init igep2_get_revision(void)
+{
+       u8 ret;
+
+       omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT);
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "GPIO_HW0_REV") == 0) &&
+           (gpio_direction_input(IGEP2_GPIO_LED1_RED) == 0)) {
+               ret = gpio_get_value(IGEP2_GPIO_LED1_RED);
+               if (ret == 0) {
+                       pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_C;
+               } else if (ret ==  1) {
+                       pr_info("IGEP2: Hardware Revision B/C (B compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_B;
+               } else {
+                       pr_err("IGEP2: Unknown Hardware Revision\n");
+                       hwrev = -1;
+               }
+       } else {
+               pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n");
+               pr_err("IGEP2: Unknown Hardware Revision\n");
+       }
+
+       gpio_free(IGEP2_GPIO_LED1_RED);
+}
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
        defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
@@ -107,7 +157,7 @@ static struct platform_device igep2_onenand_device = {
        },
 };
 
-void __init igep2_flash_init(void)
+static void __init igep2_flash_init(void)
 {
        u8              cs = 0;
        u8              onenandcs = GPMC_CS_NUM + 1;
@@ -141,7 +191,7 @@ void __init igep2_flash_init(void)
 }
 
 #else
-void __init igep2_flash_init(void) {}
+static void __init igep2_flash_init(void) {}
 #endif
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -211,10 +261,6 @@ static struct regulator_consumer_supply igep2_vmmc1_supply = {
        .supply         = "vmmc",
 };
 
-static struct regulator_consumer_supply igep2_vmmc2_supply = {
-       .supply         = "vmmc",
-};
-
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
        .constraints = {
@@ -230,37 +276,95 @@ static struct regulator_init_data igep2_vmmc1 = {
        .consumer_supplies      = &igep2_vmmc1_supply,
 };
 
-/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
-static struct regulator_init_data igep2_vmmc2 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &igep2_vmmc2_supply,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#endif
        {}      /* Terminator */
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep2_gpio_leds[] = {
+       [0] = {
+               .name                   = "gpio-led:red:d0",
+               .gpio                   = IGEP2_GPIO_LED0_RED,
+               .default_trigger        = "default-off"
+       },
+       [1] = {
+               .name                   = "gpio-led:green:d0",
+               .gpio                   = IGEP2_GPIO_LED0_GREEN,
+               .default_trigger        = "default-off",
+       },
+       [2] = {
+               .name                   = "gpio-led:red:d1",
+               .gpio                   = IGEP2_GPIO_LED1_RED,
+               .default_trigger        = "default-off",
+       },
+       [3] = {
+               .name                   = "gpio-led:green:d1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = -EINVAL, /* gets replaced */
+       },
+};
+
+static struct gpio_led_platform_data igep2_led_pdata = {
+       .leds           = igep2_gpio_leds,
+       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
+};
+
+static struct platform_device igep2_led_device = {
+        .name   = "leds-gpio",
+        .id     = -1,
+        .dev    = {
+                .platform_data  =  &igep2_led_pdata,
+       },
+};
+
+static void __init igep2_leds_init(void)
+{
+       platform_device_register(&igep2_led_device);
+}
+
+#else
+static inline void igep2_leds_init(void)
+{
+       if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED1_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
+
+}
+#endif
+
 static int igep2_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
@@ -268,20 +372,48 @@ static int igep2_twl_gpio_setup(struct device *dev,
        mmc[0].gpio_cd = gpio + 0;
        omap2_hsmmc_init(mmc);
 
-       /* link regulators to MMC adapters ... we "know" the
+       /*
+        * link regulators to MMC adapters ... we "know" the
         * regulators will be set up only *after* we return.
-       */
+        */
        igep2_vmmc1_supply.dev = mmc[0].dev;
-       igep2_vmmc2_supply.dev = mmc[1].dev;
+
+       /*
+        * REVISIT: need ehci-omap hooks for external VBUS
+        * power switch and overcurrent detect
+        */
+       if ((gpio_request(gpio + 1, "GPIO_EHCI_NOC") < 0) ||
+           (gpio_direction_input(gpio + 1) < 0))
+               pr_err("IGEP2: Could not obtain gpio for EHCI NOC");
+
+       /*
+        * TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN
+        * (out, active low)
+        */
+       if ((gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USBH_CPEN") < 0) ||
+           (gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0) < 0))
+               pr_err("IGEP2: Could not obtain gpio for USBH_CPEN");
+
+       /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+       if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+           && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+               gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+               gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+       igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
 
        return 0;
 };
 
-static struct twl4030_gpio_platform_data igep2_gpio_data = {
+static struct twl4030_gpio_platform_data igep2_twl4030_gpio_pdata = {
        .gpio_base      = OMAP_MAX_GPIO_LINES,
        .irq_base       = TWL4030_GPIO_IRQ_BASE,
        .irq_end        = TWL4030_GPIO_IRQ_END,
-       .use_leds       = false,
+       .use_leds       = true,
        .setup          = igep2_twl_gpio_setup,
 };
 
@@ -355,47 +487,6 @@ static void __init igep2_display_init(void)
                pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
 }
 
-#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
-#include <linux/leds.h>
-
-static struct gpio_led igep2_gpio_leds[] = {
-       {
-               .name = "led0:red",
-               .gpio = IGEP2_GPIO_LED0_RED,
-       },
-       {
-               .name = "led0:green",
-               .default_trigger = "heartbeat",
-               .gpio = IGEP2_GPIO_LED0_GREEN,
-       },
-       {
-               .name = "led1:red",
-               .gpio = IGEP2_GPIO_LED1_RED,
-       },
-};
-
-static struct gpio_led_platform_data igep2_led_pdata = {
-       .leds           = igep2_gpio_leds,
-       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
-};
-
-static struct platform_device igep2_led_device = {
-        .name   = "leds-gpio",
-        .id     = -1,
-        .dev    = {
-                .platform_data  =  &igep2_led_pdata,
-       },
-};
-
-static void __init igep2_init_led(void)
-{
-       platform_device_register(&igep2_led_device);
-}
-
-#else
-static inline void igep2_init_led(void) {}
-#endif
-
 static struct platform_device *igep2_devices[] __initdata = {
        &igep2_dss_device,
 };
@@ -425,14 +516,13 @@ static struct twl4030_platform_data igep2_twldata = {
        /* platform_data for children goes here */
        .usb            = &igep2_usb_data,
        .codec          = &igep2_codec_data,
-       .gpio           = &igep2_gpio_data,
+       .gpio           = &igep2_twl4030_gpio_pdata,
        .vmmc1          = &igep2_vmmc1,
-       .vmmc2          = &igep2_vmmc2,
        .vpll2          = &igep2_vpll2,
 
 };
 
-static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
        {
                I2C_BOARD_INFO("twl4030", 0x48),
                .flags          = I2C_CLIENT_WAKE,
@@ -441,14 +531,29 @@ static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
        },
 };
 
-static int __init igep2_i2c_init(void)
+static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
+static void __init igep2_i2c_init(void)
 {
-       omap_register_i2c_bus(1, 2600, igep2_i2c_boardinfo,
-                       ARRAY_SIZE(igep2_i2c_boardinfo));
-       /* Bus 3 is attached to the DVI port where devices like the pico DLP
-        * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 100, NULL, 0);
-       return 0;
+       int ret;
+
+       ret = omap_register_i2c_bus(1, 2600, igep2_i2c1_boardinfo,
+               ARRAY_SIZE(igep2_i2c1_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C1 bus (%d)\n", ret);
+
+       /*
+        * Bus 3 is attached to the DVI port where devices like the pico DLP
+        * projector don't work reliably with 400kHz
+        */
+       ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo,
+               ARRAY_SIZE(igep2_i2c3_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -476,9 +581,57 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux      NULL
 #endif
 
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep2_wlan_bt_init(void)
+{
+       unsigned npd, wreset, btreset;
+
+       /* GPIO's for WLAN-BT combo depends on hardware revision */
+       if (hwrev == IGEP2_BOARD_HWREV_B) {
+               npd = IGEP2_RB_GPIO_WIFI_NPD;
+               wreset = IGEP2_RB_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RB_GPIO_BT_NRESET;
+       } else if (hwrev == IGEP2_BOARD_HWREV_C) {
+               npd = IGEP2_RC_GPIO_WIFI_NPD;
+               wreset = IGEP2_RC_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RC_GPIO_BT_NRESET;
+       } else
+               return;
+
+       /* Set GPIO's for  WLAN-BT combo module */
+       if ((gpio_request(npd, "GPIO_WIFI_NPD") == 0) &&
+           (gpio_direction_output(npd, 1) == 0)) {
+               gpio_export(npd, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+       if ((gpio_request(wreset, "GPIO_WIFI_NRESET") == 0) &&
+           (gpio_direction_output(wreset, 1) == 0)) {
+               gpio_export(wreset, 0);
+               gpio_set_value(wreset, 0);
+               udelay(10);
+               gpio_set_value(wreset, 1);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+       if ((gpio_request(btreset, "GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(btreset, 1) == 0)) {
+               gpio_export(btreset, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+static inline void __init igep2_wlan_bt_init(void) { }
+#endif
+
 static void __init igep2_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+       /* Get IGEP2 hardware revision */
+       igep2_get_revision();
+       /* Register I2C busses and drivers */
        igep2_i2c_init();
        platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
        omap_serial_init();
@@ -486,50 +639,16 @@ static void __init igep2_init(void)
        usb_ehci_init(&ehci_pdata);
 
        igep2_flash_init();
-       igep2_init_led();
+       igep2_leds_init();
        igep2_display_init();
        igep2_init_smsc911x();
 
-       /* GPIO userspace leds */
-#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
-       if ((gpio_request(IGEP2_GPIO_LED0_RED, "led0:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "led0:green") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED1_RED, "led1:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED1_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
-#endif
-
-       /* GPIO W-LAN + Bluetooth combo module */
-       if ((gpio_request(IGEP2_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NPD, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NPD, 0);
-/*             gpio_set_value(IGEP2_GPIO_WIFI_NPD, 0); */
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NPD\n");
+       /*
+        * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+        * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+        */
+       igep2_wlan_bt_init();
 
-       if ((gpio_request(IGEP2_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NRESET, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NRESET, 0);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 0);
-               udelay(10);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 1);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NRESET\n");
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
new file mode 100644 (file)
index 0000000..22b0b25
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2010 - ISEE 2007 SL
+ *
+ * Modified from mach-omap2/board-generic.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc.h>
+#include <plat/usb.h>
+#include <plat/onenand.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "sdram-numonyx-m65kxxxxam.h"
+
+#define IGEP3_GPIO_LED0_GREEN  54
+#define IGEP3_GPIO_LED0_RED    53
+#define IGEP3_GPIO_LED1_RED    16
+
+#define IGEP3_GPIO_WIFI_NPD    138
+#define IGEP3_GPIO_WIFI_NRESET 139
+#define IGEP3_GPIO_BT_NRESET   137
+
+#define IGEP3_GPIO_USBH_NRESET  115
+
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+       defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+#define ONENAND_MAP             0x20000000
+
+/*
+ * x2 Flash built-in COMBO POP MEMORY
+ * Since the device is equipped with two DataRAMs, and two-plane NAND
+ * Flash memory array, these two component enables simultaneous program
+ * of 4KiB. Plane1 has only even blocks such as block0, block2, block4
+ * while Plane2 has only odd blocks such as block1, block3, block5.
+ * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
+ */
+
+static struct mtd_partition igep3_onenand_partitions[] = {
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 2 * (64*(2*2048))
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 6 * (64*(2*2048)),
+       },
+       {
+               .name           = "Environment",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2 * (64*(2*2048)),
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 12 * (64*(2*2048)),
+       },
+       {
+               .name           = "File System",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_onenand_platform_data igep3_onenand_pdata = {
+       .parts = igep3_onenand_partitions,
+       .nr_parts = ARRAY_SIZE(igep3_onenand_partitions),
+       .onenand_setup = NULL,
+       .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
+};
+
+static struct platform_device igep3_onenand_device = {
+       .name           = "omap2-onenand",
+       .id             = -1,
+       .dev = {
+               .platform_data = &igep3_onenand_pdata,
+       },
+};
+
+void __init igep3_flash_init(void)
+{
+       u8 cs = 0;
+       u8 onenandcs = GPMC_CS_NUM + 1;
+
+       for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+               u32 ret;
+               ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               /* Check if NAND/oneNAND is configured */
+               if ((ret & 0xC00) == 0x800)
+                       /* NAND found */
+                       pr_err("IGEP3: Unsupported NAND found\n");
+               else {
+                       ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+
+                       if ((ret & 0x3F) == (ONENAND_MAP >> 24))
+                               /* OneNAND found */
+                               onenandcs = cs;
+               }
+       }
+
+       if (onenandcs > GPMC_CS_NUM) {
+               pr_err("IGEP3: Unable to find configuration in GPMC\n");
+               return;
+       }
+
+       igep3_onenand_pdata.cs = onenandcs;
+
+       if (platform_device_register(&igep3_onenand_device) < 0)
+               pr_err("IGEP3: Unable to register OneNAND device\n");
+}
+
+#else
+void __init igep3_flash_init(void) {}
+#endif
+
+static struct regulator_consumer_supply igep3_vmmc1_supply = {
+       .supply         = "vmmc",
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data igep3_vmmc1 = {
+       .constraints = {
+               .min_uV                 = 1850000,
+               .max_uV                 = 3150000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &igep3_vmmc1_supply,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+       [0] = {
+               .mmc            = 1,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+       [1] = {
+               .mmc            = 2,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+#endif
+       {}      /* Terminator */
+};
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep3_gpio_leds[] = {
+       [0] = {
+               .name                   = "gpio-led:red:d0",
+               .gpio                   = IGEP3_GPIO_LED0_RED,
+               .default_trigger        = "default-off"
+       },
+       [1] = {
+               .name                   = "gpio-led:green:d0",
+               .gpio                   = IGEP3_GPIO_LED0_GREEN,
+               .default_trigger        = "default-off",
+       },
+       [2] = {
+               .name                   = "gpio-led:red:d1",
+               .gpio                   = IGEP3_GPIO_LED1_RED,
+               .default_trigger        = "default-off",
+       },
+       [3] = {
+               .name                   = "gpio-led:green:d1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = -EINVAL, /* gets replaced */
+       },
+};
+
+static struct gpio_led_platform_data igep3_led_pdata = {
+       .leds           = igep3_gpio_leds,
+       .num_leds       = ARRAY_SIZE(igep3_gpio_leds),
+};
+
+static struct platform_device igep3_led_device = {
+        .name   = "leds-gpio",
+        .id     = -1,
+        .dev    = {
+                .platform_data = &igep3_led_pdata,
+       },
+};
+
+static void __init igep3_leds_init(void)
+{
+       platform_device_register(&igep3_led_device);
+}
+
+#else
+static inline void igep3_leds_init(void)
+{
+       if ((gpio_request(IGEP3_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_LED0_RED, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED0_RED, 0);
+               gpio_set_value(IGEP3_GPIO_LED0_RED, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_RED\n");
+
+       if ((gpio_request(IGEP3_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_LED0_GREEN, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED0_GREEN, 0);
+               gpio_set_value(IGEP3_GPIO_LED0_GREEN, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+       if ((gpio_request(IGEP3_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+               (gpio_direction_output(IGEP3_GPIO_LED1_RED, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED1_RED, 0);
+               gpio_set_value(IGEP3_GPIO_LED1_RED, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_RED\n");
+}
+#endif
+
+static int igep3_twl4030_gpio_setup(struct device *dev,
+               unsigned gpio, unsigned ngpio)
+{
+       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+       mmc[0].gpio_cd = gpio + 0;
+       omap2_hsmmc_init(mmc);
+
+       /*
+        * link regulators to MMC adapters ... we "know" the
+        * regulators will be set up only *after* we return.
+        */
+       igep3_vmmc1_supply.dev = mmc[0].dev;
+
+       /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+       if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+           && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+               gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+               gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+       igep3_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
+       return 0;
+};
+
+static struct twl4030_gpio_platform_data igep3_twl4030_gpio_pdata = {
+       .gpio_base      = OMAP_MAX_GPIO_LINES,
+       .irq_base       = TWL4030_GPIO_IRQ_BASE,
+       .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
+       .setup          = igep3_twl4030_gpio_setup,
+};
+
+static struct twl4030_usb_data igep3_twl4030_usb_data = {
+       .usb_mode       = T2_USB_MODE_ULPI,
+};
+
+static void __init igep3_init_irq(void)
+{
+       omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct twl4030_platform_data igep3_twl4030_pdata = {
+       .irq_base       = TWL4030_IRQ_BASE,
+       .irq_end        = TWL4030_IRQ_END,
+
+       /* platform_data for children goes here */
+       .usb            = &igep3_twl4030_usb_data,
+       .gpio           = &igep3_twl4030_gpio_pdata,
+       .vmmc1          = &igep3_vmmc1,
+};
+
+static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("twl4030", 0x48),
+               .flags          = I2C_CLIENT_WAKE,
+               .irq            = INT_34XX_SYS_NIRQ,
+               .platform_data  = &igep3_twl4030_pdata,
+       },
+};
+
+static int __init igep3_i2c_init(void)
+{
+       omap_register_i2c_bus(1, 2600, igep3_i2c_boardinfo,
+                       ARRAY_SIZE(igep3_i2c_boardinfo));
+
+       return 0;
+}
+
+static struct omap_musb_board_data musb_board_data = {
+       .interface_type = MUSB_INTERFACE_ULPI,
+       .mode           = MUSB_OTG,
+       .power          = 100,
+};
+
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep3_wifi_bt_init(void)
+{
+       /* Configure MUX values for W-LAN + Bluetooth GPIO's */
+       omap_mux_init_gpio(IGEP3_GPIO_WIFI_NPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(IGEP3_GPIO_WIFI_NRESET, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(IGEP3_GPIO_BT_NRESET, OMAP_PIN_OUTPUT);
+
+       /* Set GPIO's for  W-LAN + Bluetooth combo module */
+       if ((gpio_request(IGEP3_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_WIFI_NPD, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_WIFI_NPD, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+       if ((gpio_request(IGEP3_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_WIFI_NRESET, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_WIFI_NRESET, 0);
+               gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 0);
+               udelay(10);
+               gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+       if ((gpio_request(IGEP3_GPIO_BT_NRESET, "GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_BT_NRESET, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_BT_NRESET, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+void __init igep3_wifi_bt_init(void) {}
+#endif
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux      NULL
+#endif
+
+static void __init igep3_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+       /* Register I2C busses and drivers */
+       igep3_i2c_init();
+
+       omap_serial_init();
+       usb_musb_init(&musb_board_data);
+
+       igep3_flash_init();
+       igep3_leds_init();
+
+       /*
+        * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+        * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+        */
+       igep3_wifi_bt_init();
+
+}
+
+MACHINE_START(IGEP0030, "IGEP OMAP3 module")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = igep3_init_irq,
+       .init_machine   = igep3_init,
+       .timer          = &omap_timer,
+MACHINE_END
index f28fd77..001fd97 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/board-zoom.h>
 
 #include <asm/delay.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "control.h"
 
 #define LDP_SMSC911X_CS                1
 #define LDP_SMSC911X_GPIO      152
@@ -82,7 +84,7 @@ static struct platform_device ldp_smsc911x_device = {
        },
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_1),
        KEY(1, 0, KEY_2),
        KEY(2, 0, KEY_3),
@@ -362,7 +364,7 @@ static int __init omap_i2c_init(void)
 static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
index 3f79668..e823c70 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <sound/tlv320aic3x.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -383,15 +384,6 @@ static void n8x0_mmc_callback(void *data, u8 card_mask)
        omap_mmc_notify_cover_event(mmc_device, index, *openp);
 }
 
-void n8x0_mmc_slot1_cover_handler(void *arg, int closed_state)
-{
-       if (mmc_device == NULL)
-               return;
-
-       slot1_cover_open = !closed_state;
-       omap_mmc_notify_cover_event(mmc_device, 0, closed_state);
-}
-
 static int n8x0_mmc_late_init(struct device *dev)
 {
        int r, bit, *openp;
@@ -511,7 +503,7 @@ static struct omap_mmc_platform_data mmc1_data = {
 
 static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
 
-void __init n8x0_mmc_init(void)
+static void __init n8x0_mmc_init(void)
 
 {
        int err;
@@ -560,11 +552,6 @@ void __init n8x0_mmc_init(void)
 void __init n8x0_mmc_init(void)
 {
 }
-
-void n8x0_mmc_slot1_cover_handler(void *arg, int state)
-{
-}
-
 #endif /* CONFIG_MMC_OMAP */
 
 #ifdef CONFIG_MENELAUS
@@ -614,29 +601,35 @@ static int n8x0_menelaus_late_init(struct device *dev)
        return 0;
 }
 
-static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {
+#else
+static int n8x0_menelaus_late_init(struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = {
+       .late_init = n8x0_menelaus_late_init,
+};
+
+static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] __initdata = {
        {
                I2C_BOARD_INFO("menelaus", 0x72),
                .irq = INT_24XX_SYS_NIRQ,
+               .platform_data = &n8x0_menelaus_platform_data,
        },
 };
 
-static struct menelaus_platform_data n8x0_menelaus_platform_data = {
-       .late_init = n8x0_menelaus_late_init,
+static struct aic3x_pdata n810_aic33_data __initdata = {
+       .gpio_reset = 118,
 };
 
-static void __init n8x0_menelaus_init(void)
-{
-       n8x0_i2c_board_info_1[0].platform_data = &n8x0_menelaus_platform_data;
-       omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
-                             ARRAY_SIZE(n8x0_i2c_board_info_1));
-}
-
-#else
-static inline void __init n8x0_menelaus_init(void)
-{
-}
-#endif
+static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
+       {
+               I2C_BOARD_INFO("tlv320aic3x", 0x18),
+               .platform_data = &n810_aic33_data,
+       },
+};
 
 static void __init n8x0_map_io(void)
 {
@@ -653,6 +646,11 @@ static void __init n8x0_init_irq(void)
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+       /* I2S codec port pins for McBSP block */
+       OMAP2420_MUX(EAC_AC_SCLK, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_FS, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_DIN, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -665,9 +663,14 @@ static void __init n8x0_init_machine(void)
        /* FIXME: add n810 spi devices */
        spi_register_board_info(n800_spi_board_info,
                                ARRAY_SIZE(n800_spi_board_info));
+       omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
+                             ARRAY_SIZE(n8x0_i2c_board_info_1));
+       omap_register_i2c_bus(2, 400, NULL, 0);
+       if (machine_is_nokia_n810())
+               i2c_register_board_info(2, n810_i2c_board_info_2,
+                                       ARRAY_SIZE(n810_i2c_board_info_2));
 
        omap_serial_init();
-       n8x0_menelaus_init();
        n8x0_onenand_init();
        n8x0_mmc_init();
        n8x0_usb_init();
index 9d9f5b8..14f4224 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE                SZ_128K
 
+/*
+ * OMAP3 Beagle revision
+ * Run time detection of Beagle revision is done by reading GPIO.
+ * GPIO ID -
+ *     AXBX    = GPIO173, GPIO172, GPIO171: 1 1 1
+ *     C1_3    = GPIO173, GPIO172, GPIO171: 1 1 0
+ *     C4      = GPIO173, GPIO172, GPIO171: 1 0 1
+ *     XM      = GPIO173, GPIO172, GPIO171: 0 0 0
+ */
+enum {
+       OMAP3BEAGLE_BOARD_UNKN = 0,
+       OMAP3BEAGLE_BOARD_AXBX,
+       OMAP3BEAGLE_BOARD_C1_3,
+       OMAP3BEAGLE_BOARD_C4,
+       OMAP3BEAGLE_BOARD_XM,
+};
+
+static u8 omap3_beagle_version;
+
+static u8 omap3_beagle_get_rev(void)
+{
+       return omap3_beagle_version;
+}
+
+static void __init omap3_beagle_init_rev(void)
+{
+       int ret;
+       u16 beagle_rev = 0;
+
+       omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP);
+
+       ret = gpio_request(171, "rev_id_0");
+       if (ret < 0)
+               goto fail0;
+
+       ret = gpio_request(172, "rev_id_1");
+       if (ret < 0)
+               goto fail1;
+
+       ret = gpio_request(173, "rev_id_2");
+       if (ret < 0)
+               goto fail2;
+
+       gpio_direction_input(171);
+       gpio_direction_input(172);
+       gpio_direction_input(173);
+
+       beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
+                       | (gpio_get_value(173) << 2);
+
+       switch (beagle_rev) {
+       case 7:
+               printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+               break;
+       case 6:
+               printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+               break;
+       case 5:
+               printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+               break;
+       case 0:
+               printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+               break;
+       default:
+               printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+       }
+
+       return;
+
+fail2:
+       gpio_free(172);
+fail1:
+       gpio_free(171);
+fail0:
+       printk(KERN_ERR "Unable to get revision detection GPIO pins\n");
+       omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+
+       return;
+}
+
 static struct mtd_partition omap3beagle_nand_partitions[] = {
        /* All the partition sizes are listed in terms of NAND block size */
        {
@@ -166,7 +254,7 @@ static void __init beagle_display_init(void)
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
@@ -185,7 +273,10 @@ static struct gpio_led gpio_leds[];
 static int beagle_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
-       if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+       if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+               mmc[0].gpio_wp = -EINVAL;
+       } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
+               (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
                omap_mux_init_gpio(23, OMAP_PIN_INPUT);
                mmc[0].gpio_wp = 23;
        } else {
@@ -322,13 +413,19 @@ static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
        },
 };
 
+static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
 static int __init omap3_beagle_i2c_init(void)
 {
        omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
                        ARRAY_SIZE(beagle_i2c_boardinfo));
        /* Bus 3 is attached to the DVI port where devices like the pico DLP
         * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 100, NULL, 0);
+       omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
        return 0;
 }
 
@@ -464,6 +561,7 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init omap3_beagle_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap3_beagle_init_rev();
        omap3_beagle_i2c_init();
        platform_add_devices(omap3_beagle_devices,
                        ARRAY_SIZE(omap3_beagle_devices));
index 8936e4f..b04365c 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/smsc911x.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -370,7 +371,7 @@ static struct regulator_init_data omap3evm_vsim = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 63,
        },
@@ -446,7 +447,7 @@ static struct twl4030_usb_data omap3evm_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_DOWN),
        KEY(0, 2, KEY_ENTER),
@@ -584,7 +585,7 @@ static int ads7846_get_pendown_state(void)
        return !gpio_get_value(OMAP3_EVM_TS_GPIO);
 }
 
-struct ads7846_platform_data ads7846_config = {
+static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
        .x_plate_ohms           = 180,
@@ -603,7 +604,7 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .single_channel = 1,    /* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3evm_spi_board_info[] = {
+static struct spi_board_info omap3evm_spi_board_info[] = {
        [0] = {
                .modalias               = "ads7846",
                .bus_num                = 1,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
new file mode 100644 (file)
index 0000000..5f7d2c1
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3logic.c
+ *
+ * Copyright (C) 2010 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Copyright (C) 2010 Logic Product Development, Inc.
+ * Peter Barada <peter.barada@logicpd.com>
+ *
+ * Modified from Beagle, EVM, and RX51
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <linux/regulator/machine.h>
+
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
+
+#include <plat/mux.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc-smsc911x.h>
+#include <plat/gpmc.h>
+#include <plat/sdrc.h>
+
+#define OMAP3LOGIC_SMSC911X_CS                 1
+
+#define OMAP3530_LV_SOM_MMC_GPIO_CD            110
+#define OMAP3530_LV_SOM_MMC_GPIO_WP            126
+#define OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ      152
+
+#define OMAP3_TORPEDO_MMC_GPIO_CD              127
+#define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ                129
+
+static struct regulator_consumer_supply omap3logic_vmmc1_supply = {
+       .supply                 = "vmmc",
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data omap3logic_vmmc1 = {
+       .constraints = {
+               .name                   = "VMMC1",
+               .min_uV                 = 1850000,
+               .max_uV                 = 3150000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &omap3logic_vmmc1_supply,
+};
+
+static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
+       .gpio_base      = OMAP_MAX_GPIO_LINES,
+       .irq_base       = TWL4030_GPIO_IRQ_BASE,
+       .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
+       .pullups        = BIT(1),
+       .pulldowns      = BIT(2)  | BIT(6)  | BIT(7)  | BIT(8)
+                       | BIT(13) | BIT(15) | BIT(16) | BIT(17),
+};
+
+static struct twl4030_platform_data omap3logic_twldata = {
+       .irq_base       = TWL4030_IRQ_BASE,
+       .irq_end        = TWL4030_IRQ_END,
+
+       /* platform_data for children goes here */
+       .gpio           = &omap3logic_gpio_data,
+       .vmmc1          = &omap3logic_vmmc1,
+};
+
+static struct i2c_board_info __initdata omap3logic_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("twl4030", 0x48),
+               .flags = I2C_CLIENT_WAKE,
+               .irq = INT_34XX_SYS_NIRQ,
+               .platform_data = &omap3logic_twldata,
+       },
+};
+
+static int __init omap3logic_i2c_init(void)
+{
+       omap_register_i2c_bus(1, 2600, omap3logic_i2c_boardinfo,
+                               ARRAY_SIZE(omap3logic_i2c_boardinfo));
+       return 0;
+}
+
+static struct omap2_hsmmc_info __initdata board_mmc_info[] = {
+       {
+               .name           = "external",
+               .mmc            = 1,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+       {}      /* Terminator */
+};
+
+static void __init board_mmc_init(void)
+{
+       if (machine_is_omap3530_lv_som()) {
+               /* OMAP3530 LV SOM board */
+               board_mmc_info[0].gpio_cd = OMAP3530_LV_SOM_MMC_GPIO_CD;
+               board_mmc_info[0].gpio_wp = OMAP3530_LV_SOM_MMC_GPIO_WP;
+               omap_mux_init_signal("gpio_110", OMAP_PIN_OUTPUT);
+               omap_mux_init_signal("gpio_126", OMAP_PIN_OUTPUT);
+       } else if (machine_is_omap3_torpedo()) {
+               /* OMAP3 Torpedo board */
+               board_mmc_info[0].gpio_cd = OMAP3_TORPEDO_MMC_GPIO_CD;
+               omap_mux_init_signal("gpio_127", OMAP_PIN_OUTPUT);
+       } else {
+               /* unsupported board */
+               printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+               return;
+       }
+
+       omap2_hsmmc_init(board_mmc_info);
+       /* link regulators to MMC adapters */
+       omap3logic_vmmc1_supply.dev = board_mmc_info[0].dev;
+}
+
+static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
+       .cs             = OMAP3LOGIC_SMSC911X_CS,
+       .gpio_irq       = -EINVAL,
+       .gpio_reset     = -EINVAL,
+       .flags          = IORESOURCE_IRQ_LOWLEVEL,
+};
+
+/* TODO/FIXME (comment by Peter Barada, LogicPD):
+ * Fix the PBIAS voltage for Torpedo MMC1 pins that
+ * are used for other needs (IRQs, etc).            */
+static void omap3torpedo_fix_pbias_voltage(void)
+{
+       u16 control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+       u32 reg;
+
+       if (machine_is_omap3_torpedo())
+       {
+               /* Set the bias for the pin */
+               reg = omap_ctrl_readl(control_pbias_offset);
+
+               reg &= ~OMAP343X_PBIASLITEPWRDNZ1;
+               omap_ctrl_writel(reg, control_pbias_offset);
+
+               /* 100ms delay required for PBIAS configuration */
+               msleep(100);
+
+               reg |= OMAP343X_PBIASLITEVMODE1;
+               reg |= OMAP343X_PBIASLITEPWRDNZ1;
+               omap_ctrl_writel(reg | 0x300, control_pbias_offset);
+       }
+}
+
+static inline void __init board_smsc911x_init(void)
+{
+       if (machine_is_omap3530_lv_som()) {
+               /* OMAP3530 LV SOM board */
+               board_smsc911x_data.gpio_irq =
+                                       OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ;
+               omap_mux_init_signal("gpio_152", OMAP_PIN_INPUT);
+       } else if (machine_is_omap3_torpedo()) {
+               /* OMAP3 Torpedo board */
+               board_smsc911x_data.gpio_irq = OMAP3_TORPEDO_SMSC911X_GPIO_IRQ;
+               omap_mux_init_signal("gpio_129", OMAP_PIN_INPUT);
+       } else {
+               /* unsupported board */
+               printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+               return;
+       }
+
+       gpmc_smsc911x_init(&board_smsc911x_data);
+}
+
+static void __init omap3logic_init_irq(void)
+{
+       omap2_init_common_hw(NULL, NULL);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux       NULL
+#endif
+
+static void __init omap3logic_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap3torpedo_fix_pbias_voltage();
+       omap3logic_i2c_init();
+       omap_serial_init();
+       board_mmc_init();
+       board_smsc911x_init();
+
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+}
+
+MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = omap3logic_init_irq,
+       .init_machine   = omap3logic_init,
+       .timer          = &omap_timer,
+MACHINE_END
+
+MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = omap3logic_init_irq,
+       .init_machine   = omap3logic_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 41d6f54..89ed1be 100644 (file)
@@ -32,7 +32,9 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -276,14 +278,14 @@ static void pandora_wl1251_init_card(struct mmc_card *card)
 static struct omap2_hsmmc_info omap3pandora_mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 126,
                .ext_clock      = 0,
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 127,
                .ext_clock      = 1,
@@ -291,7 +293,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
        },
        {
                .mmc            = 3,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .init_card      = pandora_wl1251_init_card,
@@ -344,6 +346,9 @@ static struct regulator_consumer_supply pandora_vmmc1_supply =
 static struct regulator_consumer_supply pandora_vmmc2_supply =
        REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
 
+static struct regulator_consumer_supply pandora_vmmc3_supply =
+       REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2");
+
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
        REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
@@ -488,6 +493,33 @@ static struct regulator_init_data pandora_vsim = {
        .consumer_supplies      = &pandora_adac_supply,
 };
 
+/* Fixed regulator internal to Wifi module */
+static struct regulator_init_data pandora_vmmc3 = {
+       .constraints = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &pandora_vmmc3_supply,
+};
+
+static struct fixed_voltage_config pandora_vwlan = {
+       .supply_name            = "vwlan",
+       .microvolts             = 1800000, /* 1.8V */
+       .gpio                   = PANDORA_WIFI_NRESET_GPIO,
+       .startup_delay          = 50000, /* 50ms */
+       .enable_high            = 1,
+       .enabled_at_boot        = 0,
+       .init_data              = &pandora_vmmc3,
+};
+
+static struct platform_device pandora_vwlan_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 1,
+       .dev = {
+               .platform_data = &pandora_vwlan,
+       },
+};
+
 static struct twl4030_usb_data omap3pandora_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
@@ -501,6 +533,8 @@ static struct twl4030_codec_data omap3pandora_codec_data = {
        .audio = &omap3pandora_audio_data,
 };
 
+static struct twl4030_bci_platform_data pandora_bci_data;
+
 static struct twl4030_platform_data omap3pandora_twldata = {
        .irq_base       = TWL4030_IRQ_BASE,
        .irq_end        = TWL4030_IRQ_END,
@@ -516,6 +550,7 @@ static struct twl4030_platform_data omap3pandora_twldata = {
        .vaux4          = &pandora_vaux4,
        .vsim           = &pandora_vsim,
        .keypad         = &pandora_kp_data,
+       .bci            = &pandora_bci_data,
 };
 
 static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = {
@@ -644,19 +679,8 @@ static void pandora_wl1251_init(void)
        if (pandora_wl1251_pdata.irq < 0)
                goto fail_irq;
 
-       ret = gpio_request(PANDORA_WIFI_NRESET_GPIO, "wl1251 nreset");
-       if (ret < 0)
-               goto fail_irq;
-
-       /* start powered so that it probes with MMC subsystem */
-       ret = gpio_direction_output(PANDORA_WIFI_NRESET_GPIO, 1);
-       if (ret < 0)
-               goto fail_nreset;
-
        return;
 
-fail_nreset:
-       gpio_free(PANDORA_WIFI_NRESET_GPIO);
 fail_irq:
        gpio_free(PANDORA_WIFI_IRQ_GPIO);
 fail:
@@ -668,6 +692,7 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
        &pandora_keys_gpio,
        &pandora_dss_device,
        &pandora_wl1251_data,
+       &pandora_vwlan_device,
 };
 
 static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
index bc5ac83..f252721 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -38,7 +39,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -52,6 +52,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #define OMAP3STALKER_ETHR_START        0x2c000000
@@ -275,7 +276,7 @@ static struct regulator_init_data omap3stalker_vsim = {
 static struct omap2_hsmmc_info mmc[] = {
        {
         .mmc           = 1,
-        .wires         = 4,
+        .caps          = MMC_CAP_4_BIT_DATA,
         .gpio_cd       = -EINVAL,
         .gpio_wp       = 23,
         },
@@ -389,7 +390,7 @@ static struct twl4030_usb_data omap3stalker_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_DOWN),
        KEY(0, 2, KEY_ENTER),
@@ -564,7 +565,7 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .single_channel         = 1,    /* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3stalker_spi_board_info[] = {
+static struct spi_board_info omap3stalker_spi_board_info[] = {
        [0] = {
               .modalias        = "ads7846",
               .bus_num         = 1,
index 0e99ce5..41104bb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <plat/mcspi.h>
 #include <linux/spi/spi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #include <asm/setup.h>
 
@@ -61,7 +62,7 @@
 #define TB_BL_PWM_TIMER                9
 #define TB_KILL_POWER_GPIO     168
 
-unsigned long touchbook_revision;
+static unsigned long touchbook_revision;
 
 static struct mtd_partition omap3touchbook_nand_partitions[] = {
        /* All the partition sizes are listed in terms of NAND block size */
@@ -108,7 +109,7 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
index db69bca..702f2a6 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include "timer-gp.h"
+
 #include "hsmmc.h"
+#include "control.h"
+
+#define GPIO_HUB_POWER         1
+#define GPIO_HUB_NRESET                62
+
+static struct gpio_led gpio_leds[] = {
+       {
+               .name                   = "pandaboard::status1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 7,
+       },
+       {
+               .name                   = "pandaboard::status2",
+               .default_trigger        = "mmc0",
+               .gpio                   = 8,
+       },
+};
 
+static struct gpio_led_platform_data gpio_led_info = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_led_info,
+       },
+};
+
+static struct platform_device *panda_devices[] __initdata = {
+       &leds_gpio,
+};
 
 static void __init omap4_panda_init_irq(void)
 {
@@ -47,6 +81,56 @@ static void __init omap4_panda_init_irq(void)
        omap_gpio_init();
 }
 
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+       .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+       .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+       .phy_reset  = false,
+       .reset_gpio_port[0]  = -EINVAL,
+       .reset_gpio_port[1]  = -EINVAL,
+       .reset_gpio_port[2]  = -EINVAL
+};
+
+static void __init omap4_ehci_init(void)
+{
+       int ret;
+
+
+       /* disable the power to the usb hub prior to init */
+       ret = gpio_request(GPIO_HUB_POWER, "hub_power");
+       if (ret) {
+               pr_err("Cannot request GPIO %d\n", GPIO_HUB_POWER);
+               goto error1;
+       }
+       gpio_export(GPIO_HUB_POWER, 0);
+       gpio_direction_output(GPIO_HUB_POWER, 0);
+       gpio_set_value(GPIO_HUB_POWER, 0);
+
+       /* reset phy+hub */
+       ret = gpio_request(GPIO_HUB_NRESET, "hub_nreset");
+       if (ret) {
+               pr_err("Cannot request GPIO %d\n", GPIO_HUB_NRESET);
+               goto error2;
+       }
+       gpio_export(GPIO_HUB_NRESET, 0);
+       gpio_direction_output(GPIO_HUB_NRESET, 0);
+       gpio_set_value(GPIO_HUB_NRESET, 0);
+       gpio_set_value(GPIO_HUB_NRESET, 1);
+
+       usb_ehci_init(&ehci_pdata);
+
+       /* enable power to hub */
+       gpio_set_value(GPIO_HUB_POWER, 1);
+       return;
+
+error2:
+       gpio_free(GPIO_HUB_POWER);
+error1:
+       pr_err("Unable to initialize EHCI power/reset\n");
+       return;
+
+}
+
 static struct omap_musb_board_data musb_board_data = {
        .interface_type         = MUSB_INTERFACE_UTMI,
        .mode                   = MUSB_PERIPHERAL,
@@ -56,7 +140,7 @@ static struct omap_musb_board_data musb_board_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = -EINVAL,
        },
        {}      /* Terminator */
@@ -67,10 +151,6 @@ static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
                .supply = "vmmc",
                .dev_name = "mmci-omap-hs.0",
        },
-       {
-               .supply = "vmmc",
-               .dev_name = "mmci-omap-hs.1",
-       },
 };
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
@@ -89,7 +169,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-       struct omap_mmc_platform_data *pdata = dev->platform_data;
+       struct omap_mmc_platform_data *pdata;
+
+       /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+       if (!dev) {
+               pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
+               return;
+       }
+       pdata = dev->platform_data;
 
        pdata->init =   omap4_twl6030_hsmmc_late_init;
 }
@@ -156,7 +243,7 @@ static struct regulator_init_data omap4_panda_vmmc = {
                                        | REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 2,
+       .num_consumer_supplies  = 1,
        .consumer_supplies      = omap4_panda_vmmc_supply,
 };
 
@@ -274,13 +361,13 @@ static int __init omap4_panda_i2c_init(void)
 }
 static void __init omap4_panda_init(void)
 {
-       int status;
-
        omap4_panda_i2c_init();
+       platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
        omap_serial_init();
        omap4_twl6030_hsmmc_init(mmc);
        /* OMAP4 Panda uses internal transceiver so register nop transceiver */
        usb_nop_xceiv_register();
+       omap4_ehci_init();
        /* FIXME: allow multi-omap to boot until musb is updated for omap4 */
        if (!cpu_is_omap44xx())
                usb_musb_init(&musb_board_data);
index 5e528ca..7053bc0 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -303,13 +304,13 @@ static void __init overo_flash_init(void)
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .transceiver    = true,
index ce28a85..4128529 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
+#include <sound/tlv320aic3x.h>
 
 #include <plat/mcspi.h>
 #include <plat/board.h>
@@ -32,6 +33,8 @@
 #include <plat/onenand.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <mach/board-rx51.h>
+
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
 
@@ -184,7 +187,7 @@ static void __init rx51_add_gpio_keys(void)
 }
 #endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        /*
         * Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
         * connected to the ground" matrix state.
@@ -302,7 +305,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "external",
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .cover_only     = true,
                .gpio_cd        = 160,
                .gpio_wp        = -EINVAL,
@@ -311,7 +314,8 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "internal",
                .mmc            = 2,
-               .wires          = 8, /* See also rx51_mmc2_remux */
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+                                               /* See also rx51_mmc2_remux */
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
@@ -689,7 +693,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
 };
 
 
-
 static struct twl4030_platform_data rx51_twldata __initdata = {
        .irq_base               = TWL4030_IRQ_BASE,
        .irq_end                = TWL4030_IRQ_END,
@@ -710,10 +713,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
        .vio                    = &rx51_vio,
 };
 
-static struct aic3x_pdata rx51_aic3x_data __initdata = {
-       .gpio_reset             = 60,
-};
-
 static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata = {
        .id                     = TPA6130A2,
        .power_gpio             = 98,
@@ -728,6 +727,17 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = {
        },
 };
 
+/* Audio setup data */
+static struct aic3x_setup_data rx51_aic34_setup = {
+       .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
+       .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
+};
+
+static struct aic3x_pdata rx51_aic3x_data = {
+       .setup = &rx51_aic34_setup,
+       .gpio_reset = 60,
+};
+
 static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
        {
                I2C_BOARD_INFO("tlv320aic3x", 0x18),
index f392844..a43b2c5 100644 (file)
@@ -43,7 +43,7 @@ struct sdram_timings {
        u32 tWTR;
 };
 
-struct omap_sdrc_params rx51_sdrc_params[4];
+static struct omap_sdrc_params rx51_sdrc_params[4];
 
 static const struct sdram_timings rx51_timings[] = {
        {
index 5a1005b..85503fe 100644 (file)
@@ -20,6 +20,8 @@
 #include <plat/vram.h>
 #include <plat/mcspi.h>
 
+#include <mach/board-rx51.h>
+
 #include "mux.h"
 
 #define RX51_LCD_RESET_GPIO    90
index 1d7f827..007ebdc 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <plat/gpmc.h>
 
+#include <mach/board-zoom.h>
+
 #define ZOOM_SMSC911X_CS       7
 #define ZOOM_SMSC911X_GPIO     158
 #define ZOOM_QUADUART_CS       3
index 189a6d1..86c9b21 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -26,6 +27,8 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 
+#include <mach/board-zoom.h>
+
 #include "mux.h"
 #include "hsmmc.h"
 
@@ -33,7 +36,7 @@
 #define OMAP_ZOOM_WLAN_IRQ_GPIO                (162)
 
 /* Zoom2 has Qwerty keyboard*/
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_E),
        KEY(0, 1, KEY_R),
        KEY(0, 2, KEY_T),
@@ -197,14 +200,14 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "external",
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_wp        = -EINVAL,
                .power_saving   = true,
        },
        {
                .name           = "internal",
                .mmc            = 2,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
@@ -238,6 +241,11 @@ static int zoom_twl_gpio_setup(struct device *dev,
        return 0;
 }
 
+/* EXTMUTE callback function */
+void zoom2_set_hs_extmute(int mute)
+{
+       gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
+}
 
 static int zoom_batt_table[] = {
 /* 0 C*/
@@ -307,6 +315,11 @@ static struct i2c_board_info __initdata zoom_i2c_boardinfo[] = {
 
 static int __init omap_i2c_init(void)
 {
+       if (machine_is_omap_zoom2()) {
+               zoom_audio_data.ramp_delay_value = 3;   /* 161 ms */
+               zoom_audio_data.hs_extmute = 1;
+               zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute;
+       }
        omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo,
                        ARRAY_SIZE(zoom_i2c_boardinfo));
        omap_register_i2c_bus(2, 400, NULL, 0);
@@ -336,4 +349,5 @@ void __init zoom_peripherals_init(void)
        platform_device_register(&omap_vwlan_device);
        usb_musb_init(&musb_board_data);
        enable_board_wakeup_source();
+       omap_serial_init();
 }
index 24bbd0d..2992a9f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/i2c/twl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -23,6 +24,7 @@
 
 #include <mach/board-zoom.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 
@@ -34,41 +36,6 @@ static void __init omap_zoom2_init_irq(void)
        omap_gpio_init();
 }
 
-/* REVISIT: These audio entries can be removed once MFD code is merged */
-#if 0
-
-static struct twl4030_madc_platform_data zoom2_madc_data = {
-       .irq_line       = 1,
-};
-
-static struct twl4030_codec_audio_data zoom2_audio_data = {
-       .audio_mclk = 26000000,
-};
-
-static struct twl4030_codec_data zoom2_codec_data = {
-       .audio_mclk = 26000000,
-       .audio = &zoom2_audio_data,
-};
-
-static struct twl4030_platform_data zoom2_twldata = {
-       .irq_base       = TWL4030_IRQ_BASE,
-       .irq_end        = TWL4030_IRQ_END,
-
-       /* platform_data for children goes here */
-       .bci            = &zoom2_bci_data,
-       .madc           = &zoom2_madc_data,
-       .usb            = &zoom2_usb_data,
-       .gpio           = &zoom2_gpio_data,
-       .keypad         = &zoom2_kp_twl4030_data,
-       .codec          = &zoom2_codec_data,
-       .vmmc1          = &zoom2_vmmc1,
-       .vmmc2          = &zoom2_vmmc2,
-       .vsim           = &zoom2_vsim,
-
-};
-
-#endif
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        /* WLAN IRQ - GPIO 162 */
index b2bb3ff..5adde12 100644 (file)
@@ -22,6 +22,7 @@
 #include <plat/board.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
index 605f531..b5babf5 100644 (file)
@@ -395,7 +395,7 @@ void omap2_clk_disable_unused(struct clk *clk)
        if ((regval32 & (1 << clk->enable_bit)) == v)
                return;
 
-       printk(KERN_DEBUG "Disabling unused clock \"%s\"\n", clk->name);
+       pr_debug("Disabling unused clock \"%s\"\n", clk->name);
        if (cpu_is_omap34xx()) {
                omap2_clk_enable(clk);
                omap2_clk_disable(clk);
index 5f2066a..21f8562 100644 (file)
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
 
@@ -89,6 +90,12 @@ static struct clk alt_ck = {         /* Typical 54M or 48M, may not exist */
        .clkdm_name     = "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+       .name           = "mcbsp_clks",
+       .ops            = &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1135,14 +1142,34 @@ static struct clk mcbsp1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+       { .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+       { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+       { .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
        .name           = "mcbsp1_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP1_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1159,10 +1186,14 @@ static struct clk mcbsp2_fck = {
        .name           = "mcbsp2_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP2_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1721,6 +1752,9 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_242X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_242X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_242X),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_242X),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_242X),
+       CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_242X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_242X),
        CLK(NULL,       "apll96_ck",    &apll96_ck,     CK_242X),
@@ -1728,6 +1762,8 @@ static struct omap_clk omap2420_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_242X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_242X),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_242X),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_242X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_242X),
index 701a171..e32afcb 100644 (file)
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR                        OMAP2430_CM_REGADDR
 
@@ -89,6 +90,12 @@ static struct clk alt_ck = {         /* Typical 54M or 48M, may not exist */
        .clkdm_name     = "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+       .name           = "mcbsp_clks",
+       .ops            = &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1123,14 +1130,34 @@ static struct clk mcbsp1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+       { .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+       { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+       { .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
        .name           = "mcbsp1_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP1_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1147,10 +1174,14 @@ static struct clk mcbsp2_fck = {
        .name           = "mcbsp2_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP2_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp3_ick = {
@@ -1167,10 +1198,14 @@ static struct clk mcbsp3_fck = {
        .name           = "mcbsp3_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP3_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP3_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp4_ick = {
@@ -1187,10 +1222,14 @@ static struct clk mcbsp4_fck = {
        .name           = "mcbsp4_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP4_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP4_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp5_ick = {
@@ -1207,10 +1246,14 @@ static struct clk mcbsp5_fck = {
        .name           = "mcbsp5_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP5_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP5_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1808,6 +1851,12 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_243X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_243X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_243X),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_243X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_243X),
        CLK(NULL,       "apll96_ck",    &apll96_ck,     CK_243X),
@@ -1815,6 +1864,11 @@ static struct omap_clk omap2430_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_243X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_243X),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.3",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.4",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.5",     "prcm_fck",     &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_243X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_243X),
index c73906d..d85ecd5 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -33,6 +32,7 @@
 #include "cm-regbits-34xx.h"
 #include "prm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 /*
  * clocks
@@ -2465,6 +2465,16 @@ static struct clk uart3_fck = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk uart4_fck = {
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &per_48m_fck,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+       .enable_bit     = OMAP3630_EN_UART4_SHIFT,
+       .clkdm_name     = "per_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpt2_fck = {
        .name           = "gpt2_fck",
        .ops            = &clkops_omap2_dflt_wait,
@@ -2715,6 +2725,16 @@ static struct clk uart3_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk uart4_ick = {
+       .name           = "uart4_ick",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &per_l4_ick,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+       .enable_bit     = OMAP3630_EN_UART4_SHIFT,
+       .clkdm_name     = "per_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpt9_ick = {
        .name           = "gpt9_ick",
        .ops            = &clkops_omap2_dflt_wait,
@@ -3188,6 +3208,11 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "osc_sys_ck",   &osc_sys_ck,    CK_3XXX),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_3XXX),
        CLK(NULL,       "sys_altclk",   &sys_altclk,    CK_3XXX),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "sys_clkout1",  &sys_clkout1,   CK_3XXX),
        CLK(NULL,       "dpll1_ck",     &dpll1_ck,      CK_3XXX),
@@ -3253,6 +3278,8 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "cpefuse_fck",  &cpefuse_fck,   CK_3430ES2 | CK_AM35XX),
        CLK(NULL,       "ts_fck",       &ts_fck,        CK_3430ES2 | CK_AM35XX),
        CLK(NULL,       "usbtll_fck",   &usbtll_fck,    CK_3430ES2 | CK_AM35XX),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
+       CLK("omap-mcbsp.5",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "core_96m_fck", &core_96m_fck,  CK_3XXX),
        CLK("mmci-omap-hs.2",   "fck",  &mmchs3_fck,    CK_3430ES2 | CK_AM35XX),
        CLK("mmci-omap-hs.1",   "fck",  &mmchs2_fck,    CK_3XXX),
@@ -3346,9 +3373,13 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_3XXX),
        CLK(NULL,       "gpt1_ick",     &gpt1_ick,      CK_3XXX),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
+       CLK("omap-mcbsp.3",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
+       CLK("omap-mcbsp.4",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_96m_fck",  &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_48m_fck",  &per_48m_fck,   CK_3XXX),
        CLK(NULL,       "uart3_fck",    &uart3_fck,     CK_3XXX),
+       CLK(NULL,       "uart4_fck",    &uart4_fck,     CK_36XX),
        CLK(NULL,       "gpt2_fck",     &gpt2_fck,      CK_3XXX),
        CLK(NULL,       "gpt3_fck",     &gpt3_fck,      CK_3XXX),
        CLK(NULL,       "gpt4_fck",     &gpt4_fck,      CK_3XXX),
@@ -3372,6 +3403,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "gpio2_ick",    &gpio2_ick,     CK_3XXX),
        CLK(NULL,       "wdt3_ick",     &wdt3_ick,      CK_3XXX),
        CLK(NULL,       "uart3_ick",    &uart3_ick,     CK_3XXX),
+       CLK(NULL,       "uart4_ick",    &uart4_ick,     CK_36XX),
        CLK(NULL,       "gpt9_ick",     &gpt9_ick,      CK_3XXX),
        CLK(NULL,       "gpt8_ick",     &gpt8_ick,      CK_3XXX),
        CLK(NULL,       "gpt7_ick",     &gpt7_ick,      CK_3XXX),
index e10db7a..1599836 100644 (file)
  * 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.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
  */
 
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/clk.h>
-
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -32,6 +34,7 @@
 #include "cm-regbits-44xx.h"
 #include "prm.h"
 #include "prm-regbits-44xx.h"
+#include "control.h"
 
 /* Root clocks */
 
@@ -175,21 +178,27 @@ static struct clk sys_clkin_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
+static struct clk tie_low_clock_ck = {
+       .name           = "tie_low_clock_ck",
+       .rate           = 0,
+       .ops            = &clkops_null,
+};
+
 static struct clk utmi_phy_clkout_ck = {
        .name           = "utmi_phy_clkout_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
 static struct clk xclk60mhsp1_ck = {
        .name           = "xclk60mhsp1_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
 static struct clk xclk60mhsp2_ck = {
        .name           = "xclk60mhsp2_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
@@ -201,39 +210,23 @@ static struct clk xclk60motg_ck = {
 
 /* Module clocks and DPLL outputs */
 
-static const struct clksel_rate div2_1to2_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel dpll_sys_ref_clk_div[] = {
-       { .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
+static const struct clksel abe_dpll_bypass_clk_mux_sel[] = {
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-static struct clk dpll_sys_ref_clk = {
-       .name           = "dpll_sys_ref_clk",
+static struct clk abe_dpll_bypass_clk_mux_ck = {
+       .name           = "abe_dpll_bypass_clk_mux_ck",
        .parent         = &sys_clkin_ck,
-       .clksel         = dpll_sys_ref_clk_div,
-       .clksel_reg     = OMAP4430_CM_DPLL_SYS_REF_CLKSEL,
-       .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
        .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-};
-
-static const struct clksel abe_dpll_refclk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk abe_dpll_refclk_mux_ck = {
        .name           = "abe_dpll_refclk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
-       .clksel         = abe_dpll_refclk_mux_sel,
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_ABE_PLL_REF_CLKSEL,
        .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
@@ -244,7 +237,7 @@ static struct clk abe_dpll_refclk_mux_ck = {
 /* DPLL_ABE */
 static struct dpll_data dpll_abe_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_ABE,
-       .clk_bypass     = &sys_clkin_ck,
+       .clk_bypass     = &abe_dpll_bypass_clk_mux_ck,
        .clk_ref        = &abe_dpll_refclk_mux_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_ABE,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -310,6 +303,12 @@ static struct clk abe_clk = {
        .set_rate       = &omap2_clksel_set_rate,
 };
 
+static const struct clksel_rate div2_1to2_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+       { .div = 0 },
+};
+
 static const struct clksel aess_fclk_div[] = {
        { .parent = &abe_clk, .rates = div2_1to2_rates },
        { .parent = NULL },
@@ -380,14 +379,14 @@ static struct clk dpll_abe_m3_ck = {
 };
 
 static const struct clksel core_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &dpll_abe_m3_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk core_hsd_byp_clk_mux_ck = {
        .name           = "core_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .clksel         = core_hsd_byp_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_CLKSEL_DPLL_CORE,
@@ -400,7 +399,7 @@ static struct clk core_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_core_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_CORE,
        .clk_bypass     = &core_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_CORE,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
@@ -418,7 +417,7 @@ static struct dpll_data dpll_core_dd = {
 
 static struct clk dpll_core_ck = {
        .name           = "dpll_core_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_core_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_null,
@@ -596,14 +595,14 @@ static struct clk dpll_core_m7_ck = {
 };
 
 static const struct clksel iva_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &div_iva_hs_clk, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk iva_hsd_byp_clk_mux_ck = {
        .name           = "iva_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .ops            = &clkops_null,
        .recalc         = &followparent_recalc,
 };
@@ -612,7 +611,7 @@ static struct clk iva_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_iva_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_IVA,
        .clk_bypass     = &iva_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_IVA,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
@@ -630,7 +629,7 @@ static struct dpll_data dpll_iva_dd = {
 
 static struct clk dpll_iva_ck = {
        .name           = "dpll_iva_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_iva_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -672,7 +671,7 @@ static struct clk dpll_iva_m5_ck = {
 static struct dpll_data dpll_mpu_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_MPU,
        .clk_bypass     = &div_mpu_hs_clk,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_MPU,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
@@ -690,7 +689,7 @@ static struct dpll_data dpll_mpu_dd = {
 
 static struct clk dpll_mpu_ck = {
        .name           = "dpll_mpu_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_mpu_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -724,14 +723,14 @@ static struct clk per_hs_clk_div_ck = {
 };
 
 static const struct clksel per_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk per_hsd_byp_clk_mux_ck = {
        .name           = "per_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .clksel         = per_hsd_byp_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_CLKSEL_DPLL_PER,
@@ -744,7 +743,7 @@ static struct clk per_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_per_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_PER,
        .clk_bypass     = &per_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_PER,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_PER,
@@ -762,7 +761,7 @@ static struct dpll_data dpll_per_dd = {
 
 static struct clk dpll_per_ck = {
        .name           = "dpll_per_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_per_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -858,8 +857,8 @@ static struct clk dpll_per_m7_ck = {
 /* DPLL_UNIPRO */
 static struct dpll_data dpll_unipro_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
-       .clk_bypass     = &dpll_sys_ref_clk,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
@@ -877,7 +876,7 @@ static struct dpll_data dpll_unipro_dd = {
 
 static struct clk dpll_unipro_ck = {
        .name           = "dpll_unipro_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_unipro_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -914,7 +913,8 @@ static struct clk usb_hs_clk_div_ck = {
 static struct dpll_data dpll_usb_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_USB,
        .clk_bypass     = &usb_hs_clk_div_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .flags          = DPLL_J_TYPE | DPLL_NO_DCO_SEL,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_USB,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_USB,
@@ -927,13 +927,12 @@ static struct dpll_data dpll_usb_dd = {
        .max_multiplier = OMAP4430_MAX_DPLL_MULT,
        .max_divider    = OMAP4430_MAX_DPLL_DIV,
        .min_divider    = 1,
-       .flags          = DPLL_J_TYPE | DPLL_NO_DCO_SEL
 };
 
 
 static struct clk dpll_usb_ck = {
        .name           = "dpll_usb_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_usb_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -1222,7 +1221,7 @@ static struct clk per_abe_24m_fclk = {
 static const struct clksel pmd_stm_clock_mux_sel[] = {
        { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &dpll_core_m6_ck, .rates = div_1_1_rates },
-       { .parent = &dpll_per_m7_ck, .rates = div_1_2_rates },
+       { .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
        { .parent = NULL },
 };
 
@@ -1240,10 +1239,15 @@ static struct clk pmd_trace_clk_mux_ck = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel syc_clk_div_div[] = {
+       { .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
+       { .parent = NULL },
+};
+
 static struct clk syc_clk_div_ck = {
        .name           = "syc_clk_div_ck",
        .parent         = &sys_clkin_ck,
-       .clksel         = dpll_sys_ref_clk_div,
+       .clksel         = syc_clk_div_div,
        .clksel_reg     = OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
        .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
        .ops            = &clkops_null,
@@ -1284,13 +1288,13 @@ static struct clk aess_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk cust_efuse_fck = {
-       .name           = "cust_efuse_fck",
+static struct clk bandgap_fclk = {
+       .name           = "bandgap_fclk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_cefuse_clkdm",
-       .parent         = &sys_clkin_ck,
+       .enable_reg     = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
        .recalc         = &followparent_recalc,
 };
 
@@ -1344,6 +1348,56 @@ static struct clk dmic_fck = {
        .clkdm_name     = "abe_clkdm",
 };
 
+static struct clk dsp_fck = {
+       .name           = "dsp_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "tesla_clkdm",
+       .parent         = &dpll_iva_m4_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_sys_clk = {
+       .name           = "dss_sys_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &syc_clk_div_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_tv_clk = {
+       .name           = "dss_tv_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_TV_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &extalt_clkin_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_dss_clk = {
+       .name           = "dss_dss_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &dpll_per_m5_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_48mhz_clk = {
+       .name           = "dss_48mhz_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &func_48mc_fclk,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk dss_fck = {
        .name           = "dss_fck",
        .ops            = &clkops_omap2_dflt,
@@ -1354,18 +1408,18 @@ static struct clk dss_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ducati_ick = {
-       .name           = "ducati_ick",
+static struct clk efuse_ctrl_cust_fck = {
+       .name           = "efuse_ctrl_cust_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "ducati_clkdm",
-       .parent         = &ducati_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_cefuse_clkdm",
+       .parent         = &sys_clkin_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk emif1_ick = {
-       .name           = "emif1_ick",
+static struct clk emif1_fck = {
+       .name           = "emif1_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1375,8 +1429,8 @@ static struct clk emif1_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk emif2_ick = {
-       .name           = "emif2_ick",
+static struct clk emif2_fck = {
+       .name           = "emif2_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1407,42 +1461,24 @@ static struct clk fdif_fck = {
        .clkdm_name     = "iss_clkdm",
 };
 
-static const struct clksel per_sgx_fclk_div[] = {
-       { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
-};
-
-static struct clk per_sgx_fclk = {
-       .name           = "per_sgx_fclk",
-       .parent         = &dpll_per_m2x2_ck,
-       .clksel         = per_sgx_fclk_div,
-       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PER_192M_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-};
-
-static const struct clksel sgx_clk_mux_sel[] = {
-       { .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
-       { .parent = &per_sgx_fclk, .rates = div_1_1_rates },
-       { .parent = NULL },
+static struct clk fpka_fck = {
+       .name           = "fpka_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_secure_clkdm",
+       .parent         = &l4_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
-/* Merged sgx_clk_mux into gfx */
-static struct clk gfx_fck = {
-       .name           = "gfx_fck",
-       .parent         = &dpll_core_m7_ck,
-       .clksel         = sgx_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_SGX_FCLK_MASK,
+static struct clk gpio1_dbclk = {
+       .name           = "gpio1_dbclk",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_gfx_clkdm",
+       .enable_reg     = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk gpio1_ick = {
@@ -1455,6 +1491,16 @@ static struct clk gpio1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio2_dbclk = {
+       .name           = "gpio2_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio2_ick = {
        .name           = "gpio2_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1465,6 +1511,16 @@ static struct clk gpio2_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio3_dbclk = {
+       .name           = "gpio3_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio3_ick = {
        .name           = "gpio3_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1475,6 +1531,16 @@ static struct clk gpio3_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio4_dbclk = {
+       .name           = "gpio4_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio4_ick = {
        .name           = "gpio4_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1485,6 +1551,16 @@ static struct clk gpio4_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio5_dbclk = {
+       .name           = "gpio5_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio5_ick = {
        .name           = "gpio5_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1495,6 +1571,16 @@ static struct clk gpio5_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio6_dbclk = {
+       .name           = "gpio6_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio6_ick = {
        .name           = "gpio6_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1515,278 +1601,114 @@ static struct clk gpmc_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static const struct clksel dmt1_clk_mux_sel[] = {
-       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+static const struct clksel sgx_clk_mux_sel[] = {
+       { .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
+       { .parent = &dpll_per_m7_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-/*
- * Merged dmt1_clk_mux into gptimer1
- * gptimer1 renamed temporarily into gpt1 to match OMAP3 convention
- */
-static struct clk gpt1_fck = {
-       .name           = "gpt1_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
+/* Merged sgx_clk_mux into gpu */
+static struct clk gpu_fck = {
+       .name           = "gpu_fck",
+       .parent         = &dpll_core_m7_ck,
+       .clksel         = sgx_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_SGX_FCLK_MASK,
        .ops            = &clkops_omap2_dflt,
        .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
+       .clkdm_name     = "l3_gfx_clkdm",
 };
 
-/*
- * Merged cm2_dm10_mux into gptimer10
- * gptimer10 renamed temporarily into gpt10 to match OMAP3 convention
- */
-static struct clk gpt10_fck = {
-       .name           = "gpt10_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk hdq1w_fck = {
+       .name           = "hdq1w_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_12m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm11_mux into gptimer11
- * gptimer11 renamed temporarily into gpt11 to match OMAP3 convention
- */
-static struct clk gpt11_fck = {
-       .name           = "gpt11_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static const struct clksel hsi_fclk_div[] = {
+       { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
+       { .parent = NULL },
+};
+
+/* Merged hsi_fclk into hsi */
+static struct clk hsi_fck = {
+       .name           = "hsi_fck",
+       .parent         = &dpll_per_m2x2_ck,
+       .clksel         = hsi_fclk_div,
+       .clksel_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_24_25_MASK,
        .ops            = &clkops_omap2_dflt,
        .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+       .enable_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+};
+
+static struct clk i2c1_fck = {
+       .name           = "i2c1_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm2_mux into gptimer2
- * gptimer2 renamed temporarily into gpt2 to match OMAP3 convention
- */
-static struct clk gpt2_fck = {
-       .name           = "gpt2_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk i2c2_fck = {
+       .name           = "i2c2_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm3_mux into gptimer3
- * gptimer3 renamed temporarily into gpt3 to match OMAP3 convention
- */
-static struct clk gpt3_fck = {
-       .name           = "gpt3_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk i2c3_fck = {
+       .name           = "i2c3_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm4_mux into gptimer4
- * gptimer4 renamed temporarily into gpt4 to match OMAP3 convention
- */
-static struct clk gpt4_fck = {
-       .name           = "gpt4_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-};
-
-static const struct clksel timer5_sync_mux_sel[] = {
-       { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-/*
- * Merged timer5_sync_mux into gptimer5
- * gptimer5 renamed temporarily into gpt5 to match OMAP3 convention
- */
-static struct clk gpt5_fck = {
-       .name           = "gpt5_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer6_sync_mux into gptimer6
- * gptimer6 renamed temporarily into gpt6 to match OMAP3 convention
- */
-static struct clk gpt6_fck = {
-       .name           = "gpt6_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer7_sync_mux into gptimer7
- * gptimer7 renamed temporarily into gpt7 to match OMAP3 convention
- */
-static struct clk gpt7_fck = {
-       .name           = "gpt7_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer8_sync_mux into gptimer8
- * gptimer8 renamed temporarily into gpt8 to match OMAP3 convention
- */
-static struct clk gpt8_fck = {
-       .name           = "gpt8_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged cm2_dm9_mux into gptimer9
- * gptimer9 renamed temporarily into gpt9 to match OMAP3 convention
- */
-static struct clk gpt9_fck = {
-       .name           = "gpt9_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-};
-
-static struct clk hdq1w_fck = {
-       .name           = "hdq1w_fck",
-       .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_12m_fclk,
-       .recalc         = &followparent_recalc,
-};
-
-/* Merged hsi_fclk into hsi */
-static struct clk hsi_ick = {
-       .name           = "hsi_ick",
-       .parent         = &dpll_per_m2x2_ck,
-       .clksel         = per_sgx_fclk_div,
-       .clksel_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_24_25_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-       .enable_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-};
-
-static struct clk i2c1_fck = {
-       .name           = "i2c1_fck",
-       .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_96m_fclk,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
-       .name           = "i2c2_fck",
+static struct clk i2c4_fck = {
+       .name           = "i2c4_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
        .parent         = &func_96m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk i2c3_fck = {
-       .name           = "i2c3_fck",
+static struct clk ipu_fck = {
+       .name           = "ipu_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_96m_fclk,
+       .enable_reg     = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "ducati_clkdm",
+       .parent         = &ducati_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk i2c4_fck = {
-       .name           = "i2c4_fck",
+static struct clk iss_ctrlclk = {
+       .name           = "iss_ctrlclk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
+       .enable_reg     = OMAP4430_CM_CAM_ISS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
+       .clkdm_name     = "iss_clkdm",
        .parent         = &func_96m_fclk,
        .recalc         = &followparent_recalc,
 };
@@ -1801,8 +1723,8 @@ static struct clk iss_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ivahd_ick = {
-       .name           = "ivahd_ick",
+static struct clk iva_fck = {
+       .name           = "iva_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1811,8 +1733,8 @@ static struct clk ivahd_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk keyboard_fck = {
-       .name           = "keyboard_fck",
+static struct clk kbd_fck = {
+       .name           = "kbd_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
@@ -1821,8 +1743,8 @@ static struct clk keyboard_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk l3_instr_interconnect_ick = {
-       .name           = "l3_instr_interconnect_ick",
+static struct clk l3_instr_ick = {
+       .name           = "l3_instr_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1831,8 +1753,8 @@ static struct clk l3_instr_interconnect_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk l3_interconnect_3_ick = {
-       .name           = "l3_interconnect_3_ick",
+static struct clk l3_main_3_ick = {
+       .name           = "l3_main_3_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -2005,6 +1927,16 @@ static struct clk mcbsp4_fck = {
        .clkdm_name     = "l4_per_clkdm",
 };
 
+static struct clk mcpdm_fck = {
+       .name           = "mcpdm_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &pad_clks_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk mcspi1_fck = {
        .name           = "mcspi1_fck",
        .ops            = &clkops_omap2_dflt,
@@ -2105,33 +2037,33 @@ static struct clk mmc5_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ocp_wp1_ick = {
-       .name           = "ocp_wp1_ick",
+static struct clk ocp2scp_usb_phy_phy_48m = {
+       .name           = "ocp2scp_usb_phy_phy_48m",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "l3_instr_clkdm",
-       .parent         = &l3_div_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PHY_48M_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &func_48m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk pdm_fck = {
-       .name           = "pdm_fck",
+static struct clk ocp2scp_usb_phy_ick = {
+       .name           = "ocp2scp_usb_phy_ick",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM1_ABE_PDM_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-       .parent         = &pad_clks_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l4_div_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk pkaeip29_fck = {
-       .name           = "pkaeip29_fck",
+static struct clk ocp_wp_noc_ick = {
+       .name           = "ocp_wp_noc_ick",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_secure_clkdm",
-       .parent         = &l4_div_ck,
+       .enable_reg     = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_instr_clkdm",
+       .parent         = &l3_div_ck,
        .recalc         = &followparent_recalc,
 };
 
@@ -2145,8 +2077,8 @@ static struct clk rng_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sha2md51_fck = {
-       .name           = "sha2md51_fck",
+static struct clk sha2md5_fck = {
+       .name           = "sha2md5_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
@@ -2155,8 +2087,8 @@ static struct clk sha2md51_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sl2_ick = {
-       .name           = "sl2_ick",
+static struct clk sl2if_ick = {
+       .name           = "sl2if_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_IVAHD_SL2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -2165,129 +2097,340 @@ static struct clk sl2_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk slimbus1_fck = {
-       .name           = "slimbus1_fck",
+static struct clk slimbus1_fclk_1 = {
+       .name           = "slimbus1_fclk_1",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK1_SHIFT,
        .clkdm_name     = "abe_clkdm",
-       .parent         = &ocp_abe_iclk,
+       .parent         = &func_24m_clk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk slimbus2_fck = {
-       .name           = "slimbus2_fck",
+static struct clk slimbus1_fclk_0 = {
+       .name           = "slimbus1_fclk_0",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &l4_div_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK0_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &abe_24m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_core_fck = {
-       .name           = "sr_core_fck",
+static struct clk slimbus1_fclk_2 = {
+       .name           = "slimbus1_fclk_2",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK2_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &pad_clks_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_iva_fck = {
-       .name           = "sr_iva_fck",
+static struct clk slimbus1_slimbus_clk = {
+       .name           = "slimbus1_slimbus_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &slimbus_clk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_mpu_fck = {
-       .name           = "sr_mpu_fck",
+static struct clk slimbus1_fck = {
+       .name           = "slimbus1_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &ocp_abe_iclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk tesla_ick = {
-       .name           = "tesla_ick",
+static struct clk slimbus2_fclk_1 = {
+       .name           = "slimbus2_fclk_1",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "tesla_clkdm",
-       .parent         = &dpll_iva_m4_ck,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &per_abe_24m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart1_fck = {
-       .name           = "uart1_fck",
+static struct clk slimbus2_fclk_0 = {
+       .name           = "slimbus2_fclk_0",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &func_24mc_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart2_fck = {
-       .name           = "uart2_fck",
+static struct clk slimbus2_slimbus_clk = {
+       .name           = "slimbus2_slimbus_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &pad_slimbus_core_clks_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart3_fck = {
-       .name           = "uart3_fck",
+static struct clk slimbus2_fck = {
+       .name           = "slimbus2_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &l4_div_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart4_fck = {
-       .name           = "uart4_fck",
+static struct clk smartreflex_core_fck = {
+       .name           = "smartreflex_core_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk unipro1_fck = {
-       .name           = "unipro1_fck",
+static struct clk smartreflex_iva_fck = {
+       .name           = "smartreflex_iva_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-       .parent         = &func_96m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_host_fck = {
-       .name           = "usb_host_fck",
+static struct clk smartreflex_mpu_fck = {
+       .name           = "smartreflex_mpu_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-       .parent         = &init_60m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_host_fs_fck = {
-       .name           = "usb_host_fs_fck",
-       .ops            = &clkops_omap2_dflt,
+/* Merged dmt1_clk_mux into timer1 */
+static struct clk timer1_fck = {
+       .name           = "timer1_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+};
+
+/* Merged cm2_dm10_mux into timer10 */
+static struct clk timer10_fck = {
+       .name           = "timer10_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm11_mux into timer11 */
+static struct clk timer11_fck = {
+       .name           = "timer11_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm2_mux into timer2 */
+static struct clk timer2_fck = {
+       .name           = "timer2_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm3_mux into timer3 */
+static struct clk timer3_fck = {
+       .name           = "timer3_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm4_mux into timer4 */
+static struct clk timer4_fck = {
+       .name           = "timer4_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+static const struct clksel timer5_sync_mux_sel[] = {
+       { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
+       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+/* Merged timer5_sync_mux into timer5 */
+static struct clk timer5_fck = {
+       .name           = "timer5_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer6_sync_mux into timer6 */
+static struct clk timer6_fck = {
+       .name           = "timer6_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer7_sync_mux into timer7 */
+static struct clk timer7_fck = {
+       .name           = "timer7_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer8_sync_mux into timer8 */
+static struct clk timer8_fck = {
+       .name           = "timer8_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged cm2_dm9_mux into timer9 */
+static struct clk timer9_fck = {
+       .name           = "timer9_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+static struct clk uart1_fck = {
+       .name           = "uart1_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart2_fck = {
+       .name           = "uart2_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart3_fck = {
+       .name           = "uart3_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart4_fck = {
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_fs_fck = {
+       .name           = "usb_host_fs_fck",
+       .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l3_init_clkdm",
@@ -2295,75 +2438,138 @@ static struct clk usb_host_fs_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_otg_ick = {
-       .name           = "usb_otg_ick",
+static struct clk usb_host_hs_utmi_p3_clk = {
+       .name           = "usb_host_hs_utmi_p3_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l3_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_tll_ick = {
-       .name           = "usb_tll_ick",
+static struct clk usb_host_hs_hsic60m_p1_clk = {
+       .name           = "usb_host_hs_hsic60m_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l4_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usbphyocp2scp_ick = {
-       .name           = "usbphyocp2scp_ick",
+static struct clk usb_host_hs_hsic60m_p2_clk = {
+       .name           = "usb_host_hs_hsic60m_p2_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l4_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usim_fck = {
-       .name           = "usim_fck",
+static const struct clksel utmi_p1_gfclk_sel[] = {
+       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+       { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk utmi_p1_gfclk = {
+       .name           = "utmi_p1_gfclk",
+       .parent         = &init_60m_fclk,
+       .clksel         = utmi_p1_gfclk_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p1_clk = {
+       .name           = "usb_host_hs_utmi_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .parent         = &sys_32k_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &utmi_p1_gfclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk wdt2_fck = {
-       .name           = "wdt2_fck",
+static const struct clksel utmi_p2_gfclk_sel[] = {
+       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+       { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk utmi_p2_gfclk = {
+       .name           = "utmi_p2_gfclk",
+       .parent         = &init_60m_fclk,
+       .clksel         = utmi_p2_gfclk_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P2_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p2_clk = {
+       .name           = "usb_host_hs_utmi_p2_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .parent         = &sys_32k_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &utmi_p2_gfclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk wdt3_fck = {
-       .name           = "wdt3_fck",
+static struct clk usb_host_hs_hsic480m_p1_clk = {
+       .name           = "usb_host_hs_hsic480m_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &dpll_usb_m2_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_hsic480m_p2_clk = {
+       .name           = "usb_host_hs_hsic480m_p2_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &dpll_usb_m2_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_func48mclk = {
+       .name           = "usb_host_hs_func48mclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &func_48mc_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_fck = {
+       .name           = "usb_host_hs_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-       .parent         = &sys_32k_ck,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-/* Remaining optional clocks */
 static const struct clksel otg_60m_gfclk_sel[] = {
        { .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates },
        { .parent = &xclk60motg_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-static struct clk otg_60m_gfclk_ck = {
-       .name           = "otg_60m_gfclk_ck",
+static struct clk otg_60m_gfclk = {
+       .name           = "otg_60m_gfclk",
        .parent         = &utmi_phy_clkout_ck,
        .clksel         = otg_60m_gfclk_sel,
        .init           = &omap2_init_clksel_parent,
@@ -2373,38 +2579,74 @@ static struct clk otg_60m_gfclk_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
-static const struct clksel stm_clk_div_div[] = {
-       { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
+static struct clk usb_otg_hs_xclk = {
+       .name           = "usb_otg_hs_xclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_XCLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &otg_60m_gfclk,
+       .recalc         = &followparent_recalc,
 };
 
-static struct clk stm_clk_div_ck = {
-       .name           = "stm_clk_div_ck",
-       .parent         = &pmd_stm_clock_mux_ck,
-       .clksel         = stm_clk_div_div,
-       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
+static struct clk usb_otg_hs_ick = {
+       .name           = "usb_otg_hs_ick",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l3_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
-static const struct clksel trace_clk_div_div[] = {
-       { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
+static struct clk usb_phy_cm_clk32k = {
+       .name           = "usb_phy_cm_clk32k",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_CLK32K_SHIFT,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
 };
 
-static struct clk trace_clk_div_ck = {
-       .name           = "trace_clk_div_ck",
-       .parent         = &pmd_trace_clk_mux_ck,
-       .clksel         = trace_clk_div_div,
-       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
+static struct clk usb_tll_hs_usb_ch2_clk = {
+       .name           = "usb_tll_hs_usb_ch2_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch0_clk = {
+       .name           = "usb_tll_hs_usb_ch0_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch1_clk = {
+       .name           = "usb_tll_hs_usb_ch1_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_ick = {
+       .name           = "usb_tll_hs_ick",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l4_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
 static const struct clksel_rate div2_14to18_rates[] = {
@@ -2418,8 +2660,8 @@ static const struct clksel usim_fclk_div[] = {
        { .parent = NULL },
 };
 
-static struct clk usim_fclk = {
-       .name           = "usim_fclk",
+static struct clk usim_ck = {
+       .name           = "usim_ck",
        .parent         = &dpll_per_m4_ck,
        .clksel         = usim_fclk_div,
        .clksel_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
@@ -2430,38 +2672,79 @@ static struct clk usim_fclk = {
        .set_rate       = &omap2_clksel_set_rate,
 };
 
-static const struct clksel utmi_p1_gfclk_sel[] = {
-       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
-       { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+static struct clk usim_fclk = {
+       .name           = "usim_fclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &usim_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usim_fck = {
+       .name           = "usim_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk wd_timer2_fck = {
+       .name           = "wd_timer2_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk wd_timer3_fck = {
+       .name           = "wd_timer3_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+/* Remaining optional clocks */
+static const struct clksel stm_clk_div_div[] = {
+       { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
        { .parent = NULL },
 };
 
-static struct clk utmi_p1_gfclk_ck = {
-       .name           = "utmi_p1_gfclk_ck",
-       .parent         = &init_60m_fclk,
-       .clksel         = utmi_p1_gfclk_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P1_MASK,
+static struct clk stm_clk_div_ck = {
+       .name           = "stm_clk_div_ck",
+       .parent         = &pmd_stm_clock_mux_ck,
+       .clksel         = stm_clk_div_div,
+       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
        .ops            = &clkops_null,
        .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
 };
 
-static const struct clksel utmi_p2_gfclk_sel[] = {
-       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
-       { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+static const struct clksel trace_clk_div_div[] = {
+       { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
        { .parent = NULL },
 };
 
-static struct clk utmi_p2_gfclk_ck = {
-       .name           = "utmi_p2_gfclk_ck",
-       .parent         = &init_60m_fclk,
-       .clksel         = utmi_p2_gfclk_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P2_MASK,
+static struct clk trace_clk_div_ck = {
+       .name           = "trace_clk_div_ck",
+       .parent         = &pmd_trace_clk_mux_ck,
+       .clksel         = trace_clk_div_div,
+       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
        .ops            = &clkops_null,
        .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
 };
 
 /*
@@ -2483,11 +2766,12 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "virt_27000000_ck",             &virt_27000000_ck,      CK_443X),
        CLK(NULL,       "virt_38400000_ck",             &virt_38400000_ck,      CK_443X),
        CLK(NULL,       "sys_clkin_ck",                 &sys_clkin_ck,  CK_443X),
+       CLK(NULL,       "tie_low_clock_ck",             &tie_low_clock_ck,      CK_443X),
        CLK(NULL,       "utmi_phy_clkout_ck",           &utmi_phy_clkout_ck,    CK_443X),
        CLK(NULL,       "xclk60mhsp1_ck",               &xclk60mhsp1_ck,        CK_443X),
        CLK(NULL,       "xclk60mhsp2_ck",               &xclk60mhsp2_ck,        CK_443X),
        CLK(NULL,       "xclk60motg_ck",                &xclk60motg_ck, CK_443X),
-       CLK(NULL,       "dpll_sys_ref_clk",             &dpll_sys_ref_clk,      CK_443X),
+       CLK(NULL,       "abe_dpll_bypass_clk_mux_ck",   &abe_dpll_bypass_clk_mux_ck,    CK_443X),
        CLK(NULL,       "abe_dpll_refclk_mux_ck",       &abe_dpll_refclk_mux_ck,        CK_443X),
        CLK(NULL,       "dpll_abe_ck",                  &dpll_abe_ck,   CK_443X),
        CLK(NULL,       "dpll_abe_m2x2_ck",             &dpll_abe_m2x2_ck,      CK_443X),
@@ -2557,46 +2841,48 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "aes1_fck",                     &aes1_fck,      CK_443X),
        CLK(NULL,       "aes2_fck",                     &aes2_fck,      CK_443X),
        CLK(NULL,       "aess_fck",                     &aess_fck,      CK_443X),
-       CLK(NULL,       "cust_efuse_fck",               &cust_efuse_fck,        CK_443X),
+       CLK(NULL,       "bandgap_fclk",                 &bandgap_fclk,  CK_443X),
        CLK(NULL,       "des3des_fck",                  &des3des_fck,   CK_443X),
        CLK(NULL,       "dmic_sync_mux_ck",             &dmic_sync_mux_ck,      CK_443X),
        CLK(NULL,       "dmic_fck",                     &dmic_fck,      CK_443X),
+       CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
+       CLK(NULL,       "dss_sys_clk",                  &dss_sys_clk,   CK_443X),
+       CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk,    CK_443X),
+       CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk,   CK_443X),
+       CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk, CK_443X),
        CLK(NULL,       "dss_fck",                      &dss_fck,       CK_443X),
-       CLK(NULL,       "ducati_ick",                   &ducati_ick,    CK_443X),
-       CLK(NULL,       "emif1_ick",                    &emif1_ick,     CK_443X),
-       CLK(NULL,       "emif2_ick",                    &emif2_ick,     CK_443X),
+       CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
+       CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
+       CLK(NULL,       "emif2_fck",                    &emif2_fck,     CK_443X),
        CLK(NULL,       "fdif_fck",                     &fdif_fck,      CK_443X),
-       CLK(NULL,       "per_sgx_fclk",                 &per_sgx_fclk,  CK_443X),
-       CLK(NULL,       "gfx_fck",                      &gfx_fck,       CK_443X),
+       CLK(NULL,       "fpka_fck",                     &fpka_fck,      CK_443X),
+       CLK(NULL,       "gpio1_dbck",                   &gpio1_dbclk,   CK_443X),
        CLK(NULL,       "gpio1_ick",                    &gpio1_ick,     CK_443X),
+       CLK(NULL,       "gpio2_dbck",                   &gpio2_dbclk,   CK_443X),
        CLK(NULL,       "gpio2_ick",                    &gpio2_ick,     CK_443X),
+       CLK(NULL,       "gpio3_dbck",                   &gpio3_dbclk,   CK_443X),
        CLK(NULL,       "gpio3_ick",                    &gpio3_ick,     CK_443X),
+       CLK(NULL,       "gpio4_dbck",                   &gpio4_dbclk,   CK_443X),
        CLK(NULL,       "gpio4_ick",                    &gpio4_ick,     CK_443X),
+       CLK(NULL,       "gpio5_dbck",                   &gpio5_dbclk,   CK_443X),
        CLK(NULL,       "gpio5_ick",                    &gpio5_ick,     CK_443X),
+       CLK(NULL,       "gpio6_dbck",                   &gpio6_dbclk,   CK_443X),
        CLK(NULL,       "gpio6_ick",                    &gpio6_ick,     CK_443X),
        CLK(NULL,       "gpmc_ick",                     &gpmc_ick,      CK_443X),
-       CLK(NULL,       "gpt1_fck",                     &gpt1_fck,      CK_443X),
-       CLK(NULL,       "gpt10_fck",                    &gpt10_fck,     CK_443X),
-       CLK(NULL,       "gpt11_fck",                    &gpt11_fck,     CK_443X),
-       CLK(NULL,       "gpt2_fck",                     &gpt2_fck,      CK_443X),
-       CLK(NULL,       "gpt3_fck",                     &gpt3_fck,      CK_443X),
-       CLK(NULL,       "gpt4_fck",                     &gpt4_fck,      CK_443X),
-       CLK(NULL,       "gpt5_fck",                     &gpt5_fck,      CK_443X),
-       CLK(NULL,       "gpt6_fck",                     &gpt6_fck,      CK_443X),
-       CLK(NULL,       "gpt7_fck",                     &gpt7_fck,      CK_443X),
-       CLK(NULL,       "gpt8_fck",                     &gpt8_fck,      CK_443X),
-       CLK(NULL,       "gpt9_fck",                     &gpt9_fck,      CK_443X),
+       CLK(NULL,       "gpu_fck",                      &gpu_fck,       CK_443X),
        CLK("omap2_hdq.0",      "fck",                          &hdq1w_fck,     CK_443X),
-       CLK(NULL,       "hsi_ick",                      &hsi_ick,       CK_443X),
+       CLK(NULL,       "hsi_fck",                      &hsi_fck,       CK_443X),
        CLK("i2c_omap.1",       "fck",                          &i2c1_fck,      CK_443X),
        CLK("i2c_omap.2",       "fck",                          &i2c2_fck,      CK_443X),
        CLK("i2c_omap.3",       "fck",                          &i2c3_fck,      CK_443X),
        CLK("i2c_omap.4",       "fck",                          &i2c4_fck,      CK_443X),
+       CLK(NULL,       "ipu_fck",                      &ipu_fck,       CK_443X),
+       CLK(NULL,       "iss_ctrlclk",                  &iss_ctrlclk,   CK_443X),
        CLK(NULL,       "iss_fck",                      &iss_fck,       CK_443X),
-       CLK(NULL,       "ivahd_ick",                    &ivahd_ick,     CK_443X),
-       CLK(NULL,       "keyboard_fck",                 &keyboard_fck,  CK_443X),
-       CLK(NULL,       "l3_instr_interconnect_ick",    &l3_instr_interconnect_ick,     CK_443X),
-       CLK(NULL,       "l3_interconnect_3_ick",        &l3_interconnect_3_ick, CK_443X),
+       CLK(NULL,       "iva_fck",                      &iva_fck,       CK_443X),
+       CLK(NULL,       "kbd_fck",                      &kbd_fck,       CK_443X),
+       CLK(NULL,       "l3_instr_ick",                 &l3_instr_ick,  CK_443X),
+       CLK(NULL,       "l3_main_3_ick",                &l3_main_3_ick, CK_443X),
        CLK(NULL,       "mcasp_sync_mux_ck",            &mcasp_sync_mux_ck,     CK_443X),
        CLK(NULL,       "mcasp_fck",                    &mcasp_fck,     CK_443X),
        CLK(NULL,       "mcbsp1_sync_mux_ck",           &mcbsp1_sync_mux_ck,    CK_443X),
@@ -2607,6 +2893,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("omap-mcbsp.3",     "fck",                          &mcbsp3_fck,    CK_443X),
        CLK(NULL,       "mcbsp4_sync_mux_ck",           &mcbsp4_sync_mux_ck,    CK_443X),
        CLK("omap-mcbsp.4",     "fck",                          &mcbsp4_fck,    CK_443X),
+       CLK(NULL,       "mcpdm_fck",                    &mcpdm_fck,     CK_443X),
        CLK("omap2_mcspi.1",    "fck",                          &mcspi1_fck,    CK_443X),
        CLK("omap2_mcspi.2",    "fck",                          &mcspi2_fck,    CK_443X),
        CLK("omap2_mcspi.3",    "fck",                          &mcspi3_fck,    CK_443X),
@@ -2616,43 +2903,66 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("mmci-omap-hs.2",   "fck",                          &mmc3_fck,      CK_443X),
        CLK("mmci-omap-hs.3",   "fck",                          &mmc4_fck,      CK_443X),
        CLK("mmci-omap-hs.4",   "fck",                          &mmc5_fck,      CK_443X),
-       CLK(NULL,       "ocp_wp1_ick",                  &ocp_wp1_ick,   CK_443X),
-       CLK(NULL,       "pdm_fck",                      &pdm_fck,       CK_443X),
-       CLK(NULL,       "pkaeip29_fck",                 &pkaeip29_fck,  CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_ick",          &ocp2scp_usb_phy_ick,   CK_443X),
+       CLK(NULL,       "ocp_wp_noc_ick",               &ocp_wp_noc_ick,        CK_443X),
        CLK("omap_rng", "ick",                          &rng_ick,       CK_443X),
-       CLK(NULL,       "sha2md51_fck",                 &sha2md51_fck,  CK_443X),
-       CLK(NULL,       "sl2_ick",                      &sl2_ick,       CK_443X),
+       CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck,   CK_443X),
+       CLK(NULL,       "sl2if_ick",                    &sl2if_ick,     CK_443X),
+       CLK(NULL,       "slimbus1_fclk_1",              &slimbus1_fclk_1,       CK_443X),
+       CLK(NULL,       "slimbus1_fclk_0",              &slimbus1_fclk_0,       CK_443X),
+       CLK(NULL,       "slimbus1_fclk_2",              &slimbus1_fclk_2,       CK_443X),
+       CLK(NULL,       "slimbus1_slimbus_clk",         &slimbus1_slimbus_clk,  CK_443X),
        CLK(NULL,       "slimbus1_fck",                 &slimbus1_fck,  CK_443X),
+       CLK(NULL,       "slimbus2_fclk_1",              &slimbus2_fclk_1,       CK_443X),
+       CLK(NULL,       "slimbus2_fclk_0",              &slimbus2_fclk_0,       CK_443X),
+       CLK(NULL,       "slimbus2_slimbus_clk",         &slimbus2_slimbus_clk,  CK_443X),
        CLK(NULL,       "slimbus2_fck",                 &slimbus2_fck,  CK_443X),
-       CLK(NULL,       "sr_core_fck",                  &sr_core_fck,   CK_443X),
-       CLK(NULL,       "sr_iva_fck",                   &sr_iva_fck,    CK_443X),
-       CLK(NULL,       "sr_mpu_fck",                   &sr_mpu_fck,    CK_443X),
-       CLK(NULL,       "tesla_ick",                    &tesla_ick,     CK_443X),
+       CLK(NULL,       "smartreflex_core_fck",         &smartreflex_core_fck,  CK_443X),
+       CLK(NULL,       "smartreflex_iva_fck",          &smartreflex_iva_fck,   CK_443X),
+       CLK(NULL,       "smartreflex_mpu_fck",          &smartreflex_mpu_fck,   CK_443X),
+       CLK(NULL,       "gpt1_fck",                     &timer1_fck,    CK_443X),
+       CLK(NULL,       "gpt10_fck",                    &timer10_fck,   CK_443X),
+       CLK(NULL,       "gpt11_fck",                    &timer11_fck,   CK_443X),
+       CLK(NULL,       "gpt2_fck",                     &timer2_fck,    CK_443X),
+       CLK(NULL,       "gpt3_fck",                     &timer3_fck,    CK_443X),
+       CLK(NULL,       "gpt4_fck",                     &timer4_fck,    CK_443X),
+       CLK(NULL,       "gpt5_fck",                     &timer5_fck,    CK_443X),
+       CLK(NULL,       "gpt6_fck",                     &timer6_fck,    CK_443X),
+       CLK(NULL,       "gpt7_fck",                     &timer7_fck,    CK_443X),
+       CLK(NULL,       "gpt8_fck",                     &timer8_fck,    CK_443X),
+       CLK(NULL,       "gpt9_fck",                     &timer9_fck,    CK_443X),
        CLK(NULL,       "uart1_fck",                    &uart1_fck,     CK_443X),
        CLK(NULL,       "uart2_fck",                    &uart2_fck,     CK_443X),
        CLK(NULL,       "uart3_fck",                    &uart3_fck,     CK_443X),
        CLK(NULL,       "uart4_fck",                    &uart4_fck,     CK_443X),
-       CLK(NULL,       "unipro1_fck",                  &unipro1_fck,   CK_443X),
-       CLK(NULL,       "usb_host_fck",                 &usb_host_fck,  CK_443X),
        CLK(NULL,       "usb_host_fs_fck",              &usb_host_fs_fck,       CK_443X),
-       CLK("musb_hdrc",        "ick",                          &usb_otg_ick,   CK_443X),
-       CLK(NULL,       "usb_tll_ick",                  &usb_tll_ick,   CK_443X),
-       CLK(NULL,       "usbphyocp2scp_ick",            &usbphyocp2scp_ick,     CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p3_clk",      &usb_host_hs_utmi_p3_clk,       CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic60m_p1_clk",   &usb_host_hs_hsic60m_p1_clk,    CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic60m_p2_clk",   &usb_host_hs_hsic60m_p2_clk,    CK_443X),
+       CLK(NULL,       "utmi_p1_gfclk",                &utmi_p1_gfclk, CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p1_clk",      &usb_host_hs_utmi_p1_clk,       CK_443X),
+       CLK(NULL,       "utmi_p2_gfclk",                &utmi_p2_gfclk, CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p2_clk",      &usb_host_hs_utmi_p2_clk,       CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic480m_p1_clk",  &usb_host_hs_hsic480m_p1_clk,   CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic480m_p2_clk",  &usb_host_hs_hsic480m_p2_clk,   CK_443X),
+       CLK(NULL,       "usb_host_hs_func48mclk",       &usb_host_hs_func48mclk,        CK_443X),
+       CLK(NULL,       "usb_host_hs_fck",              &usb_host_hs_fck,       CK_443X),
+       CLK(NULL,       "otg_60m_gfclk",                &otg_60m_gfclk, CK_443X),
+       CLK(NULL,       "usb_otg_hs_xclk",              &usb_otg_hs_xclk,       CK_443X),
+       CLK("musb_hdrc",        "ick",                          &usb_otg_hs_ick,        CK_443X),
+       CLK(NULL,       "usb_phy_cm_clk32k",            &usb_phy_cm_clk32k,     CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch2_clk",       &usb_tll_hs_usb_ch2_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch0_clk",       &usb_tll_hs_usb_ch0_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch1_clk",       &usb_tll_hs_usb_ch1_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_ick",               &usb_tll_hs_ick,        CK_443X),
+       CLK(NULL,       "usim_ck",                      &usim_ck,       CK_443X),
+       CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
        CLK(NULL,       "usim_fck",                     &usim_fck,      CK_443X),
-       CLK("omap_wdt", "fck",                          &wdt2_fck,      CK_443X),
-       CLK(NULL,       "wdt3_fck",                     &wdt3_fck,      CK_443X),
-       CLK(NULL,       "otg_60m_gfclk_ck",             &otg_60m_gfclk_ck,      CK_443X),
+       CLK("omap_wdt", "fck",                          &wd_timer2_fck, CK_443X),
+       CLK(NULL,       "wd_timer3_fck",                &wd_timer3_fck, CK_443X),
        CLK(NULL,       "stm_clk_div_ck",               &stm_clk_div_ck,        CK_443X),
        CLK(NULL,       "trace_clk_div_ck",             &trace_clk_div_ck,      CK_443X),
-       CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
-       CLK(NULL,       "utmi_p1_gfclk_ck",             &utmi_p1_gfclk_ck,      CK_443X),
-       CLK(NULL,       "utmi_p2_gfclk_ck",             &utmi_p2_gfclk_ck,      CK_443X),
-       CLK(NULL,       "gpio1_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio2_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio3_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio4_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio5_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio6_dbck",                   &dummy_ck,      CK_443X),
        CLK(NULL,       "gpmc_ck",                      &dummy_ck,      CK_443X),
        CLK(NULL,       "gpt1_ick",                     &dummy_ck,      CK_443X),
        CLK(NULL,       "gpt2_ick",                     &dummy_ck,      CK_443X),
@@ -2669,19 +2979,19 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("i2c_omap.2",       "ick",                          &dummy_ck,      CK_443X),
        CLK("i2c_omap.3",       "ick",                          &dummy_ck,      CK_443X),
        CLK("i2c_omap.4",       "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.0",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.1",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.2",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.3",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.4",   "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.1",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.2",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.3",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.4",     "ick",                          &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.1",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.2",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.3",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.4",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.0",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.1",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.2",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.3",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.4",   "ick",          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.1",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.2",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.3",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.4",    "ick",                          &dummy_ck,      CK_443X),
        CLK(NULL,       "uart1_ick",                    &dummy_ck,      CK_443X),
        CLK(NULL,       "uart2_ick",                    &dummy_ck,      CK_443X),
        CLK(NULL,       "uart3_ick",                    &dummy_ck,      CK_443X),
index 5d80cb8..6fb61b1 100644 (file)
@@ -258,97 +258,6 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
-/**
- * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
- * @clkdm: clockdomain to initialize wkdep usecounts
- *
- * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
- * If a wakeup dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software wakeup dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_wkdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!clkdm->wkdep_srcs)
-               return;
-
-       for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
-                            "found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           PM_WKDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: wakeup dependency already "
-                                "set to wake up when %s wakes\n",
-                                clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
-       }
-}
-
-/**
- * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
- * @clkdm: clockdomain to initialize sleepdep usecounts
- *
- * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
- * If a sleep dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software sleep dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_sleepdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!cpu_is_omap34xx())
-               return;
-
-       if (!clkdm->sleepdep_srcs)
-               return;
-
-       for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
-                            "not found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           OMAP3430_CM_SLEEPDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: sleep dependency already "
-                                "set to prevent from idling until %s "
-                                "idles\n", clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
-       }
-};
-
 /* Public functions */
 
 /**
@@ -379,12 +288,17 @@ void clkdm_init(struct clockdomain **clkdms,
                        _autodep_lookup(autodep);
 
        /*
-        * Ensure that the *dep_usecount registers reflect the current
-        * state of the PRCM.
+        * Put all clockdomains into software-supervised mode; PM code
+        * should later enable hardware-supervised mode as appropriate
         */
        list_for_each_entry(clkdm, &clkdm_list, node) {
-               _init_wkdep_usecount(clkdm);
-               _init_sleepdep_usecount(clkdm);
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap2_clkdm_wakeup(clkdm);
+               else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
+                       omap2_clkdm_deny_idle(clkdm);
+
+               clkdm_clear_all_wkdeps(clkdm);
+               clkdm_clear_all_sleepdeps(clkdm);
        }
 }
 
@@ -592,6 +506,9 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->wkdep_usecount, 0);
@@ -752,6 +669,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->sleepdep_usecount, 0);
index fe82b79..4f959a7 100644 (file)
 #define OMAP3430_ST_MCBSP2_MASK                                (1 << 0)
 
 /* CM_AUTOIDLE_PER */
+#define OMAP3630_AUTO_UART4_MASK                       (1 << 18)
+#define OMAP3630_AUTO_UART4_SHIFT                      18
 #define OMAP3430_AUTO_GPIO6_MASK                       (1 << 17)
 #define OMAP3430_AUTO_GPIO6_SHIFT                      17
 #define OMAP3430_AUTO_GPIO5_MASK                       (1 << 16)
index ac8458e..0b72be4 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Clock Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
 #include "cm.h"
 
 
-/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/*
+ * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
+ * CM_TESLA_DYNAMICDEP
+ */
 #define OMAP4430_ABE_DYNDEP_SHIFT                              3
-#define OMAP4430_ABE_DYNDEP_MASK                               BITFIELD(3, 3)
+#define OMAP4430_ABE_DYNDEP_MASK                               (1 << 3)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ABE_STATDEP_SHIFT                             3
-#define OMAP4430_ABE_STATDEP_MASK                              BITFIELD(3, 3)
+#define OMAP4430_ABE_STATDEP_MASK                              (1 << 3)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_ALWONCORE_DYNDEP_SHIFT                                16
-#define OMAP4430_ALWONCORE_DYNDEP_MASK                         BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_DYNDEP_MASK                         (1 << 16)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_ALWONCORE_STATDEP_SHIFT                       16
-#define OMAP4430_ALWONCORE_STATDEP_MASK                                BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_STATDEP_MASK                                (1 << 16)
 
 /*
- * Used by CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB,
- * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
- * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU
+ * Used by CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
+ * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_DDRPHY,
+ * CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER,
+ * CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
  */
 #define OMAP4430_AUTO_DPLL_MODE_SHIFT                          0
-#define OMAP4430_AUTO_DPLL_MODE_MASK                           BITFIELD(0, 2)
+#define OMAP4430_AUTO_DPLL_MODE_MASK                           (0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_CEFUSE_DYNDEP_SHIFT                           17
-#define OMAP4430_CEFUSE_DYNDEP_MASK                            BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_DYNDEP_MASK                            (1 << 17)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_CEFUSE_STATDEP_SHIFT                          17
-#define OMAP4430_CEFUSE_STATDEP_MASK                           BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_STATDEP_MASK                           (1 << 17)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_SHIFT               13
-#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK                        BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK                        (1 << 13)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_SHIFT           12
-#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK            BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK            (1 << 12)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_LP_CLK_SHIFT                  9
-#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK                   BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK                   (1 << 9)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_SYSCLK_SHIFT                  11
-#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK                   BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK                   (1 << 11)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK                   (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT               11
-#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK                        BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK                        (1 << 11)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT              12
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK               BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK               (1 << 12)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT              13
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK               BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK               (1 << 13)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_SHIFT           9
-#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK            BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK            (1 << 9)
+
+/* Used by CM_ALWON_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_SHIFT                12
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_MASK         (1 << 12)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT           9
-#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            (1 << 9)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT          9
-#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           (1 << 9)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT                     9
-#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK                      BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK                      (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT                 9
-#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK                  BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK                  (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT                 10
-#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK                  BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK                  (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT                  11
-#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK                   BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK                   (1 << 11)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT                  12
-#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK                   BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK                   (1 << 12)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT                  13
-#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK                   BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK                   (1 << 13)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT                  14
-#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK                   BITFIELD(14, 14)
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK                   (1 << 14)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_SHIFT           10
-#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK            BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK            (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_FCLK_SHIFT                    9
-#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK                     BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK                     (1 << 9)
 
 /* Used by CM_DUCATI_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DUCATI_GCLK_SHIFT                 8
-#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK                  BITFIELD(8, 8)
-
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_SHIFT              10
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_MASK               BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK                  (1 << 8)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_SHIFT                 8
-#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK                  BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK                  (1 << 8)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT                  10
-#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK                   BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT              15
-#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK               BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK               (1 << 15)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_SHIFT              10
-#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK               BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK               (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT                11
-#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK         BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK         (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT          20
-#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK           BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK           (1 << 20)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT               26
-#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK                        BITFIELD(26, 26)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK                        (1 << 26)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT          21
-#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK           BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK           (1 << 21)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT               27
-#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK                        BITFIELD(27, 27)
-
-/* Used by CM_L3INIT_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_SHIFT              31
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_MASK               BITFIELD(31, 31)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK                        (1 << 27)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT             13
-#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK              BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK              (1 << 13)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT              12
-#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK               BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK               (1 << 12)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT           28
-#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK            BITFIELD(28, 28)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK            (1 << 28)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT           29
-#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK            BITFIELD(29, 29)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK            (1 << 29)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK               (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT              16
-#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK               BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT           17
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK            BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK            (1 << 17)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT           18
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK            BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK            (1 << 18)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT           19
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK            BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK            (1 << 19)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ISS_GCLK_SHIFT                    8
-#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK                     BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK                     (1 << 8)
 
 /* Used by CM_IVAHD_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK               (1 << 8)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_SHIFT       14
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_MASK                BITFIELD(14, 14)
+/* Used by CM_D2D_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT              10
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK               (1 << 10)
 
 /* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_SDMA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT               8
-#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK                        BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT               8
-#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK                        BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_L3INSTR_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK               (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_SHIFT             8
-#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK              BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_AO_ICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK                   (1 << 8)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT             8
-#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK              BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT                        9
-#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK                 BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK                 (1 << 9)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_SHIFT             9
-#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK              BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK              (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT               12
-#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK                        BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK                        (1 << 12)
 
 /* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK                 (1 << 8)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT              16
-#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK               BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT               17
-#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK                        BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK                        (1 << 17)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT               18
-#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK                        BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK                        (1 << 18)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT               19
-#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK                        BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK                        (1 << 19)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT           25
-#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK            BITFIELD(25, 25)
-
-/* Used by CM_EMU_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_SHIFT            10
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_MASK             BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK            (1 << 25)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT            20
-#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK             BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK             (1 << 20)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT            21
-#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK             BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK             (1 << 21)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT            22
-#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK             BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK             (1 << 22)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT               24
-#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK                        BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK                        (1 << 24)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT                        10
-#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK                 BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK                 (1 << 10)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SGX_GFCLK_SHIFT                   9
-#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK                    (1 << 9)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK               (1 << 11)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_SHIFT               10
-#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK                        BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK                        (1 << 10)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK                        (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SYS_CLK_SHIFT                     8
-#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK                      BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK                      (1 << 8)
 
 /* Used by CM_TESLA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK               (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT               22
-#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK                        BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK                        (1 << 22)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT               23
-#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK                        BITFIELD(23, 23)
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK                        (1 << 23)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT               24
-#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK                        BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK                        (1 << 24)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT             10
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK              (1 << 10)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT                        14
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK                 (1 << 14)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT             15
-#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK              BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK              (1 << 15)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT                  10
-#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK                   BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT               30
-#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK                        BITFIELD(30, 30)
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK                        (1 << 30)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT             25
-#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK              BITFIELD(25, 25)
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK              (1 << 25)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               (1 << 11)
 
 /*
- * Used by CM_WKUP_TIMER1_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
+ * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
+ * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
  * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
  * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
  * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL,
- * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
- * CM1_ABE_TIMER8_CLKCTRL
+ * CM_WKUP_TIMER1_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SHIFT                                  24
-#define OMAP4430_CLKSEL_MASK                                   BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_MASK                                   (1 << 24)
 
 /*
  * Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL,
- * CM_DPLL_SYS_REF_CLKSEL, CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT,
- * CM_CLKSEL_USB_60MHZ
+ * CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ
  */
 #define OMAP4430_CLKSEL_0_0_SHIFT                              0
-#define OMAP4430_CLKSEL_0_0_MASK                               BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_0_0_MASK                               (1 << 0)
 
 /* Renamed from CLKSEL Used by CM_BYPCLK_DPLL_IVA, CM_BYPCLK_DPLL_MPU */
 #define OMAP4430_CLKSEL_0_1_SHIFT                              0
-#define OMAP4430_CLKSEL_0_1_MASK                               BITFIELD(0, 1)
+#define OMAP4430_CLKSEL_0_1_MASK                               (0x3 << 0)
 
 /* Renamed from CLKSEL Used by CM_L3INIT_HSI_CLKCTRL */
 #define OMAP4430_CLKSEL_24_25_SHIFT                            24
-#define OMAP4430_CLKSEL_24_25_MASK                             BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_24_25_MASK                             (0x3 << 24)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_CLKSEL_60M_SHIFT                              24
-#define OMAP4430_CLKSEL_60M_MASK                               BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_60M_MASK                               (1 << 24)
 
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT                                24
-#define OMAP4430_CLKSEL_AESS_FCLK_MASK                         BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_AESS_FCLK_MASK                         (1 << 24)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_CORE_SHIFT                             0
-#define OMAP4430_CLKSEL_CORE_MASK                              BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_CORE_MASK                              (1 << 0)
 
-/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_CORE_1_1_SHIFT                         1
-#define OMAP4430_CLKSEL_CORE_1_1_MASK                          BITFIELD(1, 1)
+#define OMAP4430_CLKSEL_CORE_1_1_MASK                          (1 << 1)
 
 /* Used by CM_WKUP_USIM_CLKCTRL */
 #define OMAP4430_CLKSEL_DIV_SHIFT                              24
-#define OMAP4430_CLKSEL_DIV_MASK                               BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_DIV_MASK                               (1 << 24)
 
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT                             24
-#define OMAP4430_CLKSEL_FCLK_MASK                              BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_FCLK_MASK                              (0x3 << 24)
 
 /* Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT                  25
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK                   BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK                   (1 << 25)
 
 /*
  * Renamed from CLKSEL_INTERNAL_SOURCE Used by CM1_ABE_DMIC_CLKCTRL,
  * CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT     26
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK      BITFIELD(26, 27)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK      (0x3 << 26)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L3_SHIFT                               4
-#define OMAP4430_CLKSEL_L3_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_CLKSEL_L3_MASK                                        (1 << 4)
 
-/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_L3_SHADOW_SHIFT                                2
-#define OMAP4430_CLKSEL_L3_SHADOW_MASK                         BITFIELD(2, 2)
+#define OMAP4430_CLKSEL_L3_SHADOW_MASK                         (1 << 2)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L4_SHIFT                               8
-#define OMAP4430_CLKSEL_L4_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_CLKSEL_L4_MASK                                        (1 << 8)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_CLKSEL_OPP_SHIFT                              0
-#define OMAP4430_CLKSEL_OPP_MASK                               BITFIELD(0, 1)
-
-/* Used by CM_GFX_GFX_CLKCTRL */
-#define OMAP4430_CLKSEL_PER_192M_SHIFT                         25
-#define OMAP4430_CLKSEL_PER_192M_MASK                          BITFIELD(25, 26)
+#define OMAP4430_CLKSEL_OPP_MASK                               (0x3 << 0)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT                      27
-#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK                       BITFIELD(27, 29)
+#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK                       (0x7 << 27)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_TRACE_CLK_SHIFT                    24
-#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK                     BITFIELD(24, 26)
+#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK                     (0x7 << 24)
 
 /* Used by CM_GFX_GFX_CLKCTRL */
 #define OMAP4430_CLKSEL_SGX_FCLK_SHIFT                         24
-#define OMAP4430_CLKSEL_SGX_FCLK_MASK                          BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SGX_FCLK_MASK                          (1 << 24)
 
 /*
  * Used by CM1_ABE_DMIC_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL,
  * CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SOURCE_SHIFT                           24
-#define OMAP4430_CLKSEL_SOURCE_MASK                            BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_SOURCE_MASK                            (0x3 << 24)
 
 /* Renamed from CLKSEL_SOURCE Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT                     24
-#define OMAP4430_CLKSEL_SOURCE_24_24_MASK                      BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SOURCE_24_24_MASK                      (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P1_SHIFT                          24
-#define OMAP4430_CLKSEL_UTMI_P1_MASK                           BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_UTMI_P1_MASK                           (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P2_SHIFT                          25
-#define OMAP4430_CLKSEL_UTMI_P2_MASK                           BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_UTMI_P2_MASK                           (1 << 25)
 
 /*
- * Used by CM_WKUP_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_D2D_CLKSTCTRL,
- * CM_DUCATI_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL,
- * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_MEMIF_CLKSTCTRL,
- * CM_SDMA_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_L4PER_CLKSTCTRL, CM_L4SEC_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL, CM_CAM_CLKSTCTRL, CM_CEFUSE_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3_1_CLKSTCTRL_RESTORE,
- * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL_RESTORE,
- * CM_L4PER_CLKSTCTRL_RESTORE, CM_MEMIF_CLKSTCTRL_RESTORE, CM_ALWON_CLKSTCTRL,
- * CM_IVAHD_CLKSTCTRL, CM_DSS_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
- * CM1_ABE_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE
+ * Used by CM1_ABE_CLKSTCTRL, CM_ALWON_CLKSTCTRL, CM_CAM_CLKSTCTRL,
+ * CM_CEFUSE_CLKSTCTRL, CM_D2D_CLKSTCTRL, CM_DSS_CLKSTCTRL,
+ * CM_DUCATI_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_IVAHD_CLKSTCTRL,
+ * CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3INSTR_CLKSTCTRL,
+ * CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE, CM_L3_2_CLKSTCTRL,
+ * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE,
+ * CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE, CM_L4SEC_CLKSTCTRL,
+ * CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE, CM_MPU_CLKSTCTRL,
+ * CM_MPU_CLKSTCTRL_RESTORE, CM_SDMA_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
+ * CM_WKUP_CLKSTCTRL
  */
 #define OMAP4430_CLKTRCTRL_SHIFT                               0
-#define OMAP4430_CLKTRCTRL_MASK                                        BITFIELD(0, 1)
+#define OMAP4430_CLKTRCTRL_MASK                                        (0x3 << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_DIV_SHIFT                       0
-#define OMAP4430_CORE_DPLL_EMU_DIV_MASK                                BITFIELD(0, 6)
+#define OMAP4430_CORE_DPLL_EMU_DIV_MASK                                (0x7f << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_MULT_SHIFT                      8
-#define OMAP4430_CORE_DPLL_EMU_MULT_MASK                       BITFIELD(8, 18)
+#define OMAP4430_CORE_DPLL_EMU_MULT_MASK                       (0x7ff << 8)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_CUSTOM_SHIFT                                  6
+#define OMAP4430_CUSTOM_MASK                                   (0x3 << 6)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_D2D_DYNDEP_SHIFT                              18
-#define OMAP4430_D2D_DYNDEP_MASK                               BITFIELD(18, 18)
+#define OMAP4430_D2D_DYNDEP_MASK                               (1 << 18)
 
 /* Used by CM_MPU_STATICDEP */
 #define OMAP4430_D2D_STATDEP_SHIFT                             18
-#define OMAP4430_D2D_STATDEP_MASK                              BITFIELD(18, 18)
+#define OMAP4430_D2D_STATDEP_MASK                              (1 << 18)
 
 /*
- * Used by CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
- * CM_SSC_DELTAMSTEP_DPLL_USB, CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE,
- * CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
- * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
- * CM_SSC_DELTAMSTEP_DPLL_MPU
+ * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
+ * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY,
+ * CM_SSC_DELTAMSTEP_DPLL_IVA, CM_SSC_DELTAMSTEP_DPLL_MPU,
+ * CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
+ * CM_SSC_DELTAMSTEP_DPLL_USB
  */
 #define OMAP4430_DELTAMSTEP_SHIFT                              0
-#define OMAP4430_DELTAMSTEP_MASK                               BITFIELD(0, 19)
+#define OMAP4430_DELTAMSTEP_MASK                               (0xfffff << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_OVERRIDE_SHIFT                            2
-#define OMAP4430_DLL_OVERRIDE_MASK                             BITFIELD(2, 2)
+#define OMAP4430_DLL_OVERRIDE_MASK                             (1 << 2)
 
 /* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */
 #define OMAP4430_DLL_OVERRIDE_0_0_SHIFT                                0
-#define OMAP4430_DLL_OVERRIDE_0_0_MASK                         BITFIELD(0, 0)
+#define OMAP4430_DLL_OVERRIDE_0_0_MASK                         (1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_RESET_SHIFT                               3
-#define OMAP4430_DLL_RESET_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DLL_RESET_MASK                                        (1 << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
+ * CM_CLKSEL_DPLL_USB
  */
 #define OMAP4430_DPLL_BYP_CLKSEL_SHIFT                         23
-#define OMAP4430_DPLL_BYP_CLKSEL_MASK                          BITFIELD(23, 23)
+#define OMAP4430_DPLL_BYP_CLKSEL_MASK                          (1 << 23)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT                        8
-#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK                 BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK                 (1 << 8)
 
-/* Used by CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_CORE */
+/* Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_CORE_RESTORE */
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT                   20
-#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK                    BITFIELD(20, 20)
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK                    (1 << 20)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT                      0
-#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK                       BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK                       (0x1f << 0)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT                 5
-#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK                  BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK                  (1 << 5)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT                        8
-#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK                 BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK                 (1 << 8)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_SHIFT                 10
-#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK                  BITFIELD(10, 10)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK                  (1 << 10)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIV_SHIFT                         0
-#define OMAP4430_DPLL_CLKOUT_DIV_MASK                          BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUT_DIV_MASK                          (0x1f << 0)
 
 /* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_SHIFT                     0
-#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK                      BITFIELD(0, 6)
+#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK                      (0x7f << 0)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT                    5
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK                     BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK                     (1 << 5)
 
 /* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_SHIFT             7
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK              BITFIELD(7, 7)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK              (1 << 7)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT                   8
-#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK                    BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK                    (1 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT                       8
-#define OMAP4430_DPLL_CORE_DPLL_EN_MASK                                BITFIELD(8, 10)
+#define OMAP4430_DPLL_CORE_DPLL_EN_MASK                                (0x7 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_M2_DIV_SHIFT                                11
-#define OMAP4430_DPLL_CORE_M2_DIV_MASK                         BITFIELD(11, 15)
+#define OMAP4430_DPLL_CORE_M2_DIV_MASK                         (0x1f << 11)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_DPLL_CORE_M5_DIV_SHIFT                                3
-#define OMAP4430_DPLL_CORE_M5_DIV_MASK                         BITFIELD(3, 7)
-
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_SHIFT                        1
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_MASK                 BITFIELD(1, 1)
+#define OMAP4430_DPLL_CORE_M5_DIV_MASK                         (0x1f << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_DIV_SHIFT                                        0
-#define OMAP4430_DPLL_DIV_MASK                                 BITFIELD(0, 6)
+#define OMAP4430_DPLL_DIV_MASK                                 (0x7f << 0)
 
 /* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_DIV_0_7_SHIFT                            0
-#define OMAP4430_DPLL_DIV_0_7_MASK                             BITFIELD(0, 7)
+#define OMAP4430_DPLL_DIV_0_7_MASK                             (0xff << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT                      8
-#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK                       BITFIELD(8, 8)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK                       (1 << 8)
 
 /* Renamed from DPLL_DRIFTGUARD_EN Used by CM_CLKMODE_DPLL_UNIPRO */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_SHIFT                  3
-#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK                   BITFIELD(3, 3)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK                   (1 << 3)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_EN_SHIFT                                 0
-#define OMAP4430_DPLL_EN_MASK                                  BITFIELD(0, 2)
+#define OMAP4430_DPLL_EN_MASK                                  (0x7 << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_LPMODE_EN_SHIFT                          10
-#define OMAP4430_DPLL_LPMODE_EN_MASK                           BITFIELD(10, 10)
+#define OMAP4430_DPLL_LPMODE_EN_MASK                           (1 << 10)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_MULT_SHIFT                               8
-#define OMAP4430_DPLL_MULT_MASK                                        BITFIELD(8, 18)
+#define OMAP4430_DPLL_MULT_MASK                                        (0x7ff << 8)
 
 /* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_MULT_USB_SHIFT                           8
-#define OMAP4430_DPLL_MULT_USB_MASK                            BITFIELD(8, 19)
+#define OMAP4430_DPLL_MULT_USB_MASK                            (0xfff << 8)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_REGM4XEN_SHIFT                           11
-#define OMAP4430_DPLL_REGM4XEN_MASK                            BITFIELD(11, 11)
+#define OMAP4430_DPLL_REGM4XEN_MASK                            (1 << 11)
 
 /* Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_SD_DIV_SHIFT                             24
-#define OMAP4430_DPLL_SD_DIV_MASK                              BITFIELD(24, 31)
+#define OMAP4430_DPLL_SD_DIV_MASK                              (0xff << 24)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_ACK_SHIFT                            13
-#define OMAP4430_DPLL_SSC_ACK_MASK                             BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_ACK_MASK                             (1 << 13)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT                     14
-#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK                      BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK                      (1 << 14)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_EN_SHIFT                             12
-#define OMAP4430_DPLL_SSC_EN_MASK                              BITFIELD(12, 12)
+#define OMAP4430_DPLL_SSC_EN_MASK                              (1 << 12)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_DSS_DYNDEP_SHIFT                              8
-#define OMAP4430_DSS_DYNDEP_MASK                               BITFIELD(8, 8)
+#define OMAP4430_DSS_DYNDEP_MASK                               (1 << 8)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_DSS_STATDEP_SHIFT                             8
-#define OMAP4430_DSS_STATDEP_MASK                              BITFIELD(8, 8)
+#define OMAP4430_DSS_STATDEP_MASK                              (1 << 8)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_DUCATI_DYNDEP_SHIFT                           0
-#define OMAP4430_DUCATI_DYNDEP_MASK                            BITFIELD(0, 0)
+#define OMAP4430_DUCATI_DYNDEP_MASK                            (1 << 0)
 
-/* Used by CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP */
+/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE */
 #define OMAP4430_DUCATI_STATDEP_SHIFT                          0
-#define OMAP4430_DUCATI_STATDEP_MASK                           BITFIELD(0, 0)
+#define OMAP4430_DUCATI_STATDEP_MASK                           (1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_FREQ_UPDATE_SHIFT                             0
-#define OMAP4430_FREQ_UPDATE_MASK                              BITFIELD(0, 0)
+#define OMAP4430_FREQ_UPDATE_MASK                              (1 << 0)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_FUNC_SHIFT                                    16
+#define OMAP4430_FUNC_MASK                                     (0xfff << 16)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_GFX_DYNDEP_SHIFT                              10
-#define OMAP4430_GFX_DYNDEP_MASK                               BITFIELD(10, 10)
+#define OMAP4430_GFX_DYNDEP_MASK                               (1 << 10)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_GFX_STATDEP_SHIFT                             10
-#define OMAP4430_GFX_STATDEP_MASK                              BITFIELD(10, 10)
+#define OMAP4430_GFX_STATDEP_MASK                              (1 << 10)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_GPMC_FREQ_UPDATE_SHIFT                                0
-#define OMAP4430_GPMC_FREQ_UPDATE_MASK                         BITFIELD(0, 0)
+#define OMAP4430_GPMC_FREQ_UPDATE_MASK                         (1 << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK                   BITFIELD(12, 12)
-
-/*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK                   (1 << 12)
+
+/*
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_IDLEST_SHIFT                                  16
-#define OMAP4430_IDLEST_MASK                                   BITFIELD(16, 17)
+#define OMAP4430_IDLEST_MASK                                   (0x3 << 16)
 
-/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
+/*
+ * Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_ISS_DYNDEP_SHIFT                              9
-#define OMAP4430_ISS_DYNDEP_MASK                               BITFIELD(9, 9)
+#define OMAP4430_ISS_DYNDEP_MASK                               (1 << 9)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ISS_STATDEP_SHIFT                             9
-#define OMAP4430_ISS_STATDEP_MASK                              BITFIELD(9, 9)
+#define OMAP4430_ISS_STATDEP_MASK                              (1 << 9)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_IVAHD_DYNDEP_SHIFT                            2
-#define OMAP4430_IVAHD_DYNDEP_MASK                             BITFIELD(2, 2)
+#define OMAP4430_IVAHD_DYNDEP_MASK                             (1 << 2)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_DSS_STATICDEP, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_IVAHD_STATDEP_SHIFT                           2
-#define OMAP4430_IVAHD_STATDEP_MASK                            BITFIELD(2, 2)
+#define OMAP4430_IVAHD_STATDEP_MASK                            (1 << 2)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_L3INIT_DYNDEP_SHIFT                           7
-#define OMAP4430_L3INIT_DYNDEP_MASK                            BITFIELD(7, 7)
+#define OMAP4430_L3INIT_DYNDEP_MASK                            (1 << 7)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
+ * CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3INIT_STATDEP_SHIFT                          7
-#define OMAP4430_L3INIT_STATDEP_MASK                           BITFIELD(7, 7)
+#define OMAP4430_L3INIT_STATDEP_MASK                           (1 << 7)
 
 /*
- * Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_DSS_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_DSS_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_L3_1_DYNDEP_SHIFT                             5
-#define OMAP4430_L3_1_DYNDEP_MASK                              BITFIELD(5, 5)
+#define OMAP4430_L3_1_DYNDEP_MASK                              (1 << 5)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_1_STATDEP_SHIFT                            5
-#define OMAP4430_L3_1_STATDEP_MASK                             BITFIELD(5, 5)
+#define OMAP4430_L3_1_STATDEP_MASK                             (1 << 5)
 
 /*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_SDMA_DYNAMICDEP,
- * CM_GFX_DYNAMICDEP, CM_L4SEC_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_CAM_DYNAMICDEP, CM_IVAHD_DYNAMICDEP
+ * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE,
+ * CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP,
+ * CM_IVAHD_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
  */
 #define OMAP4430_L3_2_DYNDEP_SHIFT                             6
-#define OMAP4430_L3_2_DYNDEP_MASK                              BITFIELD(6, 6)
+#define OMAP4430_L3_2_DYNDEP_MASK                              (1 << 6)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_2_STATDEP_SHIFT                            6
-#define OMAP4430_L3_2_STATDEP_MASK                             BITFIELD(6, 6)
+#define OMAP4430_L3_2_STATDEP_MASK                             (1 << 6)
 
-/* Used by CM_L3_1_DYNAMICDEP */
+/* Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4CFG_DYNDEP_SHIFT                            12
-#define OMAP4430_L4CFG_DYNDEP_MASK                             BITFIELD(12, 12)
+#define OMAP4430_L4CFG_DYNDEP_MASK                             (1 << 12)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4CFG_STATDEP_SHIFT                           12
-#define OMAP4430_L4CFG_STATDEP_MASK                            BITFIELD(12, 12)
+#define OMAP4430_L4CFG_STATDEP_MASK                            (1 << 12)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4PER_DYNDEP_SHIFT                            13
-#define OMAP4430_L4PER_DYNDEP_MASK                             BITFIELD(13, 13)
+#define OMAP4430_L4PER_DYNDEP_MASK                             (1 << 13)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4PER_STATDEP_SHIFT                           13
-#define OMAP4430_L4PER_STATDEP_MASK                            BITFIELD(13, 13)
+#define OMAP4430_L4PER_STATDEP_MASK                            (1 << 13)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_L4SEC_DYNDEP_SHIFT                            14
-#define OMAP4430_L4SEC_DYNDEP_MASK                             BITFIELD(14, 14)
+#define OMAP4430_L4SEC_DYNDEP_MASK                             (1 << 14)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_L4SEC_STATDEP_SHIFT                           14
-#define OMAP4430_L4SEC_STATDEP_MASK                            BITFIELD(14, 14)
+#define OMAP4430_L4SEC_STATDEP_MASK                            (1 << 14)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4WKUP_DYNDEP_SHIFT                           15
-#define OMAP4430_L4WKUP_DYNDEP_MASK                            BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_DYNDEP_MASK                            (1 << 15)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4WKUP_STATDEP_SHIFT                          15
-#define OMAP4430_L4WKUP_STATDEP_MASK                           BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_STATDEP_MASK                           (1 << 15)
 
 /*
- * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_MPU_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP
  */
 #define OMAP4430_MEMIF_DYNDEP_SHIFT                            4
-#define OMAP4430_MEMIF_DYNDEP_MASK                             BITFIELD(4, 4)
+#define OMAP4430_MEMIF_DYNDEP_MASK                             (1 << 4)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_MEMIF_STATDEP_SHIFT                           4
-#define OMAP4430_MEMIF_STATDEP_MASK                            BITFIELD(4, 4)
+#define OMAP4430_MEMIF_STATDEP_MASK                            (1 << 4)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_EXPONENT_SHIFT                     8
-#define OMAP4430_MODFREQDIV_EXPONENT_MASK                      BITFIELD(8, 10)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK                      (0x7 << 8)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_MANTISSA_SHIFT                     0
-#define OMAP4430_MODFREQDIV_MANTISSA_MASK                      BITFIELD(0, 6)
-
-/*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK                      (0x7f << 0)
+
+/*
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_MODULEMODE_SHIFT                              0
-#define OMAP4430_MODULEMODE_MASK                               BITFIELD(0, 1)
+#define OMAP4430_MODULEMODE_MASK                               (0x3 << 0)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT                     9
-#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      (1 << 9)
 
 /* Used by CM_WKUP_BANDGAP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT                      8
-#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK                       BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK                       (1 << 8)
 
-/* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
-#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT                                9
-#define OMAP4430_OPTFCLKEN_CLK32K_MASK                         BITFIELD(9, 9)
+/* Used by CM_ALWON_USBPHY_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT                                8
+#define OMAP4430_OPTFCLKEN_CLK32K_MASK                         (1 << 8)
 
 /* Used by CM_CAM_ISS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK                                (1 << 8)
 
 /*
- * Used by CM_WKUP_GPIO1_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE
+ * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE, CM_WKUP_GPIO1_CLKCTRL
  */
 #define OMAP4430_OPTFCLKEN_DBCLK_SHIFT                         8
-#define OMAP4430_OPTFCLKEN_DBCLK_MASK                          BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK                          (1 << 8)
 
 /* Used by CM_MEMIF_DLL_CLKCTRL, CM_MEMIF_DLL_H_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DLL_CLK_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK                                (1 << 8)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DSSCLK_SHIFT                                8
-#define OMAP4430_OPTFCLKEN_DSSCLK_MASK                         BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DSSCLK_MASK                         (1 << 8)
+
+/* Used by CM_WKUP_USIM_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_FCLK_SHIFT                          8
+#define OMAP4430_OPTFCLKEN_FCLK_MASK                           (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK0_SHIFT                         8
-#define OMAP4430_OPTFCLKEN_FCLK0_MASK                          BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_FCLK0_MASK                          (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK1_SHIFT                         9
-#define OMAP4430_OPTFCLKEN_FCLK1_MASK                          BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_FCLK1_MASK                          (1 << 9)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK2_SHIFT                         10
-#define OMAP4430_OPTFCLKEN_FCLK2_MASK                          BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_FCLK2_MASK                          (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT                    15
-#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK                     BITFIELD(15, 15)
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK                     (1 << 15)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT               13
-#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK                        BITFIELD(13, 13)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK                        (1 << 13)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT               14
-#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK                        BITFIELD(14, 14)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK                        (1 << 14)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT                        11
-#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK                 BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK                 (1 << 11)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT                        12
-#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK                 BITFIELD(12, 12)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK                 (1 << 12)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT                 8
-#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK                  BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK                  (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT               9
-#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK                        (1 << 9)
 
 /* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PHY_48M_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_PHY_48M_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PHY_48M_MASK                                (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK                    (1 << 10)
 
 /* Renamed from OPTFCLKEN_SLIMBUS_CLK Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT             11
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK              BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK              (1 << 11)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT                       10
-#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                (1 << 10)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT                                11
-#define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         (1 << 11)
 
 /* Used by CM_L3INIT_UNIPRO1_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT                      8
-#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK                       BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK                       (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT                   8
-#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK                    BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT                   9
-#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT                   8
-#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK                    BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT                   9
-#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_XCLK_SHIFT                          8
-#define OMAP4430_OPTFCLKEN_XCLK_MASK                           BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_XCLK_MASK                           (1 << 8)
 
-/* Used by CM_EMU_OVERRIDE_DPLL_PER, CM_EMU_OVERRIDE_DPLL_CORE */
+/* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_OVERRIDE_ENABLE_SHIFT                         19
-#define OMAP4430_OVERRIDE_ENABLE_MASK                          BITFIELD(19, 19)
+#define OMAP4430_OVERRIDE_ENABLE_MASK                          (1 << 19)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_PAD_CLKS_GATE_SHIFT                           8
-#define OMAP4430_PAD_CLKS_GATE_MASK                            BITFIELD(8, 8)
+#define OMAP4430_PAD_CLKS_GATE_MASK                            (1 << 8)
 
 /* Used by CM_CORE_DVFS_CURRENT, CM_IVA_DVFS_CURRENT */
 #define OMAP4430_PERF_CURRENT_SHIFT                            0
-#define OMAP4430_PERF_CURRENT_MASK                             BITFIELD(0, 7)
+#define OMAP4430_PERF_CURRENT_MASK                             (0xff << 0)
 
 /*
  * Used by CM_CORE_DVFS_PERF1, CM_CORE_DVFS_PERF2, CM_CORE_DVFS_PERF3,
  * CM_IVA_DVFS_PERF_TESLA
  */
 #define OMAP4430_PERF_REQ_SHIFT                                        0
-#define OMAP4430_PERF_REQ_MASK                                 BITFIELD(0, 7)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_DIV_SHIFT                                0
-#define OMAP4430_PER_DPLL_EMU_DIV_MASK                         BITFIELD(0, 6)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_MULT_SHIFT                       8
-#define OMAP4430_PER_DPLL_EMU_MULT_MASK                                BITFIELD(8, 18)
+#define OMAP4430_PERF_REQ_MASK                                 (0xff << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE1_COMPLETED_SHIFT                                0
-#define OMAP4430_PHASE1_COMPLETED_MASK                         BITFIELD(0, 0)
+#define OMAP4430_PHASE1_COMPLETED_MASK                         (1 << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2A_COMPLETED_SHIFT                       1
-#define OMAP4430_PHASE2A_COMPLETED_MASK                                BITFIELD(1, 1)
+#define OMAP4430_PHASE2A_COMPLETED_MASK                                (1 << 1)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2B_COMPLETED_SHIFT                       2
-#define OMAP4430_PHASE2B_COMPLETED_MASK                                BITFIELD(2, 2)
+#define OMAP4430_PHASE2B_COMPLETED_MASK                                (1 << 2)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_STM_MUX_CTRL_SHIFT                                20
-#define OMAP4430_PMD_STM_MUX_CTRL_MASK                         BITFIELD(20, 21)
+#define OMAP4430_PMD_STM_MUX_CTRL_MASK                         (0x3 << 20)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT                      22
-#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK                       BITFIELD(22, 23)
+#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK                       (0x3 << 22)
 
-/* Used by CM_DYN_DEP_PRESCAL */
+/* Used by CM_DYN_DEP_PRESCAL, CM_DYN_DEP_PRESCAL_RESTORE */
 #define OMAP4430_PRESCAL_SHIFT                                 0
-#define OMAP4430_PRESCAL_MASK                                  BITFIELD(0, 5)
+#define OMAP4430_PRESCAL_MASK                                  (0x3f << 0)
 
-/* Used by REVISION_CM2, REVISION_CM1 */
-#define OMAP4430_REV_SHIFT                                     0
-#define OMAP4430_REV_MASK                                      BITFIELD(0, 7)
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_R_RTL_SHIFT                                   11
+#define OMAP4430_R_RTL_MASK                                    (0x1f << 11)
 
 /*
- * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
+ * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
  */
 #define OMAP4430_SAR_MODE_SHIFT                                        4
-#define OMAP4430_SAR_MODE_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_SAR_MODE_MASK                                 (1 << 4)
 
 /* Used by CM_SCALE_FCLK */
 #define OMAP4430_SCALE_FCLK_SHIFT                              0
-#define OMAP4430_SCALE_FCLK_MASK                               BITFIELD(0, 0)
+#define OMAP4430_SCALE_FCLK_MASK                               (1 << 0)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_SCHEME_SHIFT                                  30
+#define OMAP4430_SCHEME_MASK                                   (0x3 << 30)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_SDMA_DYNDEP_SHIFT                             11
-#define OMAP4430_SDMA_DYNDEP_MASK                              BITFIELD(11, 11)
+#define OMAP4430_SDMA_DYNDEP_MASK                              (1 << 11)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_SDMA_STATDEP_SHIFT                            11
-#define OMAP4430_SDMA_STATDEP_MASK                             BITFIELD(11, 11)
+#define OMAP4430_SDMA_STATDEP_MASK                             (1 << 11)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_SLIMBUS_CLK_GATE_SHIFT                                10
-#define OMAP4430_SLIMBUS_CLK_GATE_MASK                         BITFIELD(10, 10)
+#define OMAP4430_SLIMBUS_CLK_GATE_MASK                         (1 << 10)
 
 /*
- * Used by CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_SAD2D_CLKCTRL,
- * CM_DUCATI_DUCATI_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * Used by CM1_ABE_AESS_CLKCTRL, CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL,
+ * CM_D2D_SAD2D_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
+ * CM_DUCATI_DUCATI_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL,
+ * CM_IVAHD_IVAHD_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_IVAHD_IVAHD_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_XHPI_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
+ * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
  */
 #define OMAP4430_STBYST_SHIFT                                  18
-#define OMAP4430_STBYST_MASK                                   BITFIELD(18, 18)
+#define OMAP4430_STBYST_MASK                                   (1 << 18)
 
 /*
- * Used by CM_IDLEST_DPLL_PER, CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB,
- * CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
- * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLK_SHIFT                             0
-#define OMAP4430_ST_DPLL_CLK_MASK                              BITFIELD(0, 0)
+#define OMAP4430_ST_DPLL_CLK_MASK                              (1 << 0)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_ST_DPLL_CLKDCOLDO_SHIFT                       9
-#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK                                BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK                                (1 << 9)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLKOUT_SHIFT                          9
-#define OMAP4430_ST_DPLL_CLKOUT_MASK                           BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK                           (1 << 9)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT                       9
-#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK                                BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK                                (1 << 9)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_ST_DPLL_CLKOUTX2_SHIFT                                11
-#define OMAP4430_ST_DPLL_CLKOUTX2_MASK                         BITFIELD(11, 11)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK                         (1 << 11)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK                     (1 << 9)
+
+/*
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
+ */
+#define OMAP4430_ST_MN_BYPASS_SHIFT                            8
+#define OMAP4430_ST_MN_BYPASS_MASK                             (1 << 8)
 
 /* Used by CM_SYS_CLKSEL */
 #define OMAP4430_SYS_CLKSEL_SHIFT                              0
-#define OMAP4430_SYS_CLKSEL_MASK                               BITFIELD(0, 2)
+#define OMAP4430_SYS_CLKSEL_MASK                               (0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_TESLA_DYNDEP_SHIFT                            1
-#define OMAP4430_TESLA_DYNDEP_MASK                             BITFIELD(1, 1)
+#define OMAP4430_TESLA_DYNDEP_MASK                             (1 << 1)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_TESLA_STATDEP_SHIFT                           1
-#define OMAP4430_TESLA_STATDEP_MASK                            BITFIELD(1, 1)
+#define OMAP4430_TESLA_STATDEP_MASK                            (1 << 1)
 
 /*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_DUCATI_DYNAMICDEP,
+ * CM_EMU_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE,
+ * CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_WINDOWSIZE_SHIFT                              24
-#define OMAP4430_WINDOWSIZE_MASK                               BITFIELD(24, 27)
+#define OMAP4430_WINDOWSIZE_MASK                               (0xf << 24)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_X_MAJOR_SHIFT                                 8
+#define OMAP4430_X_MAJOR_MASK                                  (0x7 << 8)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_Y_MINOR_SHIFT                                 0
+#define OMAP4430_Y_MINOR_MASK                                  (0x3f << 0)
 #endif
index 336d948..3c35a87 100644 (file)
 #define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET              0x0088
 #define OMAP4430_CM1_ABE_WDT3_CLKCTRL                  OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0088)
 
+/* CM1.RESTORE_CM1 register offsets */
+#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET            0x0000
+#define OMAP4430_CM_CLKSEL_CORE_RESTORE                        OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET       0x0004
+#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET       0x0008
+#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET       0x000c
+#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET       0x0010
+#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET       0x0014
+#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET       0x0018
+#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET       0x001c
+#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET       0x0020
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE   OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET       0x0024
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE   OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET      0x0028
+#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE          OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET    0x002c
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE                OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET    0x0030
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE                OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET     0x0034
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE         OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET          0x0038
+#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE              OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET  0x003c
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE      OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET                0x0040
+#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE            OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0040)
+
 /* CM2 */
 
 /* CM2.OCP_SOCKET_CM2 register offsets */
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0068)
 #define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET                0x006c
 #define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x006c)
-#define OMAP4_CM_EMU_OVERRIDE_DPLL_PER_OFFSET          0x0070
-#define OMAP4430_CM_EMU_OVERRIDE_DPLL_PER              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0070)
 #define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET               0x0080
 #define OMAP4430_CM_CLKMODE_DPLL_USB                   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0080)
 #define OMAP4_CM_IDLEST_DPLL_USB_OFFSET                        0x0084
 #define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL               OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0030)
 #define OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET          0x0038
 #define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0038)
+#define OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET           0x0040
+#define OMAP4430_CM_ALWON_USBPHY_CLKCTRL               OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0040)
 
 /* CM2.CORE_CM2 register offsets */
 #define OMAP4_CM_L3_1_CLKSTCTRL_OFFSET                 0x0000
 #define OMAP4430_CM_CEFUSE_CLKSTCTRL                   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0000)
 #define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET          0x0020
 #define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0020)
+
+/* CM2.RESTORE_CM2 register offsets */
+#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET         0x0000
+#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET         0x0004
+#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET                0x0008
+#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET                0x000c
+#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET                0x0010
+#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET       0x0014
+#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET   0x0018
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE       OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET       0x001c
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET        0x0020
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE    OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET  0x0024
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE      OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET          0x0028
+#define OMAP4430_CM_D2D_STATICDEP_RESTORE              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET                0x002c
+#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET                0x0030
+#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET         0x0034
+#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET       0x0038
+#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET       0x003c
+#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET    0x0040
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0040)
+#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET    0x0044
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0044)
+#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET    0x0048
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0048)
+#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET    0x004c
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x004c)
+#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET    0x0050
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0050)
+#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET        0x0054
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE    OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0054)
+#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET 0x0058
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE     OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0058)
+#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET         0x005c
+#define OMAP4430_CM_SDMA_STATICDEP_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x005c)
 #endif
index b101091..f8a660a 100644 (file)
@@ -43,7 +43,6 @@
  *                 using separate functional clock
  *   0x3 disabled: Module is disabled and cannot be accessed
  *
- * TODO: Need to handle module accessible in idle state
  */
 int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
 {
@@ -52,9 +51,11 @@ int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
        if (!clkctrl_reg)
                return 0;
 
-       omap_test_timeout(((__raw_readl(clkctrl_reg) &
-                           OMAP4430_IDLEST_MASK) == 0),
-                         MAX_MODULE_READY_TIME, i);
+       omap_test_timeout((
+               ((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
+                (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
+                 OMAP4430_IDLEST_SHIFT) == 0x2)),
+               MAX_MODULE_READY_TIME, i);
 
        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 }
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
new file mode 100644 (file)
index 0000000..778929f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/mach-omap2/common.c
+ *
+ * Code common to all OMAP2+ machines.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/mux.h>
+
+#include <plat/clock.h>
+
+#include "sdrc.h"
+#include "control.h"
+
+/* Global address base setup code */
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+
+static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
+{
+       omap2_set_globals_tap(omap2_globals);
+       omap2_set_globals_sdrc(omap2_globals);
+       omap2_set_globals_control(omap2_globals);
+       omap2_set_globals_prcm(omap2_globals);
+}
+
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
+
+static struct omap_globals omap242x_globals = {
+       .class  = OMAP242X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x48014000),
+       .sdrc   = OMAP2420_SDRC_BASE,
+       .sms    = OMAP2420_SMS_BASE,
+       .ctrl   = OMAP242X_CTRL_BASE,
+       .prm    = OMAP2420_PRM_BASE,
+       .cm     = OMAP2420_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_242x(void)
+{
+       __omap2_set_globals(&omap242x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2430)
+
+static struct omap_globals omap243x_globals = {
+       .class  = OMAP243X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4900a000),
+       .sdrc   = OMAP243X_SDRC_BASE,
+       .sms    = OMAP243X_SMS_BASE,
+       .ctrl   = OMAP243X_CTRL_BASE,
+       .prm    = OMAP2430_PRM_BASE,
+       .cm     = OMAP2430_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_243x(void)
+{
+       __omap2_set_globals(&omap243x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+
+static struct omap_globals omap3_globals = {
+       .class  = OMAP343X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4830A000),
+       .sdrc   = OMAP343X_SDRC_BASE,
+       .sms    = OMAP343X_SMS_BASE,
+       .ctrl   = OMAP343X_CTRL_BASE,
+       .prm    = OMAP3430_PRM_BASE,
+       .cm     = OMAP3430_CM_BASE,
+       .uart1_phys     = OMAP3_UART1_BASE,
+       .uart2_phys     = OMAP3_UART2_BASE,
+       .uart3_phys     = OMAP3_UART3_BASE,
+       .uart4_phys     = OMAP3_UART4_BASE,     /* Only on 3630 */
+};
+
+void __init omap2_set_globals_3xxx(void)
+{
+       __omap2_set_globals(&omap3_globals);
+}
+
+void __init omap3_map_io(void)
+{
+       omap2_set_globals_3xxx();
+       omap34xx_map_common_io();
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct omap_globals omap4_globals = {
+       .class  = OMAP443X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+       .ctrl   = OMAP443X_SCM_BASE,
+       .ctrl_pad       = OMAP443X_CTRL_BASE,
+       .prm    = OMAP4430_PRM_BASE,
+       .cm     = OMAP4430_CM_BASE,
+       .cm2    = OMAP4430_CM2_BASE,
+       .uart1_phys     = OMAP4_UART1_BASE,
+       .uart2_phys     = OMAP4_UART2_BASE,
+       .uart3_phys     = OMAP4_UART3_BASE,
+       .uart4_phys     = OMAP4_UART4_BASE,
+};
+
+void __init omap2_set_globals_443x(void)
+{
+       omap2_set_globals_tap(&omap4_globals);
+       omap2_set_globals_control(&omap4_globals);
+       omap2_set_globals_prcm(&omap4_globals);
+}
+#endif
+
index a8d20ee..1fa3294 100644 (file)
 #include <linux/io.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/sdrc.h>
+
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "pm.h"
+#include "control.h"
 
 static void __iomem *omap2_ctrl_base;
+static void __iomem *omap4_ctrl_pad_base;
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 struct omap3_scratchpad {
@@ -137,6 +140,7 @@ static struct omap3_control_regs control_context;
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
 
 #define OMAP_CTRL_REGADDR(reg)         (omap2_ctrl_base + (reg))
+#define OMAP4_CTRL_PAD_REGADDR(reg)    (omap4_ctrl_pad_base + (reg))
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
@@ -145,6 +149,12 @@ void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
                omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
                WARN_ON(!omap2_ctrl_base);
        }
+
+       /* Static mapping, never released */
+       if (omap2_globals->ctrl_pad) {
+               omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
+               WARN_ON(!omap4_ctrl_pad_base);
+       }
 }
 
 void __iomem *omap_ctrl_base_get(void)
@@ -182,6 +192,23 @@ void omap_ctrl_writel(u32 val, u16 offset)
        __raw_writel(val, OMAP_CTRL_REGADDR(offset));
 }
 
+/*
+ * On OMAP4 control pad are not addressable from control
+ * core base. So the common omap_ctrl_read/write APIs breaks
+ * Hence export separate APIs to manage the omap4 pad control
+ * registers. This APIs will work only for OMAP4
+ */
+
+u32 omap4_ctrl_pad_readl(u16 offset)
+{
+       return __raw_readl(OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
+void omap4_ctrl_pad_writel(u32 val, u16 offset)
+{
+       __raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 /*
  * Clears the scratchpad contents in case of cold boot-
@@ -190,7 +217,7 @@ void omap_ctrl_writel(u32 val, u16 offset)
 void omap3_clear_scratchpad_contents(void)
 {
        u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
-       u32 *v_addr;
+       void __iomem *v_addr;
        u32 offset = 0;
        v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
        if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
@@ -206,7 +233,7 @@ void omap3_clear_scratchpad_contents(void)
 /* Populate the scratchpad structure with restore structure */
 void omap3_save_scratchpad_contents(void)
 {
-       void * __iomem scratchpad_address;
+       void  __iomem *scratchpad_address;
        u32 arm_context_addr;
        struct omap3_scratchpad scratchpad_contents;
        struct omap3_scratchpad_prcm_block prcm_block_contents;
similarity index 92%
rename from arch/arm/plat-omap/include/plat/control.h
rename to arch/arm/mach-omap2/control.h
index 131bf40..b6c6b7c 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * arch/arm/plat-omap/include/mach/control.h
+ * arch/arm/mach-omap2/control.h
  *
  * OMAP2/3/4 System Control Module definitions
  *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
  * the Free Software Foundation.
  */
 
-#ifndef __ASM_ARCH_CONTROL_H
-#define __ASM_ARCH_CONTROL_H
+#ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
+#define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
 #include <mach/io.h>
+#include <mach/ctrl_module_core_44xx.h>
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/ctrl_module_pad_core_44xx.h>
+#include <mach/ctrl_module_pad_wkup_44xx.h>
 
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)                                     \
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
 
-/* 44xx control status register offset */
-#define OMAP44XX_CONTROL_STATUS                0x2c4
-
-/* 44xx-only CONTROL_GENERAL register offsets */
-#define OMAP44XX_CONTROL_MMC1                  0x628
-#define OMAP44XX_CONTROL_PBIAS_LITE            0x600
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
 #define OMAP2_MMCSDIO1ADPCLKISEL       (1 << 24) /* MMC1 loop back clock */
 #define OMAP24XX_USBSTANDBYCTRL                (1 << 15)
 #define OMAP2_MCBSP2_CLKS_MASK         (1 << 6)
+#define OMAP2_MCBSP1_FSR_MASK          (1 << 4)
+#define OMAP2_MCBSP1_CLKR_MASK         (1 << 3)
 #define OMAP2_MCBSP1_CLKS_MASK         (1 << 2)
 
 /* CONTROL_DEVCONF1 bits */
 #define OMAP2_PBIASLITEPWRDNZ0         (1 << 1)
 #define OMAP2_PBIASLITEVMODE0          (1 << 0)
 
-/* CONTROL_PBIAS_LITE bits for OMAP4 */
-#define OMAP4_MMC1_PWRDNZ                      (1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE          (1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT     (1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR       (1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ            (1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE             (1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ               (1 << 20)
-
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0    (1 << 31)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1    (1 << 30)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2    (1 << 29)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3    (1 << 28)
-#define OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL     (1 << 27)
-#define OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL     (1 << 26)
-#define OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL     (1 << 25)
-
 /* CONTROL_PROG_IO1 bits */
 #define OMAP3630_PRG_SDMMC1_SPEEDCTRL  (1 << 20)
 
 #define                FEAT_L2CACHE_256KB      3
 
 #define OMAP3_ISP_SHIFT                        5
-#define OMAP3_ISP_MASK                 (1<< OMAP3_ISP_SHIFT)
+#define OMAP3_ISP_MASK                 (1 << OMAP3_ISP_SHIFT)
 #define                FEAT_ISP                0
 #define                FEAT_ISP_NONE           1
 
 #define OMAP3_NEON_SHIFT               4
-#define OMAP3_NEON_MASK                        (1<< OMAP3_NEON_SHIFT)
+#define OMAP3_NEON_MASK                        (1 << OMAP3_NEON_SHIFT)
 #define                FEAT_NEON               0
 #define                FEAT_NEON_NONE          1
 
@@ -354,9 +337,11 @@ extern void __iomem *omap_ctrl_base_get(void);
 extern u8 omap_ctrl_readb(u16 offset);
 extern u16 omap_ctrl_readw(u16 offset);
 extern u32 omap_ctrl_readl(u16 offset);
+extern u32 omap4_ctrl_pad_readl(u16 offset);
 extern void omap_ctrl_writeb(u8 val, u16 offset);
 extern void omap_ctrl_writew(u16 val, u16 offset);
 extern void omap_ctrl_writel(u32 val, u16 offset);
+extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
 
 extern void omap3_save_scratchpad_contents(void);
 extern void omap3_clear_scratchpad_contents(void);
@@ -371,11 +356,13 @@ extern void omap3_control_restore_context(void);
 #define omap_ctrl_readb(x)             0
 #define omap_ctrl_readw(x)             0
 #define omap_ctrl_readl(x)             0
+#define omap4_ctrl_pad_readl(x)                0
 #define omap_ctrl_writeb(x, y)         WARN_ON(1)
 #define omap_ctrl_writew(x, y)         WARN_ON(1)
 #define omap_ctrl_writel(x, y)         WARN_ON(1)
+#define omap4_ctrl_pad_writel(x, y)    WARN_ON(1)
 #endif
 #endif /* __ASSEMBLY__ */
 
-#endif /* __ASM_ARCH_CONTROL_H */
+#endif /* __ARCH_ARM_MACH_OMAP2_CONTROL_H */
 
index 3d3d035..0d50b45 100644 (file)
 #include <plat/irqs.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 
 #include "pm.h"
+#include "control.h"
 
 #ifdef CONFIG_CPU_IDLE
 
@@ -60,7 +60,8 @@ struct omap3_processor_cx {
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
-struct powerdomain *mpu_pd, *core_pd;
+struct powerdomain *mpu_pd, *core_pd, *per_pd;
+struct powerdomain *cam_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -233,14 +234,60 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
                               struct cpuidle_state *state)
 {
        struct cpuidle_state *new_state = next_valid_state(dev, state);
+       u32 core_next_state, per_next_state = 0, per_saved_state = 0;
+       u32 cam_state;
+       struct omap3_processor_cx *cx;
+       int ret;
 
        if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
                BUG_ON(!dev->safe_state);
                new_state = dev->safe_state;
+               goto select_state;
        }
 
+       cx = cpuidle_get_statedata(state);
+       core_next_state = cx->core_state;
+
+       /*
+        * FIXME: we currently manage device-specific idle states
+        *        for PER and CORE in combination with CPU-specific
+        *        idle states.  This is wrong, and device-specific
+        *        idle managment needs to be separated out into 
+        *        its own code.
+        */
+
+       /*
+        * Prevent idle completely if CAM is active.
+        * CAM does not have wakeup capability in OMAP3.
+        */
+       cam_state = pwrdm_read_pwrst(cam_pd);
+       if (cam_state == PWRDM_POWER_ON) {
+               new_state = dev->safe_state;
+               goto select_state;
+       }
+
+       /*
+        * Prevent PER off if CORE is not in retention or off as this
+        * would disable PER wakeups completely.
+        */
+       per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
+       if ((per_next_state == PWRDM_POWER_OFF) &&
+           (core_next_state > PWRDM_POWER_RET))
+               per_next_state = PWRDM_POWER_RET;
+
+       /* Are we changing PER target state? */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+select_state:
        dev->last_state = new_state;
-       return omap3_enter_idle(dev, new_state);
+       ret = omap3_enter_idle(dev, new_state);
+
+       /* Restore original PER state if it was modified */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_saved_state);
+
+       return ret;
 }
 
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
@@ -328,7 +375,8 @@ void omap_init_power_states(void)
                        cpuidle_params_table[OMAP3_STATE_C2].threshold;
        omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
        omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
-       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
+       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+                               CPUIDLE_FLAG_CHECK_BM;
 
        /* C3 . MPU CSWR + Core inactive */
        omap3_power_states[OMAP3_STATE_C3].valid =
@@ -426,6 +474,8 @@ int __init omap3_idle_init(void)
 
        mpu_pd = pwrdm_lookup("mpu_pwrdm");
        core_pd = pwrdm_lookup("core_pwrdm");
+       per_pd = pwrdm_lookup("per_pwrdm");
+       cam_pd = pwrdm_lookup("cam_pwrdm");
 
        omap_init_power_states();
        cpuidle_register_driver(&omap3_idle_driver);
index b27e7cb..5a0c148 100644 (file)
@@ -9,12 +9,12 @@
  * (at your option) any later version.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
 
-#include <plat/control.h>
 #include <plat/tc.h>
 #include <plat/board.h>
+#include <plat/mcbsp.h>
 #include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "mux.h"
+#include "control.h"
 
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
@@ -235,6 +238,43 @@ static inline void omap_init_mbox(void) { }
 
 static inline void omap_init_sti(void) {}
 
+#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
+
+static struct platform_device omap_pcm = {
+       .name   = "omap-pcm-audio",
+       .id     = -1,
+};
+
+/*
+ * OMAP2420 has 2 McBSP ports
+ * OMAP2430 has 5 McBSP ports
+ * OMAP3 has 5 McBSP ports
+ * OMAP4 has 4 McBSP ports
+ */
+OMAP_MCBSP_PLATFORM_DEVICE(1);
+OMAP_MCBSP_PLATFORM_DEVICE(2);
+OMAP_MCBSP_PLATFORM_DEVICE(3);
+OMAP_MCBSP_PLATFORM_DEVICE(4);
+OMAP_MCBSP_PLATFORM_DEVICE(5);
+
+static void omap_init_audio(void)
+{
+       platform_device_register(&omap_mcbsp1);
+       platform_device_register(&omap_mcbsp2);
+       if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+               platform_device_register(&omap_mcbsp3);
+               platform_device_register(&omap_mcbsp4);
+       }
+       if (cpu_is_omap243x() || cpu_is_omap34xx())
+               platform_device_register(&omap_mcbsp5);
+
+       platform_device_register(&omap_pcm);
+}
+
+#else
+static inline void omap_init_audio(void) {}
+#endif
+
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
 #include <plat/mcspi.h>
@@ -500,7 +540,7 @@ static inline void omap_init_sham(void) { }
 
 #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
 
-#ifdef CONFIG_ARCH_OMAP24XX
+#ifdef CONFIG_ARCH_OMAP2
 static struct resource omap2_aes_resources[] = {
        {
                .start  = OMAP24XX_SEC_AES_BASE,
@@ -522,7 +562,7 @@ static int omap2_aes_resources_sz = ARRAY_SIZE(omap2_aes_resources);
 #define omap2_aes_resources_sz         0
 #endif
 
-#ifdef CONFIG_ARCH_OMAP34XX
+#ifdef CONFIG_ARCH_OMAP3
 static struct resource omap3_aes_resources[] = {
        {
                .start  = OMAP34XX_SEC_AES_BASE,
@@ -694,7 +734,7 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                omap_mux_init_signal("sdmmc_dat0", 0);
                omap_mux_init_signal("sdmmc_dat_dir0", 0);
                omap_mux_init_signal("sdmmc_cmd_dir", 0);
-               if (mmc_controller->slots[0].wires == 4) {
+               if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
                        omap_mux_init_signal("sdmmc_dat1", 0);
                        omap_mux_init_signal("sdmmc_dat2", 0);
                        omap_mux_init_signal("sdmmc_dat3", 0);
@@ -722,8 +762,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                OMAP_PIN_INPUT_PULLUP);
                        omap_mux_init_signal("sdmmc1_dat0",
                                OMAP_PIN_INPUT_PULLUP);
-                       if (mmc_controller->slots[0].wires == 4 ||
-                               mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                               (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc1_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc1_dat2",
@@ -731,7 +771,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc1_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                                               MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc1_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc1_dat5",
@@ -755,8 +796,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                         * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
                         * in the board-*.c files
                         */
-                       if (mmc_controller->slots[0].wires == 4 ||
-                               mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                               (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc2_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc2_dat2",
@@ -764,7 +805,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc2_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                                                       MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
@@ -815,13 +857,13 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                case 3:
                        if (!cpu_is_omap44xx())
                                return;
-                       base = OMAP4_MMC4_BASE + OMAP4_MMC_REG_OFFSET;
+                       base = OMAP4_MMC4_BASE;
                        irq = OMAP44XX_IRQ_MMC4;
                        break;
                case 4:
                        if (!cpu_is_omap44xx())
                                return;
-                       base = OMAP4_MMC5_BASE + OMAP4_MMC_REG_OFFSET;
+                       base = OMAP4_MMC5_BASE;
                        irq = OMAP44XX_IRQ_MMC5;
                        break;
                default:
@@ -832,10 +874,8 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                        size = OMAP2420_MMC_SIZE;
                        name = "mmci-omap";
                } else if (cpu_is_omap44xx()) {
-                       if (i < 3) {
-                               base += OMAP4_MMC_REG_OFFSET;
+                       if (i < 3)
                                irq += OMAP44XX_IRQ_GIC_START;
-                       }
                        size = OMAP4_HSMMC_SIZE;
                        name = "mmci-omap-hs";
                } else {
@@ -911,12 +951,74 @@ static inline void omap_init_vout(void) {}
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Inorder to avoid any assumptions from bootloader regarding WDT
+ * settings, WDT module is reset during init. This enables the watchdog
+ * timer. Hence it is required to disable the watchdog after the WDT reset
+ * during init. Otherwise the system would reboot as per the default
+ * watchdog timer registers settings.
+ */
+#define OMAP_WDT_WPS   (0x34)
+#define OMAP_WDT_SPR   (0x48)
+
+static int omap2_disable_wdt(struct omap_hwmod *oh, void *unused)
+{
+       void __iomem *base;
+       int ret;
+
+       if (!oh) {
+               pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
+               return -EINVAL;
+       }
+
+       base = omap_hwmod_get_mpu_rt_va(oh);
+       if (!base) {
+               pr_err("%s: Could not get the base address for %s\n",
+                               oh->name, __func__);
+               return -EINVAL;
+       }
+
+       /* Enable the clocks before accessing the WDT registers */
+       ret = omap_hwmod_enable(oh);
+       if (ret) {
+               pr_err("%s: Could not enable clocks for %s\n",
+                               oh->name, __func__);
+               return ret;
+       }
+
+       /* sequence required to disable watchdog */
+       __raw_writel(0xAAAA, base + OMAP_WDT_SPR);
+       while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+               cpu_relax();
+
+       __raw_writel(0x5555, base + OMAP_WDT_SPR);
+       while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+               cpu_relax();
+
+       ret = omap_hwmod_idle(oh);
+       if (ret)
+               pr_err("%s: Could not disable clocks for %s\n",
+                               oh->name, __func__);
+
+       return ret;
+}
+
+static void __init omap_disable_wdt(void)
+{
+       if (cpu_class_is_omap2())
+               omap_hwmod_for_each_by_class("wd_timer",
+                                               omap2_disable_wdt, NULL);
+       return;
+}
+
 static int __init omap2_init_devices(void)
 {
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
+       omap_disable_wdt();
        omap_hsmmc_reset();
+       omap_init_audio();
        omap_init_camera();
        omap_init_mbox();
        omap_init_mcspi();
@@ -930,3 +1032,39 @@ static int __init omap2_init_devices(void)
        return 0;
 }
 arch_initcall(omap2_init_devices);
+
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+struct omap_device_pm_latency omap_wdt_latency[] = {
+       [0] = {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func   = omap_device_enable_hwmods,
+               .flags           = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+static int __init omap_init_wdt(void)
+{
+       int id = -1;
+       struct omap_device *od;
+       struct omap_hwmod *oh;
+       char *oh_name = "wd_timer2";
+       char *dev_name = "omap_wdt";
+
+       if (!cpu_class_is_omap2())
+               return 0;
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up wd_timer%d hwmod\n", id);
+               return -EINVAL;
+       }
+
+       od = omap_device_build(dev_name, id, oh, NULL, 0,
+                               omap_wdt_latency,
+                               ARRAY_SIZE(omap_wdt_latency), 0);
+       WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n",
+                               dev_name, oh->name);
+       return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
new file mode 100644 (file)
index 0000000..703f150
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-omap2/gpmc-smsc911x.c
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+
+#include <plat/board.h>
+#include <plat/gpmc.h>
+#include <plat/gpmc-smsc911x.h>
+
+static struct omap_smsc911x_platform_data *gpmc_cfg;
+
+static struct resource gpmc_smsc911x_resources[] = {
+       [0] = {
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct smsc911x_platform_config gpmc_smsc911x_config = {
+       .phy_interface  = PHY_INTERFACE_MODE_MII,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type       = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+       .flags          = SMSC911X_USE_16BIT,
+};
+
+static struct platform_device gpmc_smsc911x_device = {
+       .name           = "smsc911x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(gpmc_smsc911x_resources),
+       .resource       = gpmc_smsc911x_resources,
+       .dev            = {
+               .platform_data = &gpmc_smsc911x_config,
+       },
+};
+
+/*
+ * Initialize smsc911x device connected to the GPMC. Note that we
+ * assume that pin multiplexing is done in the board-*.c file,
+ * or in the bootloader.
+ */
+void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
+{
+       unsigned long cs_mem_base;
+       int ret;
+
+       gpmc_cfg = board_data;
+
+       if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
+               printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n");
+               return;
+       }
+
+       gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
+       gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+
+       if (gpio_request(gpmc_cfg->gpio_irq, "smsc911x irq") < 0) {
+               printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
+                               gpmc_cfg->gpio_irq);
+               goto free1;
+       }
+
+       gpio_direction_input(gpmc_cfg->gpio_irq);
+       gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+       gpmc_smsc911x_resources[1].flags |=
+                                       (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+
+       if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
+               ret = gpio_request(gpmc_cfg->gpio_reset, "smsc911x reset");
+               if (ret) {
+                       printk(KERN_ERR "Failed to request GPIO%d for smsc911x reset\n",
+                                       gpmc_cfg->gpio_reset);
+                       goto free2;
+               }
+
+               gpio_direction_output(gpmc_cfg->gpio_reset, 1);
+               gpio_set_value(gpmc_cfg->gpio_reset, 0);
+               msleep(100);
+               gpio_set_value(gpmc_cfg->gpio_reset, 1);
+       }
+
+       if (platform_device_register(&gpmc_smsc911x_device) < 0) {
+               printk(KERN_ERR "Unable to register smsc911x device\n");
+               gpio_free(gpmc_cfg->gpio_reset);
+               goto free2;
+       }
+
+       return;
+
+free2:
+       gpio_free(gpmc_cfg->gpio_irq);
+free1:
+       gpmc_cs_free(gpmc_cfg->cs);
+
+       printk(KERN_ERR "Could not initialize smsc911x\n");
+}
index c8f647b..34272e4 100644 (file)
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <mach/hardware.h>
-#include <plat/control.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
 
 #include "hsmmc.h"
+#include "control.h"
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -135,10 +135,11 @@ static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
         *
         * FIXME handle VMMC1A as needed ...
         */
-       reg = omap_ctrl_readl(control_pbias_offset);
-       reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-                                       OMAP4_USBC1_ICUSB_PWRDNZ);
-       omap_ctrl_writel(reg, control_pbias_offset);
+       reg = omap4_ctrl_pad_readl(control_pbias_offset);
+       reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+               OMAP4_MMC1_PWRDNZ_MASK |
+               OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+       omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
 static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
@@ -147,30 +148,33 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
        u32 reg;
 
        if (power_on) {
-               reg = omap_ctrl_readl(control_pbias_offset);
-               reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ;
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK;
                if ((1 << vdd) <= MMC_VDD_165_195)
-                       reg &= ~OMAP4_MMC1_PBIASLITE_VMODE;
+                       reg &= ~OMAP4_MMC1_PBIASLITE_VMODE_MASK;
                else
-                       reg |= OMAP4_MMC1_PBIASLITE_VMODE;
-               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-                                               OMAP4_USBC1_ICUSB_PWRDNZ);
-               omap_ctrl_writel(reg, control_pbias_offset);
+                       reg |= OMAP4_MMC1_PBIASLITE_VMODE_MASK;
+               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+                       OMAP4_MMC1_PWRDNZ_MASK |
+                       OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+               omap4_ctrl_pad_writel(reg, control_pbias_offset);
                /* 4 microsec delay for comparator to generate an error*/
                udelay(4);
-               reg = omap_ctrl_readl(control_pbias_offset);
-               if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR) {
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
                        pr_err("Pbias Voltage is not same as LDO\n");
                        /* Caution : On VMODE_ERROR Power Down MMC IO */
-                       reg &= ~(OMAP4_MMC1_PWRDNZ | OMAP4_USBC1_ICUSB_PWRDNZ);
-                       omap_ctrl_writel(reg, control_pbias_offset);
+                       reg &= ~(OMAP4_MMC1_PWRDNZ_MASK |
+                               OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+                       omap4_ctrl_pad_writel(reg, control_pbias_offset);
                }
        } else {
-               reg = omap_ctrl_readl(control_pbias_offset);
-                reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ |
-                       OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDNZ |
-                       OMAP4_USBC1_ICUSB_PWRDNZ);
-               omap_ctrl_writel(reg, control_pbias_offset);
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+                       OMAP4_MMC1_PWRDNZ_MASK |
+                       OMAP4_MMC1_PBIASLITE_VMODE_MASK |
+                       OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+               omap4_ctrl_pad_writel(reg, control_pbias_offset);
        }
 }
 
@@ -218,17 +222,18 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                        control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
                }
        } else {
-               control_pbias_offset = OMAP44XX_CONTROL_PBIAS_LITE;
-               control_mmc1 = OMAP44XX_CONTROL_MMC1;
-               reg = omap_ctrl_readl(control_mmc1);
-               reg |= (OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 |
-                       OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1);
-               reg &= ~(OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 |
-                       OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3);
-               reg |= (OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL |
-                       OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL |
-                       OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL);
-               omap_ctrl_writel(reg, control_mmc1);
+               control_pbias_offset =
+                       OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
+               control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
+               reg = omap4_ctrl_pad_readl(control_mmc1);
+               reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
+                       OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
+               reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
+                       OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
+               reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+                       OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
+                       OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
+               omap4_ctrl_pad_writel(reg, control_mmc1);
        }
 
        for (c = controllers; c->mmc; c++) {
@@ -258,9 +263,13 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                                "mmc%islot%i", c->mmc, 1);
                mmc->slots[0].name = hc->name;
                mmc->nr_slots = 1;
-               mmc->slots[0].wires = c->wires;
+               mmc->slots[0].caps = c->caps;
                mmc->slots[0].internal_clock = !c->ext_clock;
                mmc->dma_mask = 0xffffffff;
+               if (cpu_is_omap44xx())
+                       mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
+               else
+                       mmc->reg_offset = 0;
 
                mmc->get_context_loss_count = hsmmc_get_context_loss;
 
@@ -298,6 +307,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                else
                        mmc->slots[0].features |= HSMMC_HAS_PBIAS;
 
+               if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
+                       mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
                switch (c->mmc) {
                case 1:
                        if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
@@ -316,16 +328,20 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                        }
 
                        /* Omap3630 HSMMC1 supports only 4-bit */
-                       if (cpu_is_omap3630() && c->wires > 4) {
-                               c->wires = 4;
-                               mmc->slots[0].wires = c->wires;
+                       if (cpu_is_omap3630() &&
+                                       (c->caps & MMC_CAP_8_BIT_DATA)) {
+                               c->caps &= ~MMC_CAP_8_BIT_DATA;
+                               c->caps |= MMC_CAP_4_BIT_DATA;
+                               mmc->slots[0].caps = c->caps;
                        }
                        break;
                case 2:
                        if (c->ext_clock)
                                c->transceiver = 1;
-                       if (c->transceiver && c->wires > 4)
-                               c->wires = 4;
+                       if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
+                               c->caps &= ~MMC_CAP_8_BIT_DATA;
+                               c->caps |= MMC_CAP_4_BIT_DATA;
+                       }
                        /* FALLTHROUGH */
                case 3:
                        if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
index 0f8a2e6..f119348 100644 (file)
@@ -10,7 +10,8 @@ struct mmc_card;
 
 struct omap2_hsmmc_info {
        u8      mmc;            /* controller 1/2/3 */
-       u8      wires;          /* 1/4/8 wires */
+       u32     caps;           /* 4/8 wires and any additional host
+                                * capabilities OR'd (ref. linux/mmc/host.h) */
        bool    transceiver;    /* MMC-2 option */
        bool    ext_clock;      /* use external pin for input clock */
        bool    cover_only;     /* No card detect - just cover switch */
index 9a879f9..5f9086c 100644 (file)
 #include <asm/cputype.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/cpu.h>
 
 #include <mach/id.h>
 
+#include "control.h"
+
 static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
@@ -60,7 +61,7 @@ int omap_type(void)
        } else if (cpu_is_omap34xx()) {
                val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
        } else if (cpu_is_omap44xx()) {
-               val = omap_ctrl_readl(OMAP44XX_CONTROL_STATUS);
+               val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
        } else {
                pr_err("Cannot detect omap type!\n");
                goto out;
@@ -298,7 +299,6 @@ static void __init omap4_check_revision(void)
        u32 idcode;
        u16 hawkeye;
        u8 rev;
-       char *rev_name = "ES1.0";
 
        /*
         * The IC rev detection is done with hawkeye and rev.
@@ -309,14 +309,39 @@ static void __init omap4_check_revision(void)
        hawkeye = (idcode >> 12) & 0xffff;
        rev = (idcode >> 28) & 0xff;
 
-       if ((hawkeye == 0xb852) && (rev == 0x0)) {
-               omap_revision = OMAP4430_REV_ES1_0;
-               omap_chip.oc |= CHIP_IS_OMAP4430ES1;
-               pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name);
-               return;
+       /*
+        * Few initial ES2.0 samples IDCODE is same as ES1.0
+        * Use ARM register to detect the correct ES version
+        */
+       if (!rev) {
+               idcode = read_cpuid(CPUID_ID);
+               rev = (idcode & 0xf) - 1;
+       }
+
+       switch (hawkeye) {
+       case 0xb852:
+               switch (rev) {
+               case 0:
+                       omap_revision = OMAP4430_REV_ES1_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES1;
+                       break;
+               case 1:
+                       omap_revision = OMAP4430_REV_ES2_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+                       break;
+               default:
+                       omap_revision = OMAP4430_REV_ES2_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+       }
+       break;
+       default:
+               /* Unknown default to latest silicon rev as default*/
+               omap_revision = OMAP4430_REV_ES2_0;
+               omap_chip.oc |= CHIP_IS_OMAP4430ES2;
        }
 
-       pr_err("Unknown OMAP4 CPU id\n");
+       pr_info("OMAP%04x ES%d.0\n",
+                       omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1);
 }
 
 #define OMAP3_SHOW_FEATURE(feat)               \
@@ -361,30 +386,54 @@ static void __init omap3_cpuinfo(void)
                strcpy(cpu_name, "OMAP3503");
        }
 
-       switch (rev) {
-       case OMAP_REVBITS_00:
-               strcpy(cpu_rev, "1.0");
-               break;
-       case OMAP_REVBITS_01:
-               strcpy(cpu_rev, "1.1");
-               break;
-       case OMAP_REVBITS_02:
-               strcpy(cpu_rev, "1.2");
-               break;
-       case OMAP_REVBITS_10:
-               strcpy(cpu_rev, "2.0");
-               break;
-       case OMAP_REVBITS_20:
-               strcpy(cpu_rev, "2.1");
-               break;
-       case OMAP_REVBITS_30:
-               strcpy(cpu_rev, "3.0");
-               break;
-       case OMAP_REVBITS_40:
-       /* FALLTHROUGH */
-       default:
-               /* Use the latest known revision as default */
-               strcpy(cpu_rev, "3.1");
+       if (cpu_is_omap3630()) {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       strcpy(cpu_rev, "1.1");
+                       break;
+               case OMAP_REVBITS_02:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "1.2");
+               }
+       } else if (cpu_is_omap3505() || cpu_is_omap3517()) {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "1.1");
+               }
+       } else {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       strcpy(cpu_rev, "2.0");
+                       break;
+               case OMAP_REVBITS_02:
+                       strcpy(cpu_rev, "2.1");
+                       break;
+               case OMAP_REVBITS_03:
+                       strcpy(cpu_rev, "3.0");
+                       break;
+               case OMAP_REVBITS_04:
+                       strcpy(cpu_rev, "3.1");
+                       break;
+               case OMAP_REVBITS_05:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "3.1.2");
+               }
        }
 
        /* Print verbose information */
diff --git a/arch/arm/mach-omap2/include/mach/board-rx51.h b/arch/arm/mach-omap2/include/mach/board-rx51.h
new file mode 100644 (file)
index 0000000..b76f49e
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Defines for rx51 boards
+ */
+
+#ifndef _OMAP_BOARD_RX51_H
+#define _OMAP_BOARD_RX51_H
+
+extern void __init rx51_peripherals_init(void);
+extern void __init rx51_video_mem_init(void);
+
+#endif
index 3af69d2..f93ca39 100644 (file)
@@ -1,11 +1,9 @@
 /*
  * Defines for zoom boards
  */
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
 #define ZOOM_NAND_CS    0
 
-extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs);
 extern int __init zoom_debugboard_init(void);
 extern void __init zoom_peripherals_init(void);
+
+#define ZOOM2_HEADSET_EXTMUTE_GPIO     153
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
new file mode 100644 (file)
index 0000000..2f7ac70
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * OMAP44xx CTRL_MODULE_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_CORE                                 0x4a002000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_CORE_IP_REVISION                     0x0000
+#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO                       0x0004
+#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG                    0x0010
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0               0x0200
+#define OMAP4_CTRL_MODULE_CORE_ID_CODE                         0x0204
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1               0x0208
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2               0x020c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3               0x0210
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0              0x0214
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1              0x0218
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF               0x021c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP           0x0228
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP               0x0260
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0             0x0264
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1             0x0268
+#define OMAP4_CTRL_MODULE_CORE_STATUS                          0x02c4
+#define OMAP4_CTRL_MODULE_CORE_DEV_CONF                                0x0300
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL         0x0314
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL         0x0318
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL                0x0320
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL                0x0324
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL       0x0328
+#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR                     0x032c
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0               0x0330
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1               0x0334
+#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL                        0x033c
+#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL                     0x0340
+#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL                   0x0350
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL            0x0400
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU                  0x0408
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0              0x042c
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1              0x0430
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2              0x0434
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3              0x0438
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0                   0x0440
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1                   0x0444
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2                   0x0448
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL          0x044c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL            0x0450
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL         0x0454
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0            0x0480
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1            0x0484
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2            0x0488
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3            0x048c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4            0x0490
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5            0x0494
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6            0x0498
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7            0x049c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8            0x04a0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9            0x04a4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10           0x04a8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11           0x04ac
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12           0x04b0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13           0x04b4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14           0x04b8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15           0x04bc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16           0x04c0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17           0x04c4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18           0x04c8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19           0x04cc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20           0x04d0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21           0x04d4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22           0x04d8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23           0x04dc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24           0x04e0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25           0x04e4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26           0x04e8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27           0x04ec
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28           0x04f0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29           0x04f4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30           0x04f8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31           0x04fc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                      30
+#define OMAP4_IP_REV_SCHEME_MASK                       (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                16
+#define OMAP4_IP_REV_FUNC_MASK                         (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                         11
+#define OMAP4_IP_REV_RTL_MASK                          (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                       8
+#define OMAP4_IP_REV_MAJOR_MASK                                (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                      6
+#define OMAP4_IP_REV_CUSTOM_MASK                       (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                       0
+#define OMAP4_IP_REV_MINOR_MASK                                (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                          0
+#define OMAP4_IP_HWINFO_MASK                           (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT              2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK               (0x3 << 2)
+
+/* STD_FUSE_DIE_ID_0 */
+#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_0_MASK                   (0xffffffff << 0)
+
+/* ID_CODE */
+#define OMAP4_STD_FUSE_IDCODE_SHIFT                    0
+#define OMAP4_STD_FUSE_IDCODE_MASK                     (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_1 */
+#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_1_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_2 */
+#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_2_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_3 */
+#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_3_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_0 */
+#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT                 0
+#define OMAP4_STD_FUSE_PROD_ID_0_MASK                  (0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_1 */
+#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT                 0
+#define OMAP4_STD_FUSE_PROD_ID_1_MASK                  (0xffffffff << 0)
+
+/* STD_FUSE_USB_CONF */
+#define OMAP4_USB_PROD_ID_SHIFT                                16
+#define OMAP4_USB_PROD_ID_MASK                         (0xffff << 16)
+#define OMAP4_USB_VENDOR_ID_SHIFT                      0
+#define OMAP4_USB_VENDOR_ID_MASK                       (0xffff << 0)
+
+/* STD_FUSE_OPP_VDD_WKUP */
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT              0
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK               (0xffffffff << 0)
+
+/* STD_FUSE_OPP_BGAP */
+#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT                  0
+#define OMAP4_STD_FUSE_OPP_BGAP_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_0 */
+#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT                        0
+#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK                 (0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_1 */
+#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT                        0
+#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK                 (0xffffffff << 0)
+
+/* STATUS */
+#define OMAP4_ATTILA_CONF_SHIFT                                11
+#define OMAP4_ATTILA_CONF_MASK                         (0x3 << 11)
+#define OMAP4_DEVICE_TYPE_SHIFT                                8
+#define OMAP4_DEVICE_TYPE_MASK                         (0x7 << 8)
+#define OMAP4_SYS_BOOT_SHIFT                           0
+#define OMAP4_SYS_BOOT_MASK                            (0xff << 0)
+
+/* DEV_CONF */
+#define OMAP4_DEV_CONF_SHIFT                           1
+#define OMAP4_DEV_CONF_MASK                            (0x7fffffff << 1)
+#define OMAP4_USBPHY_PD_SHIFT                          0
+#define OMAP4_USBPHY_PD_MASK                           (1 << 0)
+
+/* LDOVBB_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT             26
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK              (1 << 26)
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT              21
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK               (0x1f << 21)
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT             16
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK              (0x1f << 16)
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT             10
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK              (1 << 10)
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT              5
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK               (0x1f << 5)
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT             0
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK              (0x1f << 0)
+
+/* LDOVBB_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT             26
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK              (1 << 26)
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT              21
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK               (0x1f << 21)
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT             16
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK              (0x1f << 16)
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT             10
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK              (1 << 10)
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT              5
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK               (0x1f << 5)
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT             0
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK              (0x1f << 0)
+
+/* LDOSRAM_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT                26
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK         (1 << 26)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT         21
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK          (0x1f << 21)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT                16
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK         (0x1f << 16)
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT                10
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK         (1 << 10)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT         5
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK          (0x1f << 5)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT                0
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK         (0x1f << 0)
+
+/* LDOSRAM_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT                26
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK         (1 << 26)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT         21
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK          (0x1f << 21)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT                16
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK         (0x1f << 16)
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT                10
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK         (1 << 10)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT         5
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK          (0x1f << 5)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT                0
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK         (0x1f << 0)
+
+/* LDOSRAM_CORE_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT       26
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK                (1 << 26)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT                21
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK         (0x1f << 21)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT       16
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK                (0x1f << 16)
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT       10
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK                (1 << 10)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT                5
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK         (0x1f << 5)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT       0
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK                (0x1f << 0)
+
+/* TEMP_SENSOR */
+#define OMAP4_BGAP_TEMPSOFF_SHIFT                      12
+#define OMAP4_BGAP_TEMPSOFF_MASK                       (1 << 12)
+#define OMAP4_BGAP_TSHUT_SHIFT                         11
+#define OMAP4_BGAP_TSHUT_MASK                          (1 << 11)
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT          10
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK           (1 << 10)
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT               9
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK                        (1 << 9)
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT              8
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK               (1 << 8)
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT             0
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK              (0xff << 0)
+
+/* DPLL_NWELL_TRIM_0 */
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT       29
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK                (1 << 29)
+#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT                        24
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK                 (0x1f << 24)
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT       23
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK                (1 << 23)
+#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT                        18
+#define OMAP4_DPLL_PER_NWELL_TRIM_MASK                 (0x1f << 18)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT      17
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK       (1 << 17)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT               12
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK                        (0x1f << 12)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT       11
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK                (1 << 11)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT                        6
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK                 (0x1f << 6)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT       5
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK                (1 << 5)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT                        0
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK                 (0x1f << 0)
+
+/* DPLL_NWELL_TRIM_1 */
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT    29
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK     (1 << 29)
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT             24
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK              (0x1f << 24)
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT       23
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK                (1 << 23)
+#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT                        18
+#define OMAP4_DPLL_USB_NWELL_TRIM_MASK                 (0x1f << 18)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT      17
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK       (1 << 17)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT               12
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK                        (0x1f << 12)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT      11
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK       (1 << 11)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT               6
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK                        (0x1f << 6)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT      5
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK       (1 << 5)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT               0
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK                        (0x1f << 0)
+
+/* USBOTGHS_CONTROL */
+#define OMAP4_DISCHRGVBUS_SHIFT                                8
+#define OMAP4_DISCHRGVBUS_MASK                         (1 << 8)
+#define OMAP4_CHRGVBUS_SHIFT                           7
+#define OMAP4_CHRGVBUS_MASK                            (1 << 7)
+#define OMAP4_DRVVBUS_SHIFT                            6
+#define OMAP4_DRVVBUS_MASK                             (1 << 6)
+#define OMAP4_IDPULLUP_SHIFT                           5
+#define OMAP4_IDPULLUP_MASK                            (1 << 5)
+#define OMAP4_IDDIG_SHIFT                              4
+#define OMAP4_IDDIG_MASK                               (1 << 4)
+#define OMAP4_SESSEND_SHIFT                            3
+#define OMAP4_SESSEND_MASK                             (1 << 3)
+#define OMAP4_VBUSVALID_SHIFT                          2
+#define OMAP4_VBUSVALID_MASK                           (1 << 2)
+#define OMAP4_BVALID_SHIFT                             1
+#define OMAP4_BVALID_MASK                              (1 << 1)
+#define OMAP4_AVALID_SHIFT                             0
+#define OMAP4_AVALID_MASK                              (1 << 0)
+
+/* DSS_CONTROL */
+#define OMAP4_DSS_MUX6_SELECT_SHIFT                    0
+#define OMAP4_DSS_MUX6_SELECT_MASK                     (1 << 0)
+
+/* HWOBS_CONTROL */
+#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT                   3
+#define OMAP4_HWOBS_CLKDIV_SEL_MASK                    (0x1f << 3)
+#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT                        2
+#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK                 (1 << 2)
+#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT                 1
+#define OMAP4_HWOBS_ALL_ONE_MODE_MASK                  (1 << 1)
+#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT                 0
+#define OMAP4_HWOBS_MACRO_ENABLE_MASK                  (1 << 0)
+
+/* DEBOBS_FINAL_MUX_SEL */
+#define OMAP4_SELECT_SHIFT                             0
+#define OMAP4_SELECT_MASK                              (0xffffffff << 0)
+
+/* DEBOBS_MMR_MPU */
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT              0
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK               (0xf << 0)
+
+/* CONF_SDMA_REQ_SEL0 */
+#define OMAP4_MULT_SHIFT                               0
+#define OMAP4_MULT_MASK                                        (0x7f << 0)
+
+/* CONF_CLK_SEL0 */
+#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL0_MASK                  (0x7 << 0)
+
+/* CONF_CLK_SEL1 */
+#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL1_MASK                  (0x7 << 0)
+
+/* CONF_CLK_SEL2 */
+#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL2_MASK                  (0x7 << 0)
+
+/* CONF_DPLL_FREQLOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT                0
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK         (0x7 << 0)
+
+/* CONF_DPLL_TINITZ_SEL */
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT          0
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK           (0x7 << 0)
+
+/* CONF_DPLL_PHASELOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT       0
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK                (0x7 << 0)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_MODE_SHIFT                               0
+#define OMAP4_MODE_MASK                                        (0xf << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
new file mode 100644 (file)
index 0000000..c88420d
--- /dev/null
@@ -0,0 +1,1409 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_CORE                             0x4a100000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION                 0x0000
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO                   0x0004
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG                        0x0010
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0       0x01d8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1       0x01dc
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2       0x01e0
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3       0x01e4
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4       0x01e8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5       0x01ec
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6       0x01f0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL      0x05a0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE                0x05a4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0  0x05a8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1  0x05ac
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0  0x05b0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1  0x05b4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0  0x05b8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1  0x05bc
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2  0x05c0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC           0x05c4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS             0x05c8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE           0x0600
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0               0x0604
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX           0x0608
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC               0x060c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY         0x0610
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2                        0x0614
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY              0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP             0x061c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE         0x0620
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1               0x0624
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1                        0x0628
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI                 0x062c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB                 0x0630
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ                 0x0634
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0         0x0638
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1         0x063c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2         0x0640
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3         0x0644
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0         0x0648
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1         0x064c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2         0x0650
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3         0x0654
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD            0x0658
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C                 0x065c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW       0x0660
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R                0x0664
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0     0x0668
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1             0x0700
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2             0x0704
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3             0x0708
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4             0x070c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                              30
+#define OMAP4_IP_REV_SCHEME_MASK                               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                        16
+#define OMAP4_IP_REV_FUNC_MASK                                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                                 11
+#define OMAP4_IP_REV_RTL_MASK                                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                               8
+#define OMAP4_IP_REV_MAJOR_MASK                                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                              6
+#define OMAP4_IP_REV_CUSTOM_MASK                               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                               0
+#define OMAP4_IP_REV_MINOR_MASK                                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                                  0
+#define OMAP4_IP_HWINFO_MASK                                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT                      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK                       (0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT              31
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK               (1 << 31)
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT              30
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK               (1 << 30)
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT             29
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK              (1 << 29)
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT             28
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK              (1 << 28)
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT             27
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK              (1 << 27)
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT             26
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK              (1 << 26)
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT              25
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK               (1 << 25)
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT              19
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK               (1 << 19)
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT              18
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK               (1 << 18)
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT              17
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK               (1 << 17)
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT              16
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK               (1 << 16)
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT             15
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK              (1 << 15)
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT             14
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK              (1 << 14)
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT             11
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK              (1 << 11)
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT             10
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK              (1 << 10)
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT              9
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK               (1 << 9)
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT              8
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK               (1 << 8)
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT              7
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK               (1 << 7)
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT              6
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK               (1 << 6)
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT              5
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK               (1 << 5)
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT              4
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK               (1 << 4)
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT              3
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK               (1 << 3)
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT              2
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK               (1 << 2)
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT              1
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK               (1 << 1)
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT              0
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK               (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_1 */
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT           30
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK            (1 << 30)
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT             29
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK              (1 << 29)
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT             28
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK              (1 << 28)
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT             27
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK              (1 << 27)
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT             26
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK              (1 << 26)
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT             25
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK              (1 << 25)
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT             24
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK              (1 << 24)
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT             23
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK              (1 << 23)
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT             22
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK              (1 << 22)
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT             21
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK              (1 << 21)
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT             20
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK              (1 << 20)
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT             19
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK              (1 << 19)
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT             16
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK              (1 << 16)
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT          15
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK           (1 << 15)
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT          14
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK           (1 << 14)
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT              13
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK               (1 << 13)
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT              12
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK               (1 << 12)
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT            11
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK             (1 << 11)
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT            10
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK             (1 << 10)
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT            9
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK             (1 << 9)
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT            8
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK             (1 << 8)
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT            7
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK             (1 << 7)
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT            6
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK             (1 << 6)
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT             4
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK              (1 << 4)
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT         3
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK          (1 << 3)
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT              2
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK               (1 << 2)
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT              1
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK               (1 << 1)
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT         0
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK          (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_2 */
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT       31
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK                (1 << 31)
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT                30
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK         (1 << 30)
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT         29
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK          (1 << 29)
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT         28
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK          (1 << 28)
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT       27
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK                (1 << 27)
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT           26
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK            (1 << 26)
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT           25
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK            (1 << 25)
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT           24
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK            (1 << 24)
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT           23
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK            (1 << 23)
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT           22
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK            (1 << 22)
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT           21
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK            (1 << 21)
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT           20
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK            (1 << 20)
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT           19
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK            (1 << 19)
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT            18
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK             (1 << 18)
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT            17
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 17)
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT                16
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK         (1 << 16)
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT                15
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK         (1 << 15)
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT     14
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK      (1 << 14)
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT       13
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 13)
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT    12
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK     (1 << 12)
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT    11
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK     (1 << 11)
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT    10
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK     (1 << 10)
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT    9
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK     (1 << 9)
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT    8
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK     (1 << 8)
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT    7
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK     (1 << 7)
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT    6
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK     (1 << 6)
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT    5
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK     (1 << 5)
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT     4
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK      (1 << 4)
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT     3
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK      (1 << 3)
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT     2
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK      (1 << 2)
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT     1
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK      (1 << 1)
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT       0
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK                (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_3 */
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT            30
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK             (1 << 30)
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT            29
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK             (1 << 29)
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT            28
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK             (1 << 28)
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT           27
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK            (1 << 27)
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT           26
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK            (1 << 26)
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT            25
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 25)
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT              19
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 19)
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT              18
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 18)
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT              17
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 17)
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT               16
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK                        (1 << 16)
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT              15
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK               (1 << 15)
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT              14
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK               (1 << 14)
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT         9
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK          (1 << 9)
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT         8
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK          (1 << 8)
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT              7
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK               (1 << 7)
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT                6
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK         (1 << 6)
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT         5
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK          (1 << 5)
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT       4
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 4)
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT       3
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 3)
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT                2
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK         (1 << 2)
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT         1
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK          (1 << 1)
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT         0
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK          (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_4 */
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT            30
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK             (1 << 30)
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT     29
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK      (1 << 29)
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT       28
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 28)
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT    27
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK     (1 << 27)
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT    26
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK     (1 << 26)
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT    25
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK     (1 << 25)
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT    24
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK     (1 << 24)
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT    23
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK     (1 << 23)
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT    22
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK     (1 << 22)
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT    21
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK     (1 << 21)
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT    20
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK     (1 << 20)
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT     19
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK      (1 << 19)
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT     18
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK      (1 << 18)
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT     17
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK      (1 << 17)
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT     16
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK      (1 << 16)
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT              15
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK               (1 << 15)
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT              14
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK               (1 << 14)
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT            13
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK             (1 << 13)
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT           12
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK            (1 << 12)
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT           11
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK            (1 << 11)
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT            10
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 10)
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT           9
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK            (1 << 9)
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT           8
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK            (1 << 8)
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT           7
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK            (1 << 7)
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT           6
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK            (1 << 6)
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT            4
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 4)
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT         3
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK          (1 << 3)
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT         2
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK          (1 << 2)
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT          1
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK           (1 << 1)
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT                0
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK         (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_5 */
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT             31
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK              (1 << 31)
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT             30
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK              (1 << 30)
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT              29
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK               (1 << 29)
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT              28
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK               (1 << 28)
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT              27
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK               (1 << 27)
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT              26
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK               (1 << 26)
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT              25
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK               (1 << 25)
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT             19
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK              (1 << 19)
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT             16
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK              (1 << 16)
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT             15
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK              (1 << 15)
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT             14
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK              (1 << 14)
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT            9
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK             (1 << 9)
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT            8
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK             (1 << 8)
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT            7
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK             (1 << 7)
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT            6
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK             (1 << 6)
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT            4
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK             (1 << 4)
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT            3
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK             (1 << 3)
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT            2
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK             (1 << 2)
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT            1
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK             (1 << 1)
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT            0
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK             (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_6 */
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT             7
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK              (1 << 7)
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT             6
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK              (1 << 6)
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT             5
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK              (1 << 5)
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT             4
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK              (1 << 4)
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT             3
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK              (1 << 3)
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT             2
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK              (1 << 2)
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT             1
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK              (1 << 1)
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT             0
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK              (1 << 0)
+
+/* CONTROL_PADCONF_GLOBAL */
+#define OMAP4_FORCE_OFFMODE_EN_SHIFT                           31
+#define OMAP4_FORCE_OFFMODE_EN_MASK                            (1 << 31)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_BANK0_SHIFT                              31
+#define OMAP4_VDDS_DV_BANK0_MASK                               (1 << 31)
+#define OMAP4_VDDS_DV_BANK1_SHIFT                              30
+#define OMAP4_VDDS_DV_BANK1_MASK                               (1 << 30)
+#define OMAP4_VDDS_DV_BANK3_SHIFT                              29
+#define OMAP4_VDDS_DV_BANK3_MASK                               (1 << 29)
+#define OMAP4_VDDS_DV_BANK4_SHIFT                              28
+#define OMAP4_VDDS_DV_BANK4_MASK                               (1 << 28)
+#define OMAP4_VDDS_DV_BANK5_SHIFT                              27
+#define OMAP4_VDDS_DV_BANK5_MASK                               (1 << 27)
+#define OMAP4_VDDS_DV_BANK6_SHIFT                              26
+#define OMAP4_VDDS_DV_BANK6_MASK                               (1 << 26)
+#define OMAP4_VDDS_DV_C2C_SHIFT                                        25
+#define OMAP4_VDDS_DV_C2C_MASK                                 (1 << 25)
+#define OMAP4_VDDS_DV_CAM_SHIFT                                        24
+#define OMAP4_VDDS_DV_CAM_MASK                                 (1 << 24)
+#define OMAP4_VDDS_DV_GPMC_SHIFT                               23
+#define OMAP4_VDDS_DV_GPMC_MASK                                        (1 << 23)
+#define OMAP4_VDDS_DV_SDMMC2_SHIFT                             22
+#define OMAP4_VDDS_DV_SDMMC2_MASK                              (1 << 22)
+
+/* CONTROL_SMART1IO_PADCONF_0 */
+#define OMAP4_ABE_DR0_SC_SHIFT                                 30
+#define OMAP4_ABE_DR0_SC_MASK                                  (0x3 << 30)
+#define OMAP4_CAM_DR0_SC_SHIFT                                 28
+#define OMAP4_CAM_DR0_SC_MASK                                  (0x3 << 28)
+#define OMAP4_FREF_DR2_SC_SHIFT                                        26
+#define OMAP4_FREF_DR2_SC_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR3_SC_SHIFT                                        24
+#define OMAP4_FREF_DR3_SC_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR8_SC_SHIFT                                        22
+#define OMAP4_GPIO_DR8_SC_MASK                                 (0x3 << 22)
+#define OMAP4_GPIO_DR9_SC_SHIFT                                        20
+#define OMAP4_GPIO_DR9_SC_MASK                                 (0x3 << 20)
+#define OMAP4_GPMC_DR2_SC_SHIFT                                        18
+#define OMAP4_GPMC_DR2_SC_MASK                                 (0x3 << 18)
+#define OMAP4_GPMC_DR3_SC_SHIFT                                        16
+#define OMAP4_GPMC_DR3_SC_MASK                                 (0x3 << 16)
+#define OMAP4_GPMC_DR6_SC_SHIFT                                        14
+#define OMAP4_GPMC_DR6_SC_MASK                                 (0x3 << 14)
+#define OMAP4_HDMI_DR0_SC_SHIFT                                        12
+#define OMAP4_HDMI_DR0_SC_MASK                                 (0x3 << 12)
+#define OMAP4_MCSPI1_DR0_SC_SHIFT                              10
+#define OMAP4_MCSPI1_DR0_SC_MASK                               (0x3 << 10)
+#define OMAP4_UART1_DR0_SC_SHIFT                               8
+#define OMAP4_UART1_DR0_SC_MASK                                        (0x3 << 8)
+#define OMAP4_UART3_DR0_SC_SHIFT                               6
+#define OMAP4_UART3_DR0_SC_MASK                                        (0x3 << 6)
+#define OMAP4_UART3_DR1_SC_SHIFT                               4
+#define OMAP4_UART3_DR1_SC_MASK                                        (0x3 << 4)
+#define OMAP4_UNIPRO_DR0_SC_SHIFT                              2
+#define OMAP4_UNIPRO_DR0_SC_MASK                               (0x3 << 2)
+#define OMAP4_UNIPRO_DR1_SC_SHIFT                              0
+#define OMAP4_UNIPRO_DR1_SC_MASK                               (0x3 << 0)
+
+/* CONTROL_SMART1IO_PADCONF_1 */
+#define OMAP4_ABE_DR0_LB_SHIFT                                 30
+#define OMAP4_ABE_DR0_LB_MASK                                  (0x3 << 30)
+#define OMAP4_CAM_DR0_LB_SHIFT                                 28
+#define OMAP4_CAM_DR0_LB_MASK                                  (0x3 << 28)
+#define OMAP4_FREF_DR2_LB_SHIFT                                        26
+#define OMAP4_FREF_DR2_LB_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR3_LB_SHIFT                                        24
+#define OMAP4_FREF_DR3_LB_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR8_LB_SHIFT                                        22
+#define OMAP4_GPIO_DR8_LB_MASK                                 (0x3 << 22)
+#define OMAP4_GPIO_DR9_LB_SHIFT                                        20
+#define OMAP4_GPIO_DR9_LB_MASK                                 (0x3 << 20)
+#define OMAP4_GPMC_DR2_LB_SHIFT                                        18
+#define OMAP4_GPMC_DR2_LB_MASK                                 (0x3 << 18)
+#define OMAP4_GPMC_DR3_LB_SHIFT                                        16
+#define OMAP4_GPMC_DR3_LB_MASK                                 (0x3 << 16)
+#define OMAP4_GPMC_DR6_LB_SHIFT                                        14
+#define OMAP4_GPMC_DR6_LB_MASK                                 (0x3 << 14)
+#define OMAP4_HDMI_DR0_LB_SHIFT                                        12
+#define OMAP4_HDMI_DR0_LB_MASK                                 (0x3 << 12)
+#define OMAP4_MCSPI1_DR0_LB_SHIFT                              10
+#define OMAP4_MCSPI1_DR0_LB_MASK                               (0x3 << 10)
+#define OMAP4_UART1_DR0_LB_SHIFT                               8
+#define OMAP4_UART1_DR0_LB_MASK                                        (0x3 << 8)
+#define OMAP4_UART3_DR0_LB_SHIFT                               6
+#define OMAP4_UART3_DR0_LB_MASK                                        (0x3 << 6)
+#define OMAP4_UART3_DR1_LB_SHIFT                               4
+#define OMAP4_UART3_DR1_LB_MASK                                        (0x3 << 4)
+#define OMAP4_UNIPRO_DR0_LB_SHIFT                              2
+#define OMAP4_UNIPRO_DR0_LB_MASK                               (0x3 << 2)
+#define OMAP4_UNIPRO_DR1_LB_SHIFT                              0
+#define OMAP4_UNIPRO_DR1_LB_MASK                               (0x3 << 0)
+
+/* CONTROL_SMART2IO_PADCONF_0 */
+#define OMAP4_C2C_DR0_LB_SHIFT                                 31
+#define OMAP4_C2C_DR0_LB_MASK                                  (1 << 31)
+#define OMAP4_DPM_DR1_LB_SHIFT                                 30
+#define OMAP4_DPM_DR1_LB_MASK                                  (1 << 30)
+#define OMAP4_DPM_DR2_LB_SHIFT                                 29
+#define OMAP4_DPM_DR2_LB_MASK                                  (1 << 29)
+#define OMAP4_DPM_DR3_LB_SHIFT                                 28
+#define OMAP4_DPM_DR3_LB_MASK                                  (1 << 28)
+#define OMAP4_GPIO_DR0_LB_SHIFT                                        27
+#define OMAP4_GPIO_DR0_LB_MASK                                 (1 << 27)
+#define OMAP4_GPIO_DR1_LB_SHIFT                                        26
+#define OMAP4_GPIO_DR1_LB_MASK                                 (1 << 26)
+#define OMAP4_GPIO_DR10_LB_SHIFT                               25
+#define OMAP4_GPIO_DR10_LB_MASK                                        (1 << 25)
+#define OMAP4_GPIO_DR2_LB_SHIFT                                        24
+#define OMAP4_GPIO_DR2_LB_MASK                                 (1 << 24)
+#define OMAP4_GPMC_DR0_LB_SHIFT                                        23
+#define OMAP4_GPMC_DR0_LB_MASK                                 (1 << 23)
+#define OMAP4_GPMC_DR1_LB_SHIFT                                        22
+#define OMAP4_GPMC_DR1_LB_MASK                                 (1 << 22)
+#define OMAP4_GPMC_DR4_LB_SHIFT                                        21
+#define OMAP4_GPMC_DR4_LB_MASK                                 (1 << 21)
+#define OMAP4_GPMC_DR5_LB_SHIFT                                        20
+#define OMAP4_GPMC_DR5_LB_MASK                                 (1 << 20)
+#define OMAP4_GPMC_DR7_LB_SHIFT                                        19
+#define OMAP4_GPMC_DR7_LB_MASK                                 (1 << 19)
+#define OMAP4_HSI2_DR0_LB_SHIFT                                        18
+#define OMAP4_HSI2_DR0_LB_MASK                                 (1 << 18)
+#define OMAP4_HSI2_DR1_LB_SHIFT                                        17
+#define OMAP4_HSI2_DR1_LB_MASK                                 (1 << 17)
+#define OMAP4_HSI2_DR2_LB_SHIFT                                        16
+#define OMAP4_HSI2_DR2_LB_MASK                                 (1 << 16)
+#define OMAP4_KPD_DR0_LB_SHIFT                                 15
+#define OMAP4_KPD_DR0_LB_MASK                                  (1 << 15)
+#define OMAP4_KPD_DR1_LB_SHIFT                                 14
+#define OMAP4_KPD_DR1_LB_MASK                                  (1 << 14)
+#define OMAP4_PDM_DR0_LB_SHIFT                                 13
+#define OMAP4_PDM_DR0_LB_MASK                                  (1 << 13)
+#define OMAP4_SDMMC2_DR0_LB_SHIFT                              12
+#define OMAP4_SDMMC2_DR0_LB_MASK                               (1 << 12)
+#define OMAP4_SDMMC3_DR0_LB_SHIFT                              11
+#define OMAP4_SDMMC3_DR0_LB_MASK                               (1 << 11)
+#define OMAP4_SDMMC4_DR0_LB_SHIFT                              10
+#define OMAP4_SDMMC4_DR0_LB_MASK                               (1 << 10)
+#define OMAP4_SDMMC4_DR1_LB_SHIFT                              9
+#define OMAP4_SDMMC4_DR1_LB_MASK                               (1 << 9)
+#define OMAP4_SPI3_DR0_LB_SHIFT                                        8
+#define OMAP4_SPI3_DR0_LB_MASK                                 (1 << 8)
+#define OMAP4_SPI3_DR1_LB_SHIFT                                        7
+#define OMAP4_SPI3_DR1_LB_MASK                                 (1 << 7)
+#define OMAP4_UART3_DR2_LB_SHIFT                               6
+#define OMAP4_UART3_DR2_LB_MASK                                        (1 << 6)
+#define OMAP4_UART3_DR3_LB_SHIFT                               5
+#define OMAP4_UART3_DR3_LB_MASK                                        (1 << 5)
+#define OMAP4_UART3_DR4_LB_SHIFT                               4
+#define OMAP4_UART3_DR4_LB_MASK                                        (1 << 4)
+#define OMAP4_UART3_DR5_LB_SHIFT                               3
+#define OMAP4_UART3_DR5_LB_MASK                                        (1 << 3)
+#define OMAP4_USBA0_DR1_LB_SHIFT                               2
+#define OMAP4_USBA0_DR1_LB_MASK                                        (1 << 2)
+#define OMAP4_USBA_DR2_LB_SHIFT                                        1
+#define OMAP4_USBA_DR2_LB_MASK                                 (1 << 1)
+
+/* CONTROL_SMART2IO_PADCONF_1 */
+#define OMAP4_USBB1_DR0_LB_SHIFT                               31
+#define OMAP4_USBB1_DR0_LB_MASK                                        (1 << 31)
+#define OMAP4_USBB2_DR0_LB_SHIFT                               30
+#define OMAP4_USBB2_DR0_LB_MASK                                        (1 << 30)
+#define OMAP4_USBA0_DR0_LB_SHIFT                               29
+#define OMAP4_USBA0_DR0_LB_MASK                                        (1 << 29)
+
+/* CONTROL_SMART3IO_PADCONF_0 */
+#define OMAP4_DMIC_DR0_MB_SHIFT                                        30
+#define OMAP4_DMIC_DR0_MB_MASK                                 (0x3 << 30)
+#define OMAP4_GPIO_DR3_MB_SHIFT                                        28
+#define OMAP4_GPIO_DR3_MB_MASK                                 (0x3 << 28)
+#define OMAP4_GPIO_DR4_MB_SHIFT                                        26
+#define OMAP4_GPIO_DR4_MB_MASK                                 (0x3 << 26)
+#define OMAP4_GPIO_DR5_MB_SHIFT                                        24
+#define OMAP4_GPIO_DR5_MB_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR6_MB_SHIFT                                        22
+#define OMAP4_GPIO_DR6_MB_MASK                                 (0x3 << 22)
+#define OMAP4_HSI_DR1_MB_SHIFT                                 20
+#define OMAP4_HSI_DR1_MB_MASK                                  (0x3 << 20)
+#define OMAP4_HSI_DR2_MB_SHIFT                                 18
+#define OMAP4_HSI_DR2_MB_MASK                                  (0x3 << 18)
+#define OMAP4_HSI_DR3_MB_SHIFT                                 16
+#define OMAP4_HSI_DR3_MB_MASK                                  (0x3 << 16)
+#define OMAP4_MCBSP2_DR0_MB_SHIFT                              14
+#define OMAP4_MCBSP2_DR0_MB_MASK                               (0x3 << 14)
+#define OMAP4_MCSPI4_DR0_MB_SHIFT                              12
+#define OMAP4_MCSPI4_DR0_MB_MASK                               (0x3 << 12)
+#define OMAP4_MCSPI4_DR1_MB_SHIFT                              10
+#define OMAP4_MCSPI4_DR1_MB_MASK                               (0x3 << 10)
+#define OMAP4_SDMMC3_DR0_MB_SHIFT                              8
+#define OMAP4_SDMMC3_DR0_MB_MASK                               (0x3 << 8)
+#define OMAP4_SPI2_DR0_MB_SHIFT                                        0
+#define OMAP4_SPI2_DR0_MB_MASK                                 (0x3 << 0)
+
+/* CONTROL_SMART3IO_PADCONF_1 */
+#define OMAP4_SPI2_DR1_MB_SHIFT                                        30
+#define OMAP4_SPI2_DR1_MB_MASK                                 (0x3 << 30)
+#define OMAP4_SPI2_DR2_MB_SHIFT                                        28
+#define OMAP4_SPI2_DR2_MB_MASK                                 (0x3 << 28)
+#define OMAP4_UART2_DR0_MB_SHIFT                               26
+#define OMAP4_UART2_DR0_MB_MASK                                        (0x3 << 26)
+#define OMAP4_UART2_DR1_MB_SHIFT                               24
+#define OMAP4_UART2_DR1_MB_MASK                                        (0x3 << 24)
+#define OMAP4_UART4_DR0_MB_SHIFT                               22
+#define OMAP4_UART4_DR0_MB_MASK                                        (0x3 << 22)
+#define OMAP4_HSI_DR0_MB_SHIFT                                 20
+#define OMAP4_HSI_DR0_MB_MASK                                  (0x3 << 20)
+
+/* CONTROL_SMART3IO_PADCONF_2 */
+#define OMAP4_DMIC_DR0_LB_SHIFT                                        31
+#define OMAP4_DMIC_DR0_LB_MASK                                 (1 << 31)
+#define OMAP4_GPIO_DR3_LB_SHIFT                                        30
+#define OMAP4_GPIO_DR3_LB_MASK                                 (1 << 30)
+#define OMAP4_GPIO_DR4_LB_SHIFT                                        29
+#define OMAP4_GPIO_DR4_LB_MASK                                 (1 << 29)
+#define OMAP4_GPIO_DR5_LB_SHIFT                                        28
+#define OMAP4_GPIO_DR5_LB_MASK                                 (1 << 28)
+#define OMAP4_GPIO_DR6_LB_SHIFT                                        27
+#define OMAP4_GPIO_DR6_LB_MASK                                 (1 << 27)
+#define OMAP4_HSI_DR1_LB_SHIFT                                 26
+#define OMAP4_HSI_DR1_LB_MASK                                  (1 << 26)
+#define OMAP4_HSI_DR2_LB_SHIFT                                 25
+#define OMAP4_HSI_DR2_LB_MASK                                  (1 << 25)
+#define OMAP4_HSI_DR3_LB_SHIFT                                 24
+#define OMAP4_HSI_DR3_LB_MASK                                  (1 << 24)
+#define OMAP4_MCBSP2_DR0_LB_SHIFT                              23
+#define OMAP4_MCBSP2_DR0_LB_MASK                               (1 << 23)
+#define OMAP4_MCSPI4_DR0_LB_SHIFT                              22
+#define OMAP4_MCSPI4_DR0_LB_MASK                               (1 << 22)
+#define OMAP4_MCSPI4_DR1_LB_SHIFT                              21
+#define OMAP4_MCSPI4_DR1_LB_MASK                               (1 << 21)
+#define OMAP4_SLIMBUS2_DR0_LB_SHIFT                            18
+#define OMAP4_SLIMBUS2_DR0_LB_MASK                             (1 << 18)
+#define OMAP4_SPI2_DR0_LB_SHIFT                                        16
+#define OMAP4_SPI2_DR0_LB_MASK                                 (1 << 16)
+#define OMAP4_SPI2_DR1_LB_SHIFT                                        15
+#define OMAP4_SPI2_DR1_LB_MASK                                 (1 << 15)
+#define OMAP4_SPI2_DR2_LB_SHIFT                                        14
+#define OMAP4_SPI2_DR2_LB_MASK                                 (1 << 14)
+#define OMAP4_UART2_DR0_LB_SHIFT                               13
+#define OMAP4_UART2_DR0_LB_MASK                                        (1 << 13)
+#define OMAP4_UART2_DR1_LB_SHIFT                               12
+#define OMAP4_UART2_DR1_LB_MASK                                        (1 << 12)
+#define OMAP4_UART4_DR0_LB_SHIFT                               11
+#define OMAP4_UART4_DR0_LB_MASK                                        (1 << 11)
+#define OMAP4_HSI_DR0_LB_SHIFT                                 10
+#define OMAP4_HSI_DR0_LB_MASK                                  (1 << 10)
+
+/* CONTROL_USBB_HSIC */
+#define OMAP4_USBB2_DR1_SR_SHIFT                               30
+#define OMAP4_USBB2_DR1_SR_MASK                                        (0x3 << 30)
+#define OMAP4_USBB2_DR1_I_SHIFT                                        27
+#define OMAP4_USBB2_DR1_I_MASK                                 (0x7 << 27)
+#define OMAP4_USBB1_DR1_SR_SHIFT                               25
+#define OMAP4_USBB1_DR1_SR_MASK                                        (0x3 << 25)
+#define OMAP4_USBB1_DR1_I_SHIFT                                        22
+#define OMAP4_USBB1_DR1_I_MASK                                 (0x7 << 22)
+#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT                         20
+#define OMAP4_USBB1_HSIC_DATA_WD_MASK                          (0x3 << 20)
+#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT                       18
+#define OMAP4_USBB1_HSIC_STROBE_WD_MASK                                (0x3 << 18)
+#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT                         16
+#define OMAP4_USBB2_HSIC_DATA_WD_MASK                          (0x3 << 16)
+#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT                       14
+#define OMAP4_USBB2_HSIC_STROBE_WD_MASK                                (0x3 << 14)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT          13
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK           (1 << 13)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT                 11
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK                  (0x3 << 11)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT                10
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK         (1 << 10)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT               8
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK                        (0x3 << 8)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT          7
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK           (1 << 7)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT                 5
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK                  (0x3 << 5)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT                4
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK         (1 << 4)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT               2
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK                        (0x3 << 2)
+
+/* CONTROL_SLIMBUS */
+#define OMAP4_SLIMBUS1_DR0_MB_SHIFT                            30
+#define OMAP4_SLIMBUS1_DR0_MB_MASK                             (0x3 << 30)
+#define OMAP4_SLIMBUS1_DR1_MB_SHIFT                            28
+#define OMAP4_SLIMBUS1_DR1_MB_MASK                             (0x3 << 28)
+#define OMAP4_SLIMBUS2_DR0_MB_SHIFT                            26
+#define OMAP4_SLIMBUS2_DR0_MB_MASK                             (0x3 << 26)
+#define OMAP4_SLIMBUS2_DR1_MB_SHIFT                            24
+#define OMAP4_SLIMBUS2_DR1_MB_MASK                             (0x3 << 24)
+#define OMAP4_SLIMBUS2_DR2_MB_SHIFT                            22
+#define OMAP4_SLIMBUS2_DR2_MB_MASK                             (0x3 << 22)
+#define OMAP4_SLIMBUS2_DR3_MB_SHIFT                            20
+#define OMAP4_SLIMBUS2_DR3_MB_MASK                             (0x3 << 20)
+#define OMAP4_SLIMBUS1_DR0_LB_SHIFT                            19
+#define OMAP4_SLIMBUS1_DR0_LB_MASK                             (1 << 19)
+#define OMAP4_SLIMBUS2_DR1_LB_SHIFT                            18
+#define OMAP4_SLIMBUS2_DR1_LB_MASK                             (1 << 18)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT                    31
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK                     (1 << 31)
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT               30
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK                        (1 << 30)
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT                 29
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK                  (1 << 29)
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT                      28
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK                       (1 << 28)
+#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT                       27
+#define OMAP4_USIM_PBIASLITE_VMODE_MASK                                (1 << 27)
+#define OMAP4_MMC1_PWRDNZ_SHIFT                                        26
+#define OMAP4_MMC1_PWRDNZ_MASK                                 (1 << 26)
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT                    25
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK                     (1 << 25)
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT               24
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK                        (1 << 24)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT                 23
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK                  (1 << 23)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT                      22
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK                       (1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT                       21
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK                                (1 << 21)
+#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT                         20
+#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK                          (1 << 20)
+
+/* CONTROL_I2C_0 */
+#define OMAP4_I2C4_SDA_GLFENB_SHIFT                            31
+#define OMAP4_I2C4_SDA_GLFENB_MASK                             (1 << 31)
+#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT                         29
+#define OMAP4_I2C4_SDA_LOAD_BITS_MASK                          (0x3 << 29)
+#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT                                28
+#define OMAP4_I2C4_SDA_PULLUPRESX_MASK                         (1 << 28)
+#define OMAP4_I2C3_SDA_GLFENB_SHIFT                            27
+#define OMAP4_I2C3_SDA_GLFENB_MASK                             (1 << 27)
+#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT                         25
+#define OMAP4_I2C3_SDA_LOAD_BITS_MASK                          (0x3 << 25)
+#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT                                24
+#define OMAP4_I2C3_SDA_PULLUPRESX_MASK                         (1 << 24)
+#define OMAP4_I2C2_SDA_GLFENB_SHIFT                            23
+#define OMAP4_I2C2_SDA_GLFENB_MASK                             (1 << 23)
+#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT                         21
+#define OMAP4_I2C2_SDA_LOAD_BITS_MASK                          (0x3 << 21)
+#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT                                20
+#define OMAP4_I2C2_SDA_PULLUPRESX_MASK                         (1 << 20)
+#define OMAP4_I2C1_SDA_GLFENB_SHIFT                            19
+#define OMAP4_I2C1_SDA_GLFENB_MASK                             (1 << 19)
+#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT                         17
+#define OMAP4_I2C1_SDA_LOAD_BITS_MASK                          (0x3 << 17)
+#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT                                16
+#define OMAP4_I2C1_SDA_PULLUPRESX_MASK                         (1 << 16)
+#define OMAP4_I2C4_SCL_GLFENB_SHIFT                            15
+#define OMAP4_I2C4_SCL_GLFENB_MASK                             (1 << 15)
+#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT                         13
+#define OMAP4_I2C4_SCL_LOAD_BITS_MASK                          (0x3 << 13)
+#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT                                12
+#define OMAP4_I2C4_SCL_PULLUPRESX_MASK                         (1 << 12)
+#define OMAP4_I2C3_SCL_GLFENB_SHIFT                            11
+#define OMAP4_I2C3_SCL_GLFENB_MASK                             (1 << 11)
+#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT                         9
+#define OMAP4_I2C3_SCL_LOAD_BITS_MASK                          (0x3 << 9)
+#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT                                8
+#define OMAP4_I2C3_SCL_PULLUPRESX_MASK                         (1 << 8)
+#define OMAP4_I2C2_SCL_GLFENB_SHIFT                            7
+#define OMAP4_I2C2_SCL_GLFENB_MASK                             (1 << 7)
+#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT                         5
+#define OMAP4_I2C2_SCL_LOAD_BITS_MASK                          (0x3 << 5)
+#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT                                4
+#define OMAP4_I2C2_SCL_PULLUPRESX_MASK                         (1 << 4)
+#define OMAP4_I2C1_SCL_GLFENB_SHIFT                            3
+#define OMAP4_I2C1_SCL_GLFENB_MASK                             (1 << 3)
+#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT                         1
+#define OMAP4_I2C1_SCL_LOAD_BITS_MASK                          (0x3 << 1)
+#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT                                0
+#define OMAP4_I2C1_SCL_PULLUPRESX_MASK                         (1 << 0)
+
+/* CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT                  31
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK                   (1 << 31)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT                  29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK                   (0x3 << 29)
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT                  24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK                   (0x1f << 24)
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT                    22
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK                     (0x3 << 22)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT                   21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK                    (1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT                     19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK                      (0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT                   18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK                    (1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT                     16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK                      (0x3 << 16)
+
+/* CONTROL_AVDAC */
+#define OMAP4_AVDAC_ACEN_SHIFT                                 31
+#define OMAP4_AVDAC_ACEN_MASK                                  (1 << 31)
+#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT                          30
+#define OMAP4_AVDAC_TVOUTBYPASS_MASK                           (1 << 30)
+#define OMAP4_AVDAC_INPUTINV_SHIFT                             29
+#define OMAP4_AVDAC_INPUTINV_MASK                              (1 << 29)
+#define OMAP4_AVDAC_CTL_SHIFT                                  13
+#define OMAP4_AVDAC_CTL_MASK                                   (0xffff << 13)
+#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT                           12
+#define OMAP4_AVDAC_CTL_WR_ACK_MASK                            (1 << 12)
+
+/* CONTROL_HDMI_TX_PHY */
+#define OMAP4_HDMITXPHY_PADORDER_SHIFT                         31
+#define OMAP4_HDMITXPHY_PADORDER_MASK                          (1 << 31)
+#define OMAP4_HDMITXPHY_TXVALID_SHIFT                          30
+#define OMAP4_HDMITXPHY_TXVALID_MASK                           (1 << 30)
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT                      29
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK                       (1 << 29)
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT                     28
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK                      (1 << 28)
+
+/* CONTROL_MMC2 */
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT                      31
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK                       (1 << 31)
+
+/* CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT                            29
+#define OMAP4_DSI2_LANEENABLE_MASK                             (0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT                            24
+#define OMAP4_DSI1_LANEENABLE_MASK                             (0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT                                  19
+#define OMAP4_DSI1_PIPD_MASK                                   (0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT                                  14
+#define OMAP4_DSI2_PIPD_MASK                                   (0x1f << 14)
+
+/* CONTROL_MCBSPLP */
+#define OMAP4_ALBCTRLRX_FSX_SHIFT                              31
+#define OMAP4_ALBCTRLRX_FSX_MASK                               (1 << 31)
+#define OMAP4_ALBCTRLRX_CLKX_SHIFT                             30
+#define OMAP4_ALBCTRLRX_CLKX_MASK                              (1 << 30)
+#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT                           29
+#define OMAP4_ABE_MCBSP1_DR_EN_MASK                            (1 << 29)
+
+/* CONTROL_USB2PHYCORE */
+#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT                      31
+#define OMAP4_USB2PHY_AUTORESUME_EN_MASK                       (1 << 31)
+#define OMAP4_USB2PHY_DISCHGDET_SHIFT                          30
+#define OMAP4_USB2PHY_DISCHGDET_MASK                           (1 << 30)
+#define OMAP4_USB2PHY_GPIOMODE_SHIFT                           29
+#define OMAP4_USB2PHY_GPIOMODE_MASK                            (1 << 29)
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT                    28
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK                     (1 << 28)
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT                   27
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK                    (1 << 27)
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT                   26
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK                    (1 << 26)
+#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT                                25
+#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK                         (1 << 25)
+#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT                       24
+#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK                                (1 << 24)
+#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT                     21
+#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK                      (0x7 << 21)
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT                    20
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK                     (1 << 20)
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT                    19
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK                     (1 << 19)
+#define OMAP4_USB2PHY_DATADET_SHIFT                            18
+#define OMAP4_USB2PHY_DATADET_MASK                             (1 << 18)
+#define OMAP4_USB2PHY_SINKONDP_SHIFT                           17
+#define OMAP4_USB2PHY_SINKONDP_MASK                            (1 << 17)
+#define OMAP4_USB2PHY_SRCONDM_SHIFT                            16
+#define OMAP4_USB2PHY_SRCONDM_MASK                             (1 << 16)
+#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT                      15
+#define OMAP4_USB2PHY_RESTARTCHGDET_MASK                       (1 << 15)
+#define OMAP4_USB2PHY_CHGDETDONE_SHIFT                         14
+#define OMAP4_USB2PHY_CHGDETDONE_MASK                          (1 << 14)
+#define OMAP4_USB2PHY_CHGDETECTED_SHIFT                                13
+#define OMAP4_USB2PHY_CHGDETECTED_MASK                         (1 << 13)
+#define OMAP4_USB2PHY_MCPCPUEN_SHIFT                           12
+#define OMAP4_USB2PHY_MCPCPUEN_MASK                            (1 << 12)
+#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT                         11
+#define OMAP4_USB2PHY_MCPCMODEEN_MASK                          (1 << 11)
+#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT                      10
+#define OMAP4_USB2PHY_RESETDONEMCLK_MASK                       (1 << 10)
+#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT                      9
+#define OMAP4_USB2PHY_UTMIRESETDONE_MASK                       (1 << 9)
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT                   8
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK                    (1 << 8)
+#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT                      7
+#define OMAP4_USB2PHY_DATAPOLARITYN_MASK                       (1 << 7)
+#define OMAP4_USBDPLL_FREQLOCK_SHIFT                           6
+#define OMAP4_USBDPLL_FREQLOCK_MASK                            (1 << 6)
+#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT                      5
+#define OMAP4_USB2PHY_RESETDONETCLK_MASK                       (1 << 5)
+
+/* CONTROL_I2C_1 */
+#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT                                31
+#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK                         (1 << 31)
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT                     29
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK                      (0x3 << 29)
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT                    28
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK                     (1 << 28)
+#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT                                27
+#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK                         (1 << 27)
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT                     25
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK                      (0x3 << 25)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT                    24
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK                     (1 << 24)
+#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT                                23
+#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK                         (1 << 23)
+#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT                         22
+#define OMAP4_HDMI_DDC_SDA_NMODE_MASK                          (1 << 22)
+#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT                                21
+#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK                         (1 << 21)
+#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT                         20
+#define OMAP4_HDMI_DDC_SCL_NMODE_MASK                          (1 << 20)
+
+/* CONTROL_MMC1 */
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT                     31
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK                      (1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT                     30
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK                      (1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT                     29
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK                      (1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT                     28
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK                      (1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT                       27
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK                                (1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT                       26
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK                                (1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT                       25
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK                                (1 << 25)
+#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT                                24
+#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK                         (1 << 24)
+#define OMAP4_USB_FD_CDEN_SHIFT                                        23
+#define OMAP4_USB_FD_CDEN_MASK                                 (1 << 23)
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT                       22
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK                                (1 << 22)
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT                       21
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK                                (1 << 21)
+
+/* CONTROL_HSI */
+#define OMAP4_HSI1_CALLOOP_SEL_SHIFT                           31
+#define OMAP4_HSI1_CALLOOP_SEL_MASK                            (1 << 31)
+#define OMAP4_HSI1_CALMUX_SEL_SHIFT                            30
+#define OMAP4_HSI1_CALMUX_SEL_MASK                             (1 << 30)
+#define OMAP4_HSI2_CALLOOP_SEL_SHIFT                           29
+#define OMAP4_HSI2_CALLOOP_SEL_MASK                            (1 << 29)
+#define OMAP4_HSI2_CALMUX_SEL_SHIFT                            28
+#define OMAP4_HSI2_CALMUX_SEL_MASK                             (1 << 28)
+
+/* CONTROL_USB */
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT          31
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK           (1 << 31)
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT          30
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK           (1 << 30)
+
+/* CONTROL_HDQ */
+#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT                             31
+#define OMAP4_HDQ_SIO_PWRDNZ_MASK                              (1 << 31)
+
+/* CONTROL_LPDDR2IO1_0 */
+#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO1_GR4_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR4_I_SHIFT                            27
+#define OMAP4_LPDDR2IO1_GR4_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO1_GR4_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO1_GR3_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR3_I_SHIFT                            19
+#define OMAP4_LPDDR2IO1_GR3_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO1_GR3_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR2_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR2_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR2_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR2_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO1_GR1_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR1_I_SHIFT                            3
+#define OMAP4_LPDDR2IO1_GR1_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO1_GR1_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_1 */
+#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO1_GR8_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR8_I_SHIFT                            27
+#define OMAP4_LPDDR2IO1_GR8_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO1_GR8_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO1_GR7_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR7_I_SHIFT                            19
+#define OMAP4_LPDDR2IO1_GR7_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO1_GR7_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR6_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR6_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR6_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR6_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO1_GR5_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR5_I_SHIFT                            3
+#define OMAP4_LPDDR2IO1_GR5_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO1_GR5_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_2 */
+#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT                          30
+#define OMAP4_LPDDR2IO1_GR11_SR_MASK                           (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR11_I_SHIFT                           27
+#define OMAP4_LPDDR2IO1_GR11_I_MASK                            (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT                          25
+#define OMAP4_LPDDR2IO1_GR11_WD_MASK                           (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT                          22
+#define OMAP4_LPDDR2IO1_GR10_SR_MASK                           (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR10_I_SHIFT                           19
+#define OMAP4_LPDDR2IO1_GR10_I_MASK                            (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT                          17
+#define OMAP4_LPDDR2IO1_GR10_WD_MASK                           (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR9_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR9_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR9_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR9_WD_MASK                            (0x3 << 9)
+
+/* CONTROL_LPDDR2IO1_3 */
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT                      31
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK                       (1 << 31)
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT                      30
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK                       (1 << 30)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT                  29
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK                   (1 << 29)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT                  28
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK                   (1 << 28)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT                   27
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK                    (1 << 27)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT                   26
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK                    (1 << 26)
+#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT                       25
+#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK                                (1 << 25)
+#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT                       24
+#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK                                (1 << 24)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT                 23
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK                  (1 << 23)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT                 22
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK                  (1 << 22)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT                  21
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK                   (1 << 21)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT                  20
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK                   (1 << 20)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT                 19
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK                  (1 << 19)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT                 18
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK                  (1 << 18)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT                  17
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK                   (1 << 17)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT                  16
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK                   (1 << 16)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT                      15
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK                       (1 << 15)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT                      14
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK                       (1 << 14)
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT                       13
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK                                (1 << 13)
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT                       12
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK                                (1 << 12)
+
+/* CONTROL_LPDDR2IO2_0 */
+#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO2_GR4_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR4_I_SHIFT                            27
+#define OMAP4_LPDDR2IO2_GR4_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO2_GR4_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO2_GR3_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR3_I_SHIFT                            19
+#define OMAP4_LPDDR2IO2_GR3_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO2_GR3_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR2_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR2_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR2_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR2_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO2_GR1_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR1_I_SHIFT                            3
+#define OMAP4_LPDDR2IO2_GR1_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO2_GR1_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_1 */
+#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO2_GR8_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR8_I_SHIFT                            27
+#define OMAP4_LPDDR2IO2_GR8_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO2_GR8_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO2_GR7_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR7_I_SHIFT                            19
+#define OMAP4_LPDDR2IO2_GR7_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO2_GR7_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR6_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR6_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR6_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR6_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO2_GR5_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR5_I_SHIFT                            3
+#define OMAP4_LPDDR2IO2_GR5_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO2_GR5_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_2 */
+#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT                          30
+#define OMAP4_LPDDR2IO2_GR11_SR_MASK                           (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR11_I_SHIFT                           27
+#define OMAP4_LPDDR2IO2_GR11_I_MASK                            (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT                          25
+#define OMAP4_LPDDR2IO2_GR11_WD_MASK                           (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT                          22
+#define OMAP4_LPDDR2IO2_GR10_SR_MASK                           (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR10_I_SHIFT                           19
+#define OMAP4_LPDDR2IO2_GR10_I_MASK                            (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT                          17
+#define OMAP4_LPDDR2IO2_GR10_WD_MASK                           (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR9_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR9_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR9_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR9_WD_MASK                            (0x3 << 9)
+
+/* CONTROL_LPDDR2IO2_3 */
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT                      31
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK                       (1 << 31)
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT                      30
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK                       (1 << 30)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT                  29
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK                   (1 << 29)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT                  28
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK                   (1 << 28)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT                   27
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK                    (1 << 27)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT                   26
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK                    (1 << 26)
+#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT                       25
+#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK                                (1 << 25)
+#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT                       24
+#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK                                (1 << 24)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT                 23
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK                  (1 << 23)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT                 22
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK                  (1 << 22)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT                  21
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK                   (1 << 21)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT                  20
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK                   (1 << 20)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT                 19
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK                  (1 << 19)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT                 18
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK                  (1 << 18)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT                  17
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK                   (1 << 17)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT                  16
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK                   (1 << 16)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT                      15
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK                       (1 << 15)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT                      14
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK                       (1 << 14)
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT                       13
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK                                (1 << 13)
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT                       12
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK                                (1 << 12)
+
+/* CONTROL_BUS_HOLD */
+#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT                           31
+#define OMAP4_ABE_DMIC_DIN3_EN_MASK                            (1 << 31)
+#define OMAP4_MCSPI1_CS3_EN_SHIFT                              30
+#define OMAP4_MCSPI1_CS3_EN_MASK                               (1 << 30)
+
+/* CONTROL_C2C */
+#define OMAP4_MIRROR_MODE_EN_SHIFT                             31
+#define OMAP4_MIRROR_MODE_EN_MASK                              (1 << 31)
+#define OMAP4_C2C_SPARE_SHIFT                                  24
+#define OMAP4_C2C_SPARE_MASK                                   (0x7f << 24)
+
+/* CORE_CONTROL_SPARE_RW */
+#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT                      0
+#define OMAP4_CORE_CONTROL_SPARE_RW_MASK                       (0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R */
+#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT                       0
+#define OMAP4_CORE_CONTROL_SPARE_R_MASK                                (0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R_C0 */
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT                    31
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK                     (1 << 31)
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT                    30
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK                     (1 << 30)
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT                    29
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK                     (1 << 29)
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT                    28
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK                     (1 << 28)
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT                    27
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK                     (1 << 27)
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT                    26
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK                     (1 << 26)
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT                    25
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK                     (1 << 25)
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT                    24
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK                     (1 << 24)
+
+/* CONTROL_EFUSE_1 */
+#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT                           24
+#define OMAP4_AVDAC_TRIM_BYTE3_MASK                            (0x7f << 24)
+#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT                           16
+#define OMAP4_AVDAC_TRIM_BYTE2_MASK                            (0xff << 16)
+#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT                           8
+#define OMAP4_AVDAC_TRIM_BYTE1_MASK                            (0xff << 8)
+#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT                           0
+#define OMAP4_AVDAC_TRIM_BYTE0_MASK                            (0xff << 0)
+
+/* CONTROL_EFUSE_2 */
+#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT                                31
+#define OMAP4_EFUSE_SMART2TEST_P0_MASK                         (1 << 31)
+#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT                                30
+#define OMAP4_EFUSE_SMART2TEST_P1_MASK                         (1 << 30)
+#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT                                29
+#define OMAP4_EFUSE_SMART2TEST_P2_MASK                         (1 << 29)
+#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT                                28
+#define OMAP4_EFUSE_SMART2TEST_P3_MASK                         (1 << 28)
+#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT                                27
+#define OMAP4_EFUSE_SMART2TEST_N0_MASK                         (1 << 27)
+#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT                                26
+#define OMAP4_EFUSE_SMART2TEST_N1_MASK                         (1 << 26)
+#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT                                25
+#define OMAP4_EFUSE_SMART2TEST_N2_MASK                         (1 << 25)
+#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT                                24
+#define OMAP4_EFUSE_SMART2TEST_N3_MASK                         (1 << 24)
+#define OMAP4_LPDDR2_PTV_N1_SHIFT                              23
+#define OMAP4_LPDDR2_PTV_N1_MASK                               (1 << 23)
+#define OMAP4_LPDDR2_PTV_N2_SHIFT                              22
+#define OMAP4_LPDDR2_PTV_N2_MASK                               (1 << 22)
+#define OMAP4_LPDDR2_PTV_N3_SHIFT                              21
+#define OMAP4_LPDDR2_PTV_N3_MASK                               (1 << 21)
+#define OMAP4_LPDDR2_PTV_N4_SHIFT                              20
+#define OMAP4_LPDDR2_PTV_N4_MASK                               (1 << 20)
+#define OMAP4_LPDDR2_PTV_N5_SHIFT                              19
+#define OMAP4_LPDDR2_PTV_N5_MASK                               (1 << 19)
+#define OMAP4_LPDDR2_PTV_P1_SHIFT                              18
+#define OMAP4_LPDDR2_PTV_P1_MASK                               (1 << 18)
+#define OMAP4_LPDDR2_PTV_P2_SHIFT                              17
+#define OMAP4_LPDDR2_PTV_P2_MASK                               (1 << 17)
+#define OMAP4_LPDDR2_PTV_P3_SHIFT                              16
+#define OMAP4_LPDDR2_PTV_P3_MASK                               (1 << 16)
+#define OMAP4_LPDDR2_PTV_P4_SHIFT                              15
+#define OMAP4_LPDDR2_PTV_P4_MASK                               (1 << 15)
+#define OMAP4_LPDDR2_PTV_P5_SHIFT                              14
+#define OMAP4_LPDDR2_PTV_P5_MASK                               (1 << 14)
+
+/* CONTROL_EFUSE_3 */
+#define OMAP4_STD_FUSE_SPARE_1_SHIFT                           24
+#define OMAP4_STD_FUSE_SPARE_1_MASK                            (0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_2_SHIFT                           16
+#define OMAP4_STD_FUSE_SPARE_2_MASK                            (0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_3_SHIFT                           8
+#define OMAP4_STD_FUSE_SPARE_3_MASK                            (0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_4_SHIFT                           0
+#define OMAP4_STD_FUSE_SPARE_4_MASK                            (0xff << 0)
+
+/* CONTROL_EFUSE_4 */
+#define OMAP4_STD_FUSE_SPARE_5_SHIFT                           24
+#define OMAP4_STD_FUSE_SPARE_5_MASK                            (0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_6_SHIFT                           16
+#define OMAP4_STD_FUSE_SPARE_6_MASK                            (0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_7_SHIFT                           8
+#define OMAP4_STD_FUSE_SPARE_7_MASK                            (0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_8_SHIFT                           0
+#define OMAP4_STD_FUSE_SPARE_8_MASK                            (0xff << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
new file mode 100644 (file)
index 0000000..17c9b37
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_WKUP                                     0x4a31e000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION                         0x0000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO                           0x0004
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG                                0x0010
+#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0               0x007c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0      0x05a0
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1      0x05a4
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE                        0x05a8
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR             0x05ac
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO                      0x0600
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2                       0x0604
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG                                0x0608
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS                         0x060c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW               0x0614
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R                        0x0618
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0             0x061c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                              30
+#define OMAP4_IP_REV_SCHEME_MASK                               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                        16
+#define OMAP4_IP_REV_FUNC_MASK                                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                                 11
+#define OMAP4_IP_REV_RTL_MASK                                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                               8
+#define OMAP4_IP_REV_MAJOR_MASK                                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                              6
+#define OMAP4_IP_REV_CUSTOM_MASK                               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                               0
+#define OMAP4_IP_REV_MINOR_MASK                                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                                  0
+#define OMAP4_IP_HWINFO_MASK                                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT                      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK                       (0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT         22
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK          (1 << 22)
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT             21
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK              (1 << 21)
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT            19
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK             (1 << 19)
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT   16
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK    (1 << 16)
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT           15
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK            (1 << 15)
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT          14
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK           (1 << 14)
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT               13
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK                        (1 << 13)
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT         12
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 12)
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT         9
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK          (1 << 9)
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT         8
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 8)
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT                7
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK         (1 << 7)
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT                        6
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK                 (1 << 6)
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT                        5
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK                 (1 << 5)
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT           4
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK            (1 << 4)
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT                        3
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK                 (1 << 3)
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT             2
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK              (1 << 2)
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT               1
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK                        (1 << 1)
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT                        0
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK                 (1 << 0)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_0 */
+#define OMAP4_FREF_DR0_SC_SHIFT                                        30
+#define OMAP4_FREF_DR0_SC_MASK                                 (0x3 << 30)
+#define OMAP4_FREF_DR1_SC_SHIFT                                        28
+#define OMAP4_FREF_DR1_SC_MASK                                 (0x3 << 28)
+#define OMAP4_FREF_DR4_SC_SHIFT                                        26
+#define OMAP4_FREF_DR4_SC_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR5_SC_SHIFT                                        24
+#define OMAP4_FREF_DR5_SC_MASK                                 (0x3 << 24)
+#define OMAP4_FREF_DR6_SC_SHIFT                                        22
+#define OMAP4_FREF_DR6_SC_MASK                                 (0x3 << 22)
+#define OMAP4_FREF_DR7_SC_SHIFT                                        20
+#define OMAP4_FREF_DR7_SC_MASK                                 (0x3 << 20)
+#define OMAP4_GPIO_DR7_SC_SHIFT                                        18
+#define OMAP4_GPIO_DR7_SC_MASK                                 (0x3 << 18)
+#define OMAP4_DPM_DR0_SC_SHIFT                                 14
+#define OMAP4_DPM_DR0_SC_MASK                                  (0x3 << 14)
+#define OMAP4_SIM_DR0_SC_SHIFT                                 12
+#define OMAP4_SIM_DR0_SC_MASK                                  (0x3 << 12)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_1 */
+#define OMAP4_FREF_DR0_LB_SHIFT                                        30
+#define OMAP4_FREF_DR0_LB_MASK                                 (0x3 << 30)
+#define OMAP4_FREF_DR1_LB_SHIFT                                        28
+#define OMAP4_FREF_DR1_LB_MASK                                 (0x3 << 28)
+#define OMAP4_FREF_DR4_LB_SHIFT                                        26
+#define OMAP4_FREF_DR4_LB_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR5_LB_SHIFT                                        24
+#define OMAP4_FREF_DR5_LB_MASK                                 (0x3 << 24)
+#define OMAP4_FREF_DR6_LB_SHIFT                                        22
+#define OMAP4_FREF_DR6_LB_MASK                                 (0x3 << 22)
+#define OMAP4_FREF_DR7_LB_SHIFT                                        20
+#define OMAP4_FREF_DR7_LB_MASK                                 (0x3 << 20)
+#define OMAP4_GPIO_DR7_LB_SHIFT                                        18
+#define OMAP4_GPIO_DR7_LB_MASK                                 (0x3 << 18)
+#define OMAP4_DPM_DR0_LB_SHIFT                                 14
+#define OMAP4_DPM_DR0_LB_MASK                                  (0x3 << 14)
+#define OMAP4_SIM_DR0_LB_SHIFT                                 12
+#define OMAP4_SIM_DR0_LB_MASK                                  (0x3 << 12)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_FREF_SHIFT                               31
+#define OMAP4_VDDS_DV_FREF_MASK                                        (1 << 31)
+#define OMAP4_VDDS_DV_BANK2_SHIFT                              30
+#define OMAP4_VDDS_DV_BANK2_MASK                               (1 << 30)
+
+/* CONTROL_XTAL_OSCILLATOR */
+#define OMAP4_OSCILLATOR_BOOST_SHIFT                           31
+#define OMAP4_OSCILLATOR_BOOST_MASK                            (1 << 31)
+#define OMAP4_OSCILLATOR_OS_OUT_SHIFT                          30
+#define OMAP4_OSCILLATOR_OS_OUT_MASK                           (1 << 30)
+
+/* CONTROL_USIMIO */
+#define OMAP4_PAD_USIM_CLK_LOW_SHIFT                           31
+#define OMAP4_PAD_USIM_CLK_LOW_MASK                            (1 << 31)
+#define OMAP4_PAD_USIM_RST_LOW_SHIFT                           29
+#define OMAP4_PAD_USIM_RST_LOW_MASK                            (1 << 29)
+#define OMAP4_USIM_PWRDNZ_SHIFT                                        28
+#define OMAP4_USIM_PWRDNZ_MASK                                 (1 << 28)
+
+/* CONTROL_I2C_2 */
+#define OMAP4_SR_SDA_GLFENB_SHIFT                              31
+#define OMAP4_SR_SDA_GLFENB_MASK                               (1 << 31)
+#define OMAP4_SR_SDA_LOAD_BITS_SHIFT                           29
+#define OMAP4_SR_SDA_LOAD_BITS_MASK                            (0x3 << 29)
+#define OMAP4_SR_SDA_PULLUPRESX_SHIFT                          28
+#define OMAP4_SR_SDA_PULLUPRESX_MASK                           (1 << 28)
+#define OMAP4_SR_SCL_GLFENB_SHIFT                              27
+#define OMAP4_SR_SCL_GLFENB_MASK                               (1 << 27)
+#define OMAP4_SR_SCL_LOAD_BITS_SHIFT                           25
+#define OMAP4_SR_SCL_LOAD_BITS_MASK                            (0x3 << 25)
+#define OMAP4_SR_SCL_PULLUPRESX_SHIFT                          24
+#define OMAP4_SR_SCL_PULLUPRESX_MASK                           (1 << 24)
+
+/* CONTROL_JTAG */
+#define OMAP4_JTAG_NTRST_EN_SHIFT                              31
+#define OMAP4_JTAG_NTRST_EN_MASK                               (1 << 31)
+#define OMAP4_JTAG_TCK_EN_SHIFT                                        30
+#define OMAP4_JTAG_TCK_EN_MASK                                 (1 << 30)
+#define OMAP4_JTAG_RTCK_EN_SHIFT                               29
+#define OMAP4_JTAG_RTCK_EN_MASK                                        (1 << 29)
+#define OMAP4_JTAG_TDI_EN_SHIFT                                        28
+#define OMAP4_JTAG_TDI_EN_MASK                                 (1 << 28)
+#define OMAP4_JTAG_TDO_EN_SHIFT                                        27
+#define OMAP4_JTAG_TDO_EN_MASK                                 (1 << 27)
+
+/* CONTROL_SYS */
+#define OMAP4_SYS_NRESWARM_PIPU_SHIFT                          31
+#define OMAP4_SYS_NRESWARM_PIPU_MASK                           (1 << 31)
+
+/* WKUP_CONTROL_SPARE_RW */
+#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT                      0
+#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK                       (0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R */
+#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT                       0
+#define OMAP4_WKUP_CONTROL_SPARE_R_MASK                                (0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R_C0 */
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT                    31
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK                     (1 << 31)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT                    30
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK                     (1 << 30)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT                    29
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK                     (1 << 29)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT                    28
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK                     (1 << 28)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT                    27
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK                     (1 << 27)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT                    26
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK                     (1 << 26)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT                    25
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK                     (1 << 25)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT                    24
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK                     (1 << 24)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
new file mode 100644 (file)
index 0000000..a0af9ba
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * OMAP44xx CTRL_MODULE_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * 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 __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_WKUP                         0x4a30c000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION             0x0000
+#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO               0x0004
+#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG            0x0010
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0    0x0460
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1    0x0464
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2    0x0468
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_3    0x046c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_4    0x0470
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_5    0x0474
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_6    0x0478
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_7    0x047c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_8    0x0480
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_9    0x0484
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_10   0x0488
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_11   0x048c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_12   0x0490
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_13   0x0494
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_14   0x0498
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_15   0x049c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_16   0x04a0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_17   0x04a4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_18   0x04a8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_19   0x04ac
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_20   0x04b0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_21   0x04b4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_22   0x04b8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_23   0x04bc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_24   0x04c0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_25   0x04c4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_26   0x04c8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_27   0x04cc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_28   0x04d0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_29   0x04d4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_30   0x04d8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_31   0x04dc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT              30
+#define OMAP4_IP_REV_SCHEME_MASK               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                        16
+#define OMAP4_IP_REV_FUNC_MASK                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                 11
+#define OMAP4_IP_REV_RTL_MASK                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT               8
+#define OMAP4_IP_REV_MAJOR_MASK                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT              6
+#define OMAP4_IP_REV_CUSTOM_MASK               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT               0
+#define OMAP4_IP_REV_MINOR_MASK                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                  0
+#define OMAP4_IP_HWINFO_MASK                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK       (0x3 << 2)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_WKUP_MODE_SHIFT                  0
+#define OMAP4_WKUP_MODE_MASK                           (1 << 0)
+
+#endif
index b9ea70b..40562dd 100644 (file)
@@ -36,6 +36,7 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
+#include "io.h"
 
 #include <plat/omap-pm.h>
 #include <plat/powerdomain.h>
@@ -323,6 +324,9 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
                omap2430_hwmod_init();
        else if (cpu_is_omap34xx())
                omap3xxx_hwmod_init();
+       else if (cpu_is_omap44xx())
+               omap44xx_hwmod_init();
+
        /* The OPP tables have to be registered before a clk init */
        omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
 
@@ -342,9 +346,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 #ifndef CONFIG_PM_RUNTIME
        skip_setup_idle = 1;
 #endif
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())   /* FIXME: OMAP4 */
-               omap_hwmod_late_init(skip_setup_idle);
-
+       omap_hwmod_late_init(skip_setup_idle);
        if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
                omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
                _omap2_init_reprogram_sdrc();
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
new file mode 100644 (file)
index 0000000..fd230c6
--- /dev/null
@@ -0,0 +1,7 @@
+
+#ifndef __MACH_OMAP2_IO_H__
+#define __MACH_OMAP2_IO_H__
+
+extern int __init omap_sram_init(void);
+
+#endif /*  __MACH_OMAP2_IO_H__ */
index 26aeef5..32eeabe 100644 (file)
@@ -47,7 +47,6 @@ static struct omap_irq_bank {
 } __attribute__ ((aligned(4))) irq_banks[] = {
        {
                /* MPU INTC */
-               .base_reg       = 0,
                .nr_irqs        = 96,
        },
 };
index 42dbfa4..40ddeca 100644 (file)
@@ -181,7 +181,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
        l = mbox_read_reg(p->irqenable);
@@ -192,7 +192,7 @@ static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
        l = mbox_read_reg(p->irqdisable);
        l &= ~bit;
@@ -202,7 +202,7 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
 static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
        mbox_write_reg(bit, p->irqstatus);
@@ -214,7 +214,7 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
 static int omap2_mbox_is_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
        u32 enable = mbox_read_reg(p->irqenable);
        u32 status = mbox_read_reg(p->irqstatus);
index 467aae2..f9c9df5 100644 (file)
 #include <plat/cpu.h>
 #include <plat/mcbsp.h>
 
-#include "mux.h"
+#include "control.h"
 
-static void omap2_mcbsp2_mux_setup(void)
+
+/* McBSP internal signal muxing functions */
+
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-       omap_mux_init_signal("eac_ac_sclk.mcbsp2_clkx", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_fs.mcbsp2_fsx", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_din.mcbsp2_dr", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_dout.mcbsp2_dx", OMAP_PULL_ENA);
-       omap_mux_init_gpio(117, OMAP_PULL_ENA);
-       /*
-        * TODO: Need to add MUX settings for OMAP 2430 SDP
-        */
+       u32 v;
+
+       v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+       if (mux == CLKR_SRC_CLKR)
+               v &= ~OMAP2_MCBSP1_CLKR_MASK;
+       else if (mux == CLKR_SRC_CLKX)
+               v |= OMAP2_MCBSP1_CLKR_MASK;
+       omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
-static void omap2_mcbsp_request(unsigned int id)
+void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-       if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
-               omap2_mcbsp2_mux_setup();
+       u32 v;
+
+       v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+       if (mux == FSR_SRC_FSR)
+               v &= ~OMAP2_MCBSP1_FSR_MASK;
+       else if (mux == FSR_SRC_FSX)
+               v |= OMAP2_MCBSP1_FSR_MASK;
+       omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
-static struct omap_mcbsp_ops omap2_mcbsp_ops = {
-       .request        = omap2_mcbsp_request,
-};
+/* McBSP CLKS source switching function */
+
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+{
+       struct omap_mcbsp *mcbsp;
+       struct clk *fck_src;
+       char *fck_src_name;
+       int r;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+               return -EINVAL;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+
+       if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+               fck_src_name = "pad_fck";
+       else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+               fck_src_name = "prcm_fck";
+       else
+               return -EINVAL;
+
+       fck_src = clk_get(mcbsp->dev, fck_src_name);
+       if (IS_ERR_OR_NULL(fck_src)) {
+               pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
+                      fck_src_name);
+               return -EINVAL;
+       }
+
+       clk_disable(mcbsp->fclk);
+
+       r = clk_set_parent(mcbsp->fclk, fck_src);
+       if (IS_ERR_VALUE(r)) {
+               pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
+                      "clks", fck_src_name);
+               clk_put(fck_src);
+               return -EINVAL;
+       }
+
+       clk_enable(mcbsp->fclk);
+
+       clk_put(fck_src);
+
+       return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
+
+
+/* Platform data */
 
 #ifdef CONFIG_ARCH_OMAP2420
 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
@@ -55,7 +112,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -63,7 +119,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP2420_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -82,7 +137,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -90,7 +144,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP3_BASE,
@@ -98,7 +151,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP4_BASE,
@@ -106,7 +158,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP5_BASE,
@@ -114,7 +165,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP2430_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -133,7 +183,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -143,7 +192,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x500, /* The FIFO has 1024 + 256 locations */
        },
        {
@@ -153,7 +201,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -162,7 +209,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -171,7 +217,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
 };
@@ -189,28 +234,24 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP1,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP2_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP2,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP3_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP3,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP4_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP4,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP44XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap44xx_mcbsp_pdata)
index ab403b2..074536a 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -36,8 +35,7 @@
 
 #include <asm/system.h>
 
-#include <plat/control.h>
-
+#include "control.h"
 #include "mux.h"
 
 #define OMAP_MUX_BASE_OFFSET           0x30    /* Offset from CTRL_BASE */
@@ -87,7 +85,7 @@ static char *omap_mux_options;
 int __init omap_mux_init_gpio(int gpio, int val)
 {
        struct omap_mux_entry *e;
-       struct omap_mux *gpio_mux;
+       struct omap_mux *gpio_mux = NULL;
        u16 old_mode;
        u16 mux_mode;
        int found = 0;
@@ -127,17 +125,16 @@ int __init omap_mux_init_gpio(int gpio, int val)
        return 0;
 }
 
-int __init omap_mux_init_signal(char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
        struct omap_mux_entry *e;
-       char *m0_name = NULL, *mode_name = NULL;
-       int found = 0;
+       const char *mode_name;
+       int found = 0, mode0_len = 0;
 
        mode_name = strchr(muxname, '.');
        if (mode_name) {
-               *mode_name = '\0';
+               mode0_len = strlen(muxname) - strlen(mode_name);
                mode_name++;
-               m0_name = muxname;
        } else {
                mode_name = muxname;
        }
@@ -147,9 +144,11 @@ int __init omap_mux_init_signal(char *muxname, int val)
                char *m0_entry = m->muxnames[0];
                int i;
 
-               if (m0_name && strcmp(m0_name, m0_entry))
+               /* First check for full name in mode0.muxmode format */
+               if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
                        continue;
 
+               /* Then check for muxmode only */
                for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
                        char *mode_cur = m->muxnames[i];
 
index a8e040c..350c04f 100644 (file)
@@ -120,7 +120,7 @@ int omap_mux_init_gpio(int gpio, int val);
  * @muxname:           Mux name in mode0_name.signal_name format
  * @val:               Options for the mux register value
  */
-int omap_mux_init_signal(char *muxname, int val);
+int omap_mux_init_signal(const char *muxname, int val);
 
 #else
 
index fdb04a7..414af54 100644 (file)
@@ -507,7 +507,7 @@ static struct omap_mux __initdata omap2420_muxmodes[] = {
  * Balls for 447-pin POP package
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2420_pop_ball[] = {
+static struct omap_ball __initdata omap2420_pop_ball[] = {
        _OMAP2420_BALLENTRY(CAM_D0, "y4", NULL),
        _OMAP2420_BALLENTRY(CAM_D1, "y3", NULL),
        _OMAP2420_BALLENTRY(CAM_D2, "u7", NULL),
index 7dcaaa8..84d2c5a 100644 (file)
@@ -586,7 +586,7 @@ static struct omap_mux __initdata omap2430_muxmodes[] = {
  * 447-pin s-PBGA Package, 0.00mm Ball Pitch (Bottom)
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2430_pop_ball[] = {
+static struct omap_ball __initdata omap2430_pop_ball[] = {
        _OMAP2430_BALLENTRY(CAM_D0, "t8", NULL),
        _OMAP2430_BALLENTRY(CAM_D1, "t4", NULL),
        _OMAP2430_BALLENTRY(CAM_D10, "r4", NULL),
index f64d7ee..574e54e 100644 (file)
@@ -931,7 +931,7 @@ struct omap_ball __initdata omap3_cbc_ball[] = {
  * Signals different on CUS package compared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_mux __initdata omap3_cus_subset[] = {
+static struct omap_mux __initdata omap3_cus_subset[] = {
        _OMAP3_MUXENTRY(CAM_D10, 109,
                "cam_d10", NULL, NULL, NULL,
                "gpio_109", NULL, NULL, "safe_mode"),
@@ -1077,7 +1077,7 @@ struct omap_mux __initdata omap3_cus_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_ball __initdata omap3_cus_ball[] = {
+static struct omap_ball __initdata omap3_cus_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ab18", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ac18", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "f21", NULL),
@@ -1269,7 +1269,7 @@ struct omap_ball __initdata omap3_cus_ball[] = {
  * Signals different on CBB package comapared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_mux __initdata omap3_cbb_subset[] = {
+static struct omap_mux __initdata omap3_cbb_subset[] = {
        _OMAP3_MUXENTRY(CAM_D10, 109,
                "cam_d10", NULL, NULL, NULL,
                "gpio_109", NULL, NULL, "safe_mode"),
@@ -1390,7 +1390,7 @@ struct omap_mux __initdata omap3_cbb_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_ball __initdata omap3_cbb_ball[] = {
+static struct omap_ball __initdata omap3_cbb_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
@@ -1600,7 +1600,7 @@ struct omap_ball __initdata omap3_cbb_ball[] = {
  * Signals different on 36XX CBP package comapared to 34XX CBC package
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP)
-struct omap_mux __initdata omap36xx_cbp_subset[] = {
+static struct omap_mux __initdata omap36xx_cbp_subset[] = {
        _OMAP3_MUXENTRY(CAM_D0, 99,
                "cam_d0", NULL, "csi2_dx2", NULL,
                "gpio_99", NULL, NULL, "safe_mode"),
@@ -1818,7 +1818,7 @@ struct omap_mux __initdata omap36xx_cbp_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined (CONFIG_OMAP_PACKAGE_CBP)
-struct omap_ball __initdata omap36xx_cbp_ball[] = {
+static struct omap_ball __initdata omap36xx_cbp_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
index 13dc979..923f9f5 100644 (file)
@@ -61,10 +61,14 @@ static int __init omap_l2_cache_init(void)
        omap_smc1(0x102, 0x1);
 
        /*
-        * 32KB way size, 16-way associativity,
-        * parity disabled
+        * 16-way associativity, parity disabled
+        * Way size - 32KB (es1.0)
+        * Way size - 64KB (es2.0 +)
         */
-       l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+       if (omap_rev() == OMAP4430_REV_ES1_0)
+               l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+       else
+               l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff);
 
        return 0;
 }
index cb911d7..5a30658 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * This code manages "OMAP modules" (on-chip devices) and their
- * integration with Linux device driver and bus code.
- *
- * References:
+ * Introduction
+ * ------------
+ * One way to view an OMAP SoC is as a collection of largely unrelated
+ * IP blocks connected by interconnects.  The IP blocks include
+ * devices such as ARM processors, audio serial interfaces, UARTs,
+ * etc.  Some of these devices, like the DSP, are created by TI;
+ * others, like the SGX, largely originate from external vendors.  In
+ * TI's documentation, on-chip devices are referred to as "OMAP
+ * modules."  Some of these IP blocks are identical across several
+ * OMAP versions.  Others are revised frequently.
+ *
+ * These OMAP modules are tied together by various interconnects.
+ * Most of the address and data flow between modules is via OCP-based
+ * interconnects such as the L3 and L4 buses; but there are other
+ * interconnects that distribute the hardware clock tree, handle idle
+ * and reset signaling, supply power, and connect the modules to
+ * various pads or balls on the OMAP package.
+ *
+ * OMAP hwmod provides a consistent way to describe the on-chip
+ * hardware blocks and their integration into the rest of the chip.
+ * This description can be automatically generated from the TI
+ * hardware database.  OMAP hwmod provides a standard, consistent API
+ * to reset, enable, idle, and disable these hardware blocks.  And
+ * hwmod provides a way for other core code, such as the Linux device
+ * code or the OMAP power management and address space mapping code,
+ * to query the hardware database.
+ *
+ * Using hwmod
+ * -----------
+ * Drivers won't call hwmod functions directly.  That is done by the
+ * omap_device code, and in rare occasions, by custom integration code
+ * in arch/arm/ *omap*.  The omap_device code includes functions to
+ * build a struct platform_device using omap_hwmod data, and that is
+ * currently how hwmod data is communicated to drivers and to the
+ * Linux driver model.  Most drivers will call omap_hwmod functions only
+ * indirectly, via pm_runtime*() functions.
+ *
+ * From a layering perspective, here is where the OMAP hwmod code
+ * fits into the kernel software stack:
+ *
+ *            +-------------------------------+
+ *            |      Device driver code       |
+ *            |      (e.g., drivers/)         |
+ *            +-------------------------------+
+ *            |      Linux driver model       |
+ *            |     (platform_device /        |
+ *            |  platform_driver data/code)   |
+ *            +-------------------------------+
+ *            | OMAP core-driver integration  |
+ *            |(arch/arm/mach-omap2/devices.c)|
+ *            +-------------------------------+
+ *            |      omap_device code         |
+ *            | (../plat-omap/omap_device.c)  |
+ *            +-------------------------------+
+ *   ---->    |    omap_hwmod code/data       |    <-----
+ *            | (../mach-omap2/omap_hwmod*)   |
+ *            +-------------------------------+
+ *            | OMAP clock/PRCM/register fns  |
+ *            | (__raw_{read,write}l, clk*)   |
+ *            +-------------------------------+
+ *
+ * Device drivers should not contain any OMAP-specific code or data in
+ * them.  They should only contain code to operate the IP block that
+ * the driver is responsible for.  This is because these IP blocks can
+ * also appear in other SoCs, either from TI (such as DaVinci) or from
+ * other manufacturers; and drivers should be reusable across other
+ * platforms.
+ *
+ * The OMAP hwmod code also will attempt to reset and idle all on-chip
+ * devices upon boot.  The goal here is for the kernel to be
+ * completely self-reliant and independent from bootloaders.  This is
+ * to ensure a repeatable configuration, both to ensure consistent
+ * runtime behavior, and to make it easier for others to reproduce
+ * bugs.
+ *
+ * OMAP module activity states
+ * ---------------------------
+ * The hwmod code considers modules to be in one of several activity
+ * states.  IP blocks start out in an UNKNOWN state, then once they
+ * are registered via the hwmod code, proceed to the REGISTERED state.
+ * Once their clock names are resolved to clock pointers, the module
+ * enters the CLKS_INITED state; and finally, once the module has been
+ * reset and the integration registers programmed, the INITIALIZED state
+ * is entered.  The hwmod code will then place the module into either
+ * the IDLE state to save power, or in the case of a critical system
+ * module, the ENABLED state.
+ *
+ * OMAP core integration code can then call omap_hwmod*() functions
+ * directly to move the module between the IDLE, ENABLED, and DISABLED
+ * states, as needed.  This is done during both the PM idle loop, and
+ * in the OMAP core integration code's implementation of the PM runtime
+ * functions.
+ *
+ * References
+ * ----------
+ * This is a partial list.
  * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
  * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
  * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
 #include <plat/powerdomain.h>
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/prcm.h>
 
 #include "cm.h"
+#include "prm.h"
 
-/* Maximum microseconds to wait for OMAP module to reset */
-#define MAX_MODULE_RESET_WAIT          10000
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT      10000
 
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME             "mpu"
@@ -90,7 +184,7 @@ static int _update_sysc_cache(struct omap_hwmod *oh)
 
        /* XXX ensure module interface clock is up */
 
-       oh->_sysc_cache = omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+       oh->_sysc_cache = omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 
        if (!(oh->class->sysc->sysc_flags & SYSC_NO_CACHE))
                oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
@@ -117,7 +211,7 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
 
        if (oh->_sysc_cache != v) {
                oh->_sysc_cache = v;
-               omap_hwmod_writel(v, oh, oh->class->sysc->sysc_offs);
+               omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
        }
 }
 
@@ -544,6 +638,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
        return 0;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_enable(oc->_clk);
+               }
+}
+
+static void _disable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_disable(oc->_clk);
+               }
+}
+
 /**
  * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
  * @oh: struct omap_hwmod *
@@ -622,7 +746,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 }
 
 /**
- * _sysc_enable - try to bring a module out of idle via OCP_SYSCONFIG
+ * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module out of slave
@@ -630,7 +754,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
  * as SWSUP_MSUSPEND, force the module out of master standby;
  * otherwise, configure it for smart-standby.  No return value.
  */
-static void _sysc_enable(struct omap_hwmod *oh)
+static void _enable_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -653,14 +777,6 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_master_standbymode(oh, idlemode, &v);
        }
 
-       if (sf & SYSC_HAS_AUTOIDLE) {
-               idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
-                       0 : 1;
-               _set_module_autoidle(oh, idlemode, &v);
-       }
-
-       /* XXX OCP ENAWAKEUP bit? */
-
        /*
         * XXX The clock framework should handle this, by
         * calling into this code.  But this must wait until the
@@ -671,10 +787,25 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
        _write_sysconfig(v, oh);
+
+       /* If slave is in SMARTIDLE, also enable wakeup */
+       if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
+               _enable_wakeup(oh);
+
+       /*
+        * Set the autoidle bit only after setting the smartidle bit
+        * Setting this will not have any impact on the other modules.
+        */
+       if (sf & SYSC_HAS_AUTOIDLE) {
+               idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
+                       0 : 1;
+               _set_module_autoidle(oh, idlemode, &v);
+               _write_sysconfig(v, oh);
+       }
 }
 
 /**
- * _sysc_idle - try to put a module into idle via OCP_SYSCONFIG
+ * _idle_sysc - try to put a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module into slave
@@ -682,7 +813,7 @@ static void _sysc_enable(struct omap_hwmod *oh)
  * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
  * configure it for smart-standby.  No return value.
  */
-static void _sysc_idle(struct omap_hwmod *oh)
+static void _idle_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -709,13 +840,13 @@ static void _sysc_idle(struct omap_hwmod *oh)
 }
 
 /**
- * _sysc_shutdown - force a module into idle via OCP_SYSCONFIG
+ * _shutdown_sysc - force a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * Force the module into slave idle and master suspend. No return
  * value.
  */
-static void _sysc_shutdown(struct omap_hwmod *oh)
+static void _shutdown_sysc(struct omap_hwmod *oh)
 {
        u32 v;
        u8 sf;
@@ -767,10 +898,10 @@ static struct omap_hwmod *_lookup(const char *name)
  * @data: not used; pass NULL
  *
  * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Must be called
- * with omap_hwmod_mutex held.  Returns -EINVAL if the omap_hwmod
- * has not yet been registered or if the clocks have already been
- * initialized, 0 on success, or a non-zero error on failure.
+ * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
+ * the omap_hwmod has not yet been registered or if the clocks have
+ * already been initialized, 0 on success, or a non-zero error on
+ * failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
@@ -834,56 +965,202 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 }
 
 /**
+ * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line in the context of this hwmod
+ *
+ * Return the bit position of the reset line that match the
+ * input name. Return -ENOENT if not found.
+ */
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int i;
+
+       for (i = 0; i < oh->rst_lines_cnt; i++) {
+               const char *rst_line = oh->rst_lines[i].name;
+               if (!strcmp(rst_line, name)) {
+                       u8 shift = oh->rst_lines[i].rst_shift;
+                       pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
+                                oh->name, rst_line, shift);
+
+                       return shift;
+               }
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * _assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
+                                                 shift);
+       else if (cpu_is_omap44xx())
+               return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                 shift);
+       else
+               return -EINVAL;
+}
+
+/**
+ * _deassert_hardreset - deassert the HW reset line of submodules contained
+ * in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+       int r;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+                                                shift);
+       else if (cpu_is_omap44xx())
+               r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                shift);
+       else
+               return -EINVAL;
+
+       if (r == -EBUSY)
+               pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
+
+       return r;
+}
+
+/**
+ * _read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the state of the reset line.
+ */
+static int _read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+               return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
+                                                      shift);
+       } else if (cpu_is_omap44xx()) {
+               return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
+                                                      shift);
+       } else {
+               return -EINVAL;
+       }
+}
+
+/**
  * _reset - reset an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit.  hwmod must be
- * enabled for this to work.  Must be called with omap_hwmod_mutex
- * held.  Returns -EINVAL if the hwmod cannot be reset this way or if
- * the hwmod is in the wrong state, -ETIMEDOUT if the module did not
- * reset in time, or 0 upon success.
+ * enabled for this to work.  Returns -EINVAL if the hwmod cannot be
+ * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
+ * the module did not reset in time, or 0 upon success.
+ *
+ * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
+ * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
+ * use the SYSCONFIG softreset bit to provide the status.
+ *
+ * Note that some IP like McBSP does have a reset control but no reset status.
  */
 static int _reset(struct omap_hwmod *oh)
 {
-       u32 r, v;
+       u32 v;
        int c = 0;
+       int ret = 0;
 
        if (!oh->class->sysc ||
-           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET) ||
-           (oh->class->sysc->sysc_flags & SYSS_MISSING))
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
                return -EINVAL;
 
        /* clocks must be on for this operation */
        if (oh->_state != _HWMOD_STATE_ENABLED) {
-               WARN(1, "omap_hwmod: %s: reset can only be entered from "
-                    "enabled state\n", oh->name);
+               pr_warning("omap_hwmod: %s: reset can only be entered from "
+                          "enabled state\n", oh->name);
                return -EINVAL;
        }
 
+       /* For some modules, all optionnal clocks need to be enabled as well */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+
        pr_debug("omap_hwmod: %s: resetting\n", oh->name);
 
        v = oh->_sysc_cache;
-       r = _set_softreset(oh, &v);
-       if (r)
-               return r;
+       ret = _set_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
        _write_sysconfig(v, oh);
 
-       omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
-                          SYSS_RESETDONE_MASK),
-                         MAX_MODULE_RESET_WAIT, c);
-
-       if (c == MAX_MODULE_RESET_WAIT)
-               WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
-                    oh->name, MAX_MODULE_RESET_WAIT);
+       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh,
+                                                   oh->class->sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+               omap_test_timeout(!(omap_hwmod_read(oh,
+                                                    oh->class->sysc->sysc_offs)
+                                  & SYSC_TYPE2_SOFTRESET_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
+                          oh->name, MAX_MODULE_SOFTRESET_WAIT);
        else
-               pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c);
+               pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
 
        /*
         * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
         * _wait_target_ready() or _reset()
         */
 
-       return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
+       ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+dis_opt_clks:
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
+       return ret;
 }
 
 /**
@@ -891,9 +1168,11 @@ static int _reset(struct omap_hwmod *oh)
  * @oh: struct omap_hwmod *
  *
  * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
- * register target.  Must be called with omap_hwmod_mutex held.
- * Returns -EINVAL if the hwmod is in the wrong state or passes along
- * the return value of _wait_target_ready().
+ * register target.  (This function has a full name --
+ * _omap_hwmod_enable() rather than simply _enable() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or passes along the return value of
+ * _wait_target_ready().
  */
 int _omap_hwmod_enable(struct omap_hwmod *oh)
 {
@@ -909,6 +1188,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
+       /*
+        * If an IP contains only one HW reset line, then de-assert it in order
+        * to allow to enable the clocks. Otherwise the PRCM will return
+        * Intransition status, and the init will failed.
+        */
+       if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
+            oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
+               _deassert_hardreset(oh, oh->rst_lines[0].name);
+
        /* XXX mux balls */
 
        _add_initiator_dep(oh, mpu_oh);
@@ -922,7 +1210,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
                if (oh->class->sysc) {
                        if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
                                _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        } else {
                pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
@@ -933,12 +1221,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 }
 
 /**
- * _idle - idle an omap_hwmod
+ * _omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Idles an omap_hwmod @oh.  This should be called once the hwmod has
- * no further work.  Returns -EINVAL if the hwmod is in the wrong
- * state or returns 0.
+ * no further work.  (This function has a full name --
+ * _omap_hwmod_idle() rather than simply _idle() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or returns 0.
  */
 int _omap_hwmod_idle(struct omap_hwmod *oh)
 {
@@ -951,7 +1241,7 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_idle(oh);
+               _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
        _disable_clocks(oh);
 
@@ -981,10 +1271,21 @@ static int _shutdown(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_shutdown(oh);
-       _del_initiator_dep(oh, mpu_oh);
-       /* XXX what about the other system initiators here? DMA, tesla, d2d */
-       _disable_clocks(oh);
+               _shutdown_sysc(oh);
+
+       /*
+        * If an IP contains only one HW reset line, then assert it
+        * before disabling the clocks and shutting down the IP.
+        */
+       if (oh->rst_lines_cnt == 1)
+               _assert_hardreset(oh, oh->rst_lines[0].name);
+
+       /* clocks and deps are already disabled in idle */
+       if (oh->_state == _HWMOD_STATE_ENABLED) {
+               _del_initiator_dep(oh, mpu_oh);
+               /* XXX what about the other system initiators here? dma, dsp */
+               _disable_clocks(oh);
+       }
        /* XXX Should this code also force-disable the optional clocks? */
 
        /* XXX mux any associated balls to safe mode */
@@ -1000,11 +1301,10 @@ static int _shutdown(struct omap_hwmod *oh)
  * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Must be called with omap_hwmod_mutex held.
- * @skip_setup_idle is intended to be used on a system that will not
- * call omap_hwmod_enable() to enable devices (e.g., a system without
- * PM runtime).  Returns -EINVAL if the hwmod is in the wrong state or
- * returns 0.
+ * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
+ * a system that will not call omap_hwmod_enable() to enable devices
+ * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
+ * is in the wrong state or returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
@@ -1034,8 +1334,19 @@ static int _setup(struct omap_hwmod *oh, void *data)
                }
        }
 
+       mutex_init(&oh->_mutex);
        oh->_state = _HWMOD_STATE_INITIALIZED;
 
+       /*
+        * In the case of hwmod with hardreset that should not be
+        * de-assert at boot time, we have to keep the module
+        * initialized, because we cannot enable it properly with the
+        * reset asserted. Exit without warning because that behavior is
+        * expected.
+        */
+       if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
+               return 0;
+
        r = _omap_hwmod_enable(oh);
        if (r) {
                pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
@@ -1044,16 +1355,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
        }
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+               _reset(oh);
+
                /*
-                * XXX Do the OCP_SYSCONFIG bits need to be
-                * reprogrammed after a reset?  If not, then this can
-                * be removed.  If they do, then probably the
-                * _omap_hwmod_enable() function should be split to avoid the
-                * rewrite of the OCP_SYSCONFIG register.
+                * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
+                * The _omap_hwmod_enable() function should be split to
+                * avoid the rewrite of the OCP_SYSCONFIG register.
                 */
                if (oh->class->sysc) {
                        _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        }
 
@@ -1067,14 +1378,20 @@ static int _setup(struct omap_hwmod *oh, void *data)
 
 /* Public functions */
 
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
 {
-       return __raw_readl(oh->_mpu_rt_va + reg_offs);
+       if (oh->flags & HWMOD_16BIT_REG)
+               return __raw_readw(oh->_mpu_rt_va + reg_offs);
+       else
+               return __raw_readl(oh->_mpu_rt_va + reg_offs);
 }
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
 {
-       __raw_writel(v, oh->_mpu_rt_va + reg_offs);
+       if (oh->flags & HWMOD_16BIT_REG)
+               __raw_writew(v, oh->_mpu_rt_va + reg_offs);
+       else
+               __raw_writel(v, oh->_mpu_rt_va + reg_offs);
 }
 
 /**
@@ -1309,7 +1626,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Enable an omap_hwomd @oh.  Intended to be called by omap_device_enable().
+ * Enable an omap_hwmod @oh.  Intended to be called by omap_device_enable().
  * Returns -EINVAL on error or passes along the return value from _enable().
  */
 int omap_hwmod_enable(struct omap_hwmod *oh)
@@ -1319,9 +1636,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1331,7 +1648,7 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
  * omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Idle an omap_hwomd @oh.  Intended to be called by omap_device_idle().
+ * Idle an omap_hwmod @oh.  Intended to be called by omap_device_idle().
  * Returns -EINVAL on error or passes along the return value from _idle().
  */
 int omap_hwmod_idle(struct omap_hwmod *oh)
@@ -1339,9 +1656,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _omap_hwmod_idle(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1350,7 +1667,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
  * omap_hwmod_shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Shutdown an omap_hwomd @oh.  Intended to be called by
+ * Shutdown an omap_hwmod @oh.  Intended to be called by
  * omap_device_shutdown().  Returns -EINVAL on error or passes along
  * the return value from _shutdown().
  */
@@ -1359,9 +1676,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _shutdown(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1374,9 +1691,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
  */
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1389,9 +1706,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
  */
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1421,7 +1738,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
         * Forces posted writes to complete on the OCP thread handling
         * register writes
         */
-       omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+       omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 }
 
 /**
@@ -1430,20 +1747,18 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
  *
  * Under some conditions, a driver may wish to reset the entire device.
  * Called from omap_device code.  Returns -EINVAL on error or passes along
- * the return value from _reset()/_enable().
+ * the return value from _reset().
  */
 int omap_hwmod_reset(struct omap_hwmod *oh)
 {
        int r;
 
-       if (!oh || !(oh->_state & _HWMOD_STATE_ENABLED))
+       if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _reset(oh);
-       if (!r)
-               r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1468,7 +1783,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
 {
        int ret, i;
 
-       ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
+       ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
 
        for (i = 0; i < oh->slaves_cnt; i++)
                ret += oh->slaves[i]->addr_cnt;
@@ -1501,10 +1816,10 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
                r++;
        }
 
-       for (i = 0; i < oh->sdma_chs_cnt; i++) {
-               (res + r)->name = (oh->sdma_chs + i)->name;
-               (res + r)->start = (oh->sdma_chs + i)->dma_ch;
-               (res + r)->end = (oh->sdma_chs + i)->dma_ch;
+       for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+               (res + r)->name = (oh->sdma_reqs + i)->name;
+               (res + r)->start = (oh->sdma_reqs + i)->dma_req;
+               (res + r)->end = (oh->sdma_reqs + i)->dma_req;
                (res + r)->flags = IORESOURCE_DMA;
                r++;
        }
@@ -1644,9 +1959,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1669,14 +1984,92 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
 
 /**
+ * omap_hwmod_assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _assert_hardreset().
+ */
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _assert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_deassert_hardreset - deassert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _deassert_hardreset().
+ */
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _deassert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the current state of the hwmod @oh's reset line named @name:
+ * returns -EINVAL upon parameter error or if this operation
+ * is unsupported on the current OMAP; otherwise, passes along the return
+ * value from _read_hardreset().
+ */
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _read_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+
+/**
  * omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
  * @classname: struct omap_hwmod_class name to search for
  * @fn: callback function pointer to call for each hwmod in class @classname
index 3cc768e..adf6e36 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2420 hardware module integration data
@@ -33,6 +35,7 @@ static struct omap_hwmod omap2420_mpu_hwmod;
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -71,6 +74,9 @@ static struct omap_hwmod omap2420_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap2420_l4_wkup_hwmod;
+static struct omap_hwmod omap2420_uart1_hwmod;
+static struct omap_hwmod omap2420_uart2_hwmod;
+static struct omap_hwmod omap2420_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART1_BASE,
+               .pa_end         = OMAP2_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap2420_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART2_BASE,
+               .pa_end         = OMAP2_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap2420_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART3_BASE,
+               .pa_end         = OMAP2_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap2420_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
        &omap2420_l3_main__l4_core,
@@ -87,6 +147,9 @@ static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
        &omap2420_l4_core__l4_wkup,
+       &omap2_l4_core__uart1,
+       &omap2_l4_core__uart2,
+       &omap2_l4_core__uart3,
 };
 
 /* L4 CORE */
@@ -165,12 +228,206 @@ static struct omap_hwmod omap2420_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x48022000,
+               .pa_end         = 0x4802207f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
+       .master         = &omap2420_l4_wkup_hwmod,
+       .slave          = &omap2420_wd_timer2_hwmod,
+       .clk            = "mpu_wdt_ick",
+       .addr           = omap2420_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2420_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap2420_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
+       &omap2420_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2420_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap2420_wd_timer_hwmod_class,
+       .main_clk       = "mpu_wdt_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+               },
+       },
+       .slaves         = omap2420_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
+       &omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2420_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
+       &omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2420_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
+       &omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2420_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 2,
+                       .module_bit = OMAP24XX_EN_UART3_SHIFT,
+                       .idlest_reg_id = 2,
+                       .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
        &omap2420_l3_main_hwmod,
        &omap2420_l4_core_hwmod,
        &omap2420_l4_wkup_hwmod,
        &omap2420_mpu_hwmod,
        &omap2420_iva_hwmod,
+       &omap2420_wd_timer2_hwmod,
+       &omap2420_uart1_hwmod,
+       &omap2420_uart2_hwmod,
+       &omap2420_uart3_hwmod,
        NULL,
 };
 
index 4526628..12d939e 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2430 hardware module integration data
@@ -33,6 +35,7 @@ static struct omap_hwmod omap2430_mpu_hwmod;
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -71,6 +74,9 @@ static struct omap_hwmod omap2430_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap2430_l4_wkup_hwmod;
+static struct omap_hwmod omap2430_uart1_hwmod;
+static struct omap_hwmod omap2430_uart2_hwmod;
+static struct omap_hwmod omap2430_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART1_BASE,
+               .pa_end         = OMAP2_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap2430_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART2_BASE,
+               .pa_end         = OMAP2_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap2430_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART3_BASE,
+               .pa_end         = OMAP2_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap2430_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
        &omap2430_l3_main__l4_core,
@@ -104,6 +164,9 @@ static struct omap_hwmod omap2430_l4_core_hwmod = {
 /* Slave interfaces on the L4_WKUP interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = {
        &omap2430_l4_core__l4_wkup,
+       &omap2_l4_core__uart1,
+       &omap2_l4_core__uart2,
+       &omap2_l4_core__uart3,
 };
 
 /* Master interfaces on the L4_WKUP interconnect */
@@ -165,12 +228,206 @@ static struct omap_hwmod omap2430_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x49016000,
+               .pa_end         = 0x4901607f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
+       .master         = &omap2430_l4_wkup_hwmod,
+       .slave          = &omap2430_wd_timer2_hwmod,
+       .clk            = "mpu_wdt_ick",
+       .addr           = omap2430_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2430_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
+       .rev_offs       = 0x0,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap2430_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
+       &omap2430_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2430_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap2430_wd_timer_hwmod_class,
+       .main_clk       = "mpu_wdt_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+               },
+       },
+       .slaves         = omap2430_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
+       &omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2430_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
+       &omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2430_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
+       &omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2430_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 2,
+                       .module_bit = OMAP24XX_EN_UART3_SHIFT,
+                       .idlest_reg_id = 2,
+                       .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
        &omap2430_l3_main_hwmod,
        &omap2430_l4_core_hwmod,
        &omap2430_l4_wkup_hwmod,
        &omap2430_mpu_hwmod,
        &omap2430_iva_hwmod,
+       &omap2430_wd_timer2_hwmod,
+       &omap2430_uart1_hwmod,
+       &omap2430_uart2_hwmod,
+       &omap2430_uart3_hwmod,
        NULL,
 };
 
index 5d8eb58..cb97ecf 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
+#include "cm-regbits-34xx.h"
 
 /*
  * OMAP3xxx hardware module integration data
@@ -36,6 +38,7 @@ static struct omap_hwmod omap3xxx_iva_hwmod;
 static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -82,6 +85,10 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod;
+static struct omap_hwmod omap3xxx_uart1_hwmod;
+static struct omap_hwmod omap3xxx_uart2_hwmod;
+static struct omap_hwmod omap3xxx_uart3_hwmod;
+static struct omap_hwmod omap3xxx_uart4_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
@@ -90,6 +97,78 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART1_BASE,
+               .pa_end         = OMAP3_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap3xxx_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART2_BASE,
+               .pa_end         = OMAP3_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap3xxx_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART3_BASE,
+               .pa_end         = OMAP3_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
+       .master         = &omap3xxx_l4_per_hwmod,
+       .slave          = &omap3xxx_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap3xxx_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART4 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART4_BASE,
+               .pa_end         = OMAP3_UART4_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
+       .master         = &omap3xxx_l4_per_hwmod,
+       .slave          = &omap3xxx_uart4_hwmod,
+       .clk            = "uart4_ick",
+       .addr           = omap3xxx_uart4_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart4_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
        &omap3xxx_l3_main__l4_core,
@@ -98,6 +177,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
        &omap3xxx_l4_core__l4_wkup,
+       &omap3_l4_core__uart1,
+       &omap3_l4_core__uart2,
 };
 
 /* L4 CORE */
@@ -119,6 +200,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
 
 /* Master interfaces on the L4_PER interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
+       &omap3_l4_per__uart3,
+       &omap3_l4_per__uart4,
 };
 
 /* L4 PER */
@@ -197,6 +280,235 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x48314000,
+               .pa_end         = 0x4831407f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
+       .master         = &omap3xxx_l4_wkup_hwmod,
+       .slave          = &omap3xxx_wd_timer2_hwmod,
+       .clk            = "wdt2_ick",
+       .addr           = omap3xxx_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap3xxx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
+       &omap3xxx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap3xxx_wd_timer_hwmod_class,
+       .main_clk       = "wdt2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_WDT2_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART common */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
+       &omap3_l4_core__uart1,
+};
+
+static struct omap_hwmod omap3xxx_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
+       &omap3_l4_core__uart2,
+};
+
+static struct omap_hwmod omap3xxx_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
+       &omap3_l4_per__uart3,
+};
+
+static struct omap_hwmod omap3xxx_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = OMAP3430_PER_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART3_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART4 */
+
+static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
+       { .irq = INT_36XX_UART4_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP36XX_DMA_UART4_RX, },
+       { .name = "tx", .dma_req = OMAP36XX_DMA_UART4_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
+       &omap3_l4_per__uart4,
+};
+
+static struct omap_hwmod omap3xxx_uart4_hwmod = {
+       .name           = "uart4",
+       .mpu_irqs       = uart4_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart4_mpu_irqs),
+       .sdma_reqs      = uart4_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart4_sdma_reqs),
+       .main_clk       = "uart4_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = OMAP3430_PER_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3630_EN_UART4_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart4_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart4_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_l3_main_hwmod,
        &omap3xxx_l4_core_hwmod,
@@ -204,6 +516,11 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_l4_wkup_hwmod,
        &omap3xxx_mpu_hwmod,
        &omap3xxx_iva_hwmod,
+       &omap3xxx_wd_timer2_hwmod,
+       &omap3xxx_uart1_hwmod,
+       &omap3xxx_uart2_hwmod,
+       &omap3xxx_uart3_hwmod,
+       &omap3xxx_uart4_hwmod,
        NULL,
 };
 
@@ -211,5 +528,3 @@ int __init omap3xxx_hwmod_init(void)
 {
        return omap_hwmod_init(omap3xxx_hwmods);
 }
-
-
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
new file mode 100644 (file)
index 0000000..7274db4
--- /dev/null
@@ -0,0 +1,850 @@
+/*
+ * Hardware modules present on the OMAP44xx chips
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ * Benoit Cousson
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/cpu.h>
+
+#include "omap_hwmod_common_data.h"
+
+#include "cm.h"
+#include "prm-regbits-44xx.h"
+
+/* Base offset for all OMAP4 interrupts external to MPUSS */
+#define OMAP44XX_IRQ_GIC_START 32
+
+/* Base offset for all OMAP4 dma requests */
+#define OMAP44XX_DMA_REQ_START  1
+
+/* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dmm_hwmod;
+static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_l3_instr_hwmod;
+static struct omap_hwmod omap44xx_l3_main_1_hwmod;
+static struct omap_hwmod omap44xx_l3_main_2_hwmod;
+static struct omap_hwmod omap44xx_l3_main_3_hwmod;
+static struct omap_hwmod omap44xx_l4_abe_hwmod;
+static struct omap_hwmod omap44xx_l4_cfg_hwmod;
+static struct omap_hwmod omap44xx_l4_per_hwmod;
+static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mpu_hwmod;
+static struct omap_hwmod omap44xx_mpu_private_hwmod;
+
+/*
+ * Interconnects omap_hwmod structures
+ * hwmods that compose the global OMAP interconnect
+ */
+
+/*
+ * 'dmm' class
+ * instance(s): dmm
+ */
+static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
+       .name = "dmm",
+};
+
+/* dmm interface data */
+/* l3_main_1 -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dmm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
+       &omap44xx_l3_main_1__dmm,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+       { .irq = 113 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod omap44xx_dmm_hwmod = {
+       .name           = "dmm",
+       .class          = &omap44xx_dmm_hwmod_class,
+       .slaves         = omap44xx_dmm_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_dmm_slaves),
+       .mpu_irqs       = omap44xx_dmm_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_dmm_irqs),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'emif_fw' class
+ * instance(s): emif_fw
+ */
+static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
+       .name = "emif_fw",
+};
+
+/* emif_fw interface data */
+/* dmm -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
+       .master         = &omap44xx_dmm_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif_fw slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
+       &omap44xx_dmm__emif_fw,
+       &omap44xx_l4_cfg__emif_fw,
+};
+
+static struct omap_hwmod omap44xx_emif_fw_hwmod = {
+       .name           = "emif_fw",
+       .class          = &omap44xx_emif_fw_hwmod_class,
+       .slaves         = omap44xx_emif_fw_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_emif_fw_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l3' class
+ * instance(s): l3_instr, l3_main_1, l3_main_2, l3_main_3
+ */
+static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
+       .name = "l3",
+};
+
+/* l3_instr interface data */
+/* l3_main_3 -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
+       .master         = &omap44xx_l3_main_3_hwmod,
+       .slave          = &omap44xx_l3_instr_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_instr slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
+       &omap44xx_l3_main_3__l3_instr,
+};
+
+static struct omap_hwmod omap44xx_l3_instr_hwmod = {
+       .name           = "l3_instr",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_instr_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_instr_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
+       &omap44xx_l3_main_2__l3_main_1,
+       &omap44xx_l4_cfg__l3_main_1,
+       &omap44xx_mpu__l3_main_1,
+};
+
+static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
+       .name           = "l3_main_1",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 interface data */
+/* l3_main_1 -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_2,
+       &omap44xx_l4_cfg__l3_main_2,
+};
+
+static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
+       .name           = "l3_main_2",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_3 interface data */
+/* l3_main_1 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_3,
+       &omap44xx_l3_main_2__l3_main_3,
+       &omap44xx_l4_cfg__l3_main_3,
+};
+
+static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
+       .name           = "l3_main_3",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_abe, l4_cfg, l4_per, l4_wkup
+ */
+static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
+       .name = "l4",
+};
+
+/* l4_abe interface data */
+/* l3_main_1 -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_abe slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+       &omap44xx_l3_main_1__l4_abe,
+       &omap44xx_mpu__l4_abe,
+};
+
+static struct omap_hwmod omap44xx_l4_abe_hwmod = {
+       .name           = "l4_abe",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_abe_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_abe_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_cfg interface data */
+/* l3_main_1 -> l4_cfg */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_cfg_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
+       &omap44xx_l3_main_1__l4_cfg,
+};
+
+static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
+       .name           = "l4_cfg",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_cfg_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per interface data */
+/* l3_main_2 -> l4_per */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l4_per_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
+       &omap44xx_l3_main_2__l4_per,
+};
+
+static struct omap_hwmod omap44xx_l4_per_hwmod = {
+       .name           = "l4_per",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_per_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_per_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_wkup interface data */
+/* l4_cfg -> l4_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l4_wkup_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
+       &omap44xx_l4_cfg__l4_wkup,
+};
+
+static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
+       .name           = "l4_wkup",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_wkup_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu_bus' class
+ * instance(s): mpu_private
+ */
+static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
+       .name = "mpu_bus",
+};
+
+/* mpu_private interface data */
+/* mpu -> mpu_private */
+static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_mpu_private_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu_private slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
+       &omap44xx_mpu__mpu_private,
+};
+
+static struct omap_hwmod omap44xx_mpu_private_hwmod = {
+       .name           = "mpu_private",
+       .class          = &omap44xx_mpu_bus_hwmod_class,
+       .slaves         = omap44xx_mpu_private_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_mpu_private_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu' class
+ * mpu sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
+       .name = "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+       { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* mpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
+       &omap44xx_mpu__l3_main_1,
+       &omap44xx_mpu__l4_abe,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod omap44xx_mpu_hwmod = {
+       .name           = "mpu",
+       .class          = &omap44xx_mpu_hwmod_class,
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+       .mpu_irqs       = omap44xx_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_mpu_irqs),
+       .main_clk       = "dpll_mpu_m2_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+               },
+       },
+       .masters        = omap44xx_mpu_masters,
+       .masters_cnt    = ARRAY_SIZE(omap44xx_mpu_masters),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_SOFTRESET),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'uart' class
+ * universal asynchronous receiver/transmitter (uart)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
+       .rev_offs       = 0x0050,
+       .sysc_offs      = 0x0054,
+       .syss_offs      = 0x0058,
+       .sysc_flags     = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap44xx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod omap44xx_wd_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
+       { .irq = 80 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x4a314000,
+               .pa_end         = 0x4a31407f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
+       .name = "uart",
+       .sysc = &omap44xx_uart_sysc,
+};
+
+/* uart1 */
+static struct omap_hwmod omap44xx_uart1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
+       { .irq = 72 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
+       {
+               .pa_start       = 0x4806a000,
+               .pa_end         = 0x4806a0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart1_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart1_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart1_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
+       &omap44xx_l4_per__uart1,
+};
+
+static struct omap_hwmod omap44xx_uart1_hwmod = {
+       .name           = "uart1",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart1_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart1_irqs),
+       .sdma_reqs      = omap44xx_uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart1_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart2 */
+static struct omap_hwmod omap44xx_uart2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
+       { .irq = 73 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
+       {
+               .pa_start       = 0x4806c000,
+               .pa_end         = 0x4806c0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
+       .master         = &omap44xx_l4_wkup_hwmod,
+       .slave          = &omap44xx_wd_timer2_hwmod,
+       .clk            = "l4_wkup_clk_mux_ck",
+       .addr           = omap44xx_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* wd_timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
+       &omap44xx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap44xx_wd_timer_hwmod_class,
+       .mpu_irqs       = omap44xx_wd_timer2_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_wd_timer2_irqs),
+       .main_clk       = "wd_timer2_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* wd_timer3 */
+static struct omap_hwmod omap44xx_wd_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
+       { .irq = 36 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+       {
+               .pa_start       = 0x40130000,
+               .pa_end         = 0x4013007f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart2_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
+       &omap44xx_l4_per__uart2,
+};
+
+static struct omap_hwmod omap44xx_uart2_hwmod = {
+       .name           = "uart2",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart2_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart2_irqs),
+       .sdma_reqs      = omap44xx_uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart3 */
+static struct omap_hwmod omap44xx_uart3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
+       { .irq = 74 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
+       {
+               .pa_start       = 0x48020000,
+               .pa_end         = 0x480200ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_abe -> wd_timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+       .master         = &omap44xx_l4_abe_hwmod,
+       .slave          = &omap44xx_wd_timer3_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .addr           = omap44xx_wd_timer3_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer3_addrs),
+       .user           = OCP_USER_MPU,
+};
+
+/* l4_abe -> wd_timer3 (dma) */
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+       {
+               .pa_start       = 0x49030000,
+               .pa_end         = 0x4903007f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart3_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart3_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart3_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
+       &omap44xx_l4_per__uart3,
+};
+
+static struct omap_hwmod omap44xx_uart3_hwmod = {
+       .name           = "uart3",
+       .class          = &omap44xx_uart_hwmod_class,
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+       .mpu_irqs       = omap44xx_uart3_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart3_irqs),
+       .sdma_reqs      = omap44xx_uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart4 */
+static struct omap_hwmod omap44xx_uart4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
+       { .irq = 70 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
+       {
+               .pa_start       = 0x4806e000,
+               .pa_end         = 0x4806e0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+       .master         = &omap44xx_l4_abe_hwmod,
+       .slave          = &omap44xx_wd_timer3_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .addr           = omap44xx_wd_timer3_dma_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
+       .user           = OCP_USER_SDMA,
+};
+
+/* wd_timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
+       &omap44xx_l4_abe__wd_timer3,
+       &omap44xx_l4_abe__wd_timer3_dma,
+};
+
+static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
+       .name           = "wd_timer3",
+       .class          = &omap44xx_wd_timer_hwmod_class,
+       .mpu_irqs       = omap44xx_wd_timer3_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_wd_timer3_irqs),
+       .main_clk       = "wd_timer3_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_wd_timer3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_wd_timer3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per -> uart4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart4_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart4_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart4_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
+       &omap44xx_l4_per__uart4,
+};
+
+static struct omap_hwmod omap44xx_uart4_hwmod = {
+       .name           = "uart4",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart4_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart4_irqs),
+       .sdma_reqs      = omap44xx_uart4_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart4_sdma_reqs),
+       .main_clk       = "uart4_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart4_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart4_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
+       /* dmm class */
+       &omap44xx_dmm_hwmod,
+       /* emif_fw class */
+       &omap44xx_emif_fw_hwmod,
+       /* l3 class */
+       &omap44xx_l3_instr_hwmod,
+       &omap44xx_l3_main_1_hwmod,
+       &omap44xx_l3_main_2_hwmod,
+       &omap44xx_l3_main_3_hwmod,
+       /* l4 class */
+       &omap44xx_l4_abe_hwmod,
+       &omap44xx_l4_cfg_hwmod,
+       &omap44xx_l4_per_hwmod,
+       &omap44xx_l4_wkup_hwmod,
+       /* mpu_bus class */
+       &omap44xx_mpu_private_hwmod,
+
+       /* mpu class */
+       &omap44xx_mpu_hwmod,
+       /* wd_timer class */
+       &omap44xx_wd_timer2_hwmod,
+       &omap44xx_wd_timer3_hwmod,
+
+       /* uart class */
+       &omap44xx_uart1_hwmod,
+       &omap44xx_uart2_hwmod,
+       &omap44xx_uart3_hwmod,
+       &omap44xx_uart4_hwmod,
+       NULL,
+};
+
+int __init omap44xx_hwmod_init(void)
+{
+       return omap_hwmod_init(omap44xx_hwmods);
+}
+
index 723b44e..5e81517 100644 (file)
 #include <plat/board.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/dmtimer.h>
 
 #include "prm.h"
 #include "cm.h"
 #include "pm.h"
 
 int omap2_pm_debug;
+u32 enable_off_mode;
+u32 sleep_while_idle;
+u32 wakeup_timer_seconds;
+u32 wakeup_timer_milliseconds;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
        regs[reg_count].name = #mod "." #reg; \
@@ -162,7 +167,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
 
 static void pm_dbg_regset_store(u32 *ptr);
 
-struct dentry *pm_dbg_dir;
+static struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
 
@@ -349,6 +354,23 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
@@ -494,8 +516,10 @@ int pm_dbg_regset_init(int reg_set)
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
-       int ret;
-       ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
+       int ret = -EINVAL;
+
+       if (cpu_is_omap34xx())
+               ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
        *val = ret;
 
        if (ret >= 0)
@@ -505,7 +529,10 @@ static int pwrdm_suspend_get(void *data, u64 *val)
 
 static int pwrdm_suspend_set(void *data, u64 val)
 {
-       return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+       if (cpu_is_omap34xx())
+               return omap3_pm_set_suspend_state(
+                       (struct powerdomain *)data, (int)val);
+       return -EINVAL;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
@@ -553,8 +580,10 @@ static int option_set(void *data, u64 val)
 
        *option = val;
 
-       if (option == &enable_off_mode)
-               omap3_pm_off_mode_enable(val);
+       if (option == &enable_off_mode) {
+               if (cpu_is_omap34xx())
+                       omap3_pm_off_mode_enable(val);
+       }
 
        return 0;
 }
@@ -609,6 +638,9 @@ static int __init pm_dbg_init(void)
                                   &sleep_while_idle, &pm_dbg_option_fops);
        (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
                                   &wakeup_timer_seconds, &pm_dbg_option_fops);
+       (void) debugfs_create_file("wakeup_timer_milliseconds",
+                       S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
+                       &pm_dbg_option_fops);
        pm_dbg_init_done = 1;
 
        return 0;
index 68f9f2e..59ca03b 100644 (file)
 #include <plat/omap_device.h>
 #include <plat/common.h>
 
+#include <plat/powerdomain.h>
+#include <plat/clockdomain.h>
+
 static struct omap_device_pm_latency *pm_lats;
 
 static struct device *mpu_dev;
-static struct device *dsp_dev;
+static struct device *iva_dev;
 static struct device *l3_dev;
+static struct device *dsp_dev;
 
 struct device *omap2_get_mpuss_device(void)
 {
@@ -30,10 +34,10 @@ struct device *omap2_get_mpuss_device(void)
        return mpu_dev;
 }
 
-struct device *omap2_get_dsp_device(void)
+struct device *omap2_get_iva_device(void)
 {
-       WARN_ON_ONCE(!dsp_dev);
-       return dsp_dev;
+       WARN_ON_ONCE(!iva_dev);
+       return iva_dev;
 }
 
 struct device *omap2_get_l3_device(void)
@@ -42,6 +46,13 @@ struct device *omap2_get_l3_device(void)
        return l3_dev;
 }
 
+struct device *omap4_get_dsp_device(void)
+{
+       WARN_ON_ONCE(!dsp_dev);
+       return dsp_dev;
+}
+EXPORT_SYMBOL(omap4_get_dsp_device);
+
 /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
 static int _init_omap_device(char *name, struct device **new_dev)
 {
@@ -69,8 +80,60 @@ static int _init_omap_device(char *name, struct device **new_dev)
 static void omap2_init_processor_devices(void)
 {
        _init_omap_device("mpu", &mpu_dev);
-       _init_omap_device("iva", &dsp_dev);
-       _init_omap_device("l3_main", &l3_dev);
+       _init_omap_device("iva", &iva_dev);
+       if (cpu_is_omap44xx()) {
+               _init_omap_device("l3_main_1", &l3_dev);
+               _init_omap_device("dsp", &dsp_dev);
+       } else {
+               _init_omap_device("l3_main", &l3_dev);
+       }
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+       u32 cur_state;
+       int sleep_switch = 0;
+       int ret = 0;
+
+       if (pwrdm == NULL || IS_ERR(pwrdm))
+               return -EINVAL;
+
+       while (!(pwrdm->pwrsts & (1 << state))) {
+               if (state == PWRDM_POWER_OFF)
+                       return ret;
+               state--;
+       }
+
+       cur_state = pwrdm_read_next_pwrst(pwrdm);
+       if (cur_state == state)
+               return ret;
+
+       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+               sleep_switch = 1;
+               pwrdm_wait_transition(pwrdm);
+       }
+
+       ret = pwrdm_set_next_pwrst(pwrdm, state);
+       if (ret) {
+               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+                      pwrdm->name);
+               goto err;
+       }
+
+       if (sleep_switch) {
+               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+               pwrdm_wait_transition(pwrdm);
+               pwrdm_state_switch(pwrdm);
+       }
+
+err:
+       return ret;
 }
 
 static int __init omap2_common_pm_init(void)
index 3de6ece..0d75bfd 100644 (file)
 
 #include <plat/powerdomain.h>
 
-extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
-
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
-extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
 struct cpuidle_params {
@@ -48,10 +45,16 @@ extern struct omap_dm_timer *gptimer_wakeup;
 
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
 extern int omap2_pm_debug;
+extern u32 enable_off_mode;
+extern u32 sleep_while_idle;
 #else
 #define omap2_pm_dump(mode, resume, us)                do {} while (0);
+#define omap2_pm_wakeup_on_timer(seconds, milliseconds)        do {} while (0);
 #define omap2_pm_debug                         0
+#define enable_off_mode 0
+#define sleep_while_idle 0
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
index 6aeedea..a40457d 100644 (file)
@@ -38,7 +38,6 @@
 #include <mach/irqs.h>
 #include <plat/clock.h>
 #include <plat/sram.h>
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/board.h>
 
@@ -48,6 +47,7 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
+#include "control.h"
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
@@ -245,6 +245,8 @@ static int omap2_can_sleep(void)
 {
        if (omap2_fclks_active())
                return 0;
+       if (!omap_uart_can_sleep())
+               return 0;
        if (osc_ck->usecount > 1)
                return 0;
        if (omap_dma_running())
index 7b03426..75c0cd1 100644 (file)
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
 #include <plat/powerdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 #include <plat/sdrc.h>
 #include <plat/prcm.h>
 #include <plat/gpmc.h>
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 
 #include <asm/tlbflush.h>
 
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "control.h"
 
 /* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET     0x31
-#define OMAP343X_TABLE_VALUE_OFFSET       0x30
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0x32
-
-u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
+#define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
+#define OMAP343X_TABLE_VALUE_OFFSET       0xc0
+#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
 
 struct power_state {
        struct powerdomain *pwrdm;
@@ -316,7 +310,7 @@ static void restore_control_register(u32 val)
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
-       u32 *scratchpad_address;
+       void __iomem *scratchpad_address;
        u32 previous_value, control_reg_value;
        u32 *address;
 
@@ -351,7 +345,6 @@ void omap_sram_idle(void)
        int core_next_state = PWRDM_POWER_ON;
        int core_prev_state, per_prev_state;
        u32 sdrc_pwr = 0;
-       int per_state_modified = 0;
 
        if (!_omap_sram_idle)
                return;
@@ -385,9 +378,9 @@ void omap_sram_idle(void)
        /* Enable IO-PAD and IO-CHAIN wakeups */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-       if (omap3_has_io_wakeup() && \
-                       (per_next_state < PWRDM_POWER_ON ||
-                       core_next_state < PWRDM_POWER_ON)) {
+       if (omap3_has_io_wakeup() &&
+           (per_next_state < PWRDM_POWER_ON ||
+            core_next_state < PWRDM_POWER_ON)) {
                prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
                omap3_enable_io_chain();
        }
@@ -395,20 +388,12 @@ void omap_sram_idle(void)
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(2);
+               omap_uart_prepare_idle(3);
                omap2_gpio_prepare_for_idle(per_next_state);
-               if (per_next_state == PWRDM_POWER_OFF) {
-                       if (core_next_state == PWRDM_POWER_ON) {
-                               per_next_state = PWRDM_POWER_RET;
-                               pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-                               per_state_modified = 1;
-                       } else
+               if (per_next_state == PWRDM_POWER_OFF)
                                omap3_per_save_context();
-               }
        }
 
-       if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-               omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
-
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(0);
@@ -475,8 +460,7 @@ void omap_sram_idle(void)
                if (per_prev_state == PWRDM_POWER_OFF)
                        omap3_per_restore_context();
                omap_uart_resume_idle(2);
-               if (per_state_modified)
-                       pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
+               omap_uart_resume_idle(3);
        }
 
        /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -501,51 +485,6 @@ int omap3_can_sleep(void)
        return 1;
 }
 
-/* This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported. Function is assuming that clkdm doesn't have
- * hw_sup mode enabled. */
-int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
-{
-       u32 cur_state;
-       int sleep_switch = 0;
-       int ret = 0;
-
-       if (pwrdm == NULL || IS_ERR(pwrdm))
-               return -EINVAL;
-
-       while (!(pwrdm->pwrsts & (1 << state))) {
-               if (state == PWRDM_POWER_OFF)
-                       return ret;
-               state--;
-       }
-
-       cur_state = pwrdm_read_next_pwrst(pwrdm);
-       if (cur_state == state)
-               return ret;
-
-       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
-               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-               sleep_switch = 1;
-               pwrdm_wait_transition(pwrdm);
-       }
-
-       ret = pwrdm_set_next_pwrst(pwrdm, state);
-       if (ret) {
-               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-                      pwrdm->name);
-               goto err;
-       }
-
-       if (sleep_switch) {
-               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-               pwrdm_wait_transition(pwrdm);
-               pwrdm_state_switch(pwrdm);
-       }
-
-err:
-       return ret;
-}
-
 static void omap3_pm_idle(void)
 {
        local_irq_disable();
@@ -567,23 +506,6 @@ out:
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state;
 
-static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
@@ -604,7 +526,7 @@ static int omap3_pm_suspend(void)
                pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
        /* Set ones wanted by suspend */
        list_for_each_entry(pwrst, &pwrst_list, node) {
-               if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+               if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
                        goto restore;
                if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
                        goto restore;
@@ -625,7 +547,7 @@ restore:
                               pwrst->pwrdm->name, pwrst->next_state);
                        ret = -1;
                }
-               set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+               omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
        }
        if (ret)
                printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -756,6 +678,14 @@ static void __init omap3_d2d_idle(void)
 
 static void __init prcm_setup_regs(void)
 {
+       u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_AUTO_UART4_MASK : 0;
+       u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_EN_UART4_MASK : 0;
+       u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_GRPSEL_UART4_MASK : 0;
+
+
        /* XXX Reset all wkdeps. This should be done when initializing
         * powerdomains */
        prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -842,6 +772,7 @@ static void __init prcm_setup_regs(void)
                CM_AUTOIDLE);
 
        cm_write_mod_reg(
+               omap3630_auto_uart4_mask |
                OMAP3430_AUTO_GPIO6_MASK |
                OMAP3430_AUTO_GPIO5_MASK |
                OMAP3430_AUTO_GPIO4_MASK |
@@ -918,14 +849,16 @@ static void __init prcm_setup_regs(void)
                                OMAP3430_DSS_MOD, PM_WKEN);
 
        /* Enable wakeups in PER */
-       prm_write_mod_reg(OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
+       prm_write_mod_reg(omap3630_en_uart4_mask |
+                         OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
                          OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
                          OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
                          OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
                          OMAP3430_EN_MCBSP4_MASK,
                          OMAP3430_PER_MOD, PM_WKEN);
        /* and allow them to wake up MPU */
-       prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2_MASK |
+       prm_write_mod_reg(omap3630_grpsel_uart4_mask |
+                         OMAP3430_GRPSEL_GPIO2_MASK |
                          OMAP3430_GRPSEL_GPIO3_MASK |
                          OMAP3430_GRPSEL_GPIO4_MASK |
                          OMAP3430_GRPSEL_GPIO5_MASK |
@@ -974,7 +907,7 @@ void omap3_pm_off_mode_enable(int enable)
 
        list_for_each_entry(pwrst, &pwrst_list, node) {
                pwrst->next_state = state;
-               set_pwrdm_state(pwrst->pwrdm, state);
+               omap_set_pwrdm_state(pwrst->pwrdm, state);
        }
 }
 
@@ -1019,7 +952,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
        if (pwrdm_has_hdwr_sar(pwrdm))
                pwrdm_enable_hdwr_sar(pwrdm);
 
-       return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+       return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
 /*
@@ -1029,9 +962,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-       clkdm_clear_all_wkdeps(clkdm);
-       clkdm_clear_all_sleepdeps(clkdm);
-
        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
                omap2_clkdm_allow_idle(clkdm);
        else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c
new file mode 100644 (file)
index 0000000..784989f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Runtime PM support code for OMAP
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+int omap_pm_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       int r, ret = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+
+       if (!ret && dev->parent == &omap_device_parent) {
+               r = omap_device_idle(pdev);
+               WARN_ON(r);
+       }
+
+       return ret;
+};
+
+int omap_pm_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       int r;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       if (dev->parent == &omap_device_parent) {
+               r = omap_device_enable(pdev);
+               WARN_ON(r);
+       }
+
+       return pm_generic_runtime_resume(dev);
+};
+#else
+#define omap_pm_runtime_suspend NULL
+#define omap_pm_runtime_resume NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static int __init omap_pm_runtime_init(void)
+{
+       const struct dev_pm_ops *pm;
+       struct dev_pm_ops *omap_pm;
+
+       pm = platform_bus_get_pm_ops();
+       if (!pm) {
+               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+       if (!omap_pm) {
+               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       omap_pm->runtime_suspend = omap_pm_runtime_suspend;
+       omap_pm->runtime_resume = omap_pm_runtime_resume;
+
+       platform_bus_set_pm_ops(omap_pm);
+
+       return 0;
+}
+core_initcall(omap_pm_runtime_init);
index c721951..9c01b55 100644 (file)
@@ -98,7 +98,7 @@ static struct powerdomain dss_44xx_pwrdm = {
        .prcm_offs        = OMAP4430_PRM_DSS_MOD,
        .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
        .pwrsts           = PWRSTS_OFF_RET_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 1,
        .pwrsts_mem_ret = {
                [0] = PWRDM_POWER_OFF,  /* dss_mem */
index 995b7ed..298a22a 100644 (file)
 #define OMAP3430_EN_MPU_SHIFT                          1
 
 /* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
+
+#define OMAP3630_EN_UART4_MASK                         (1 << 18)
+#define OMAP3630_EN_UART4_SHIFT                                18
 #define OMAP3430_EN_GPIO6_MASK                         (1 << 17)
 #define OMAP3430_EN_GPIO6_SHIFT                                17
 #define OMAP3430_EN_GPIO5_MASK                         (1 << 16)
 #define OMAP3430_EN_MCBSP2_SHIFT                       0
 
 /* CM_IDLEST_PER, PM_WKST_PER shared bits */
+#define OMAP3630_ST_UART4_SHIFT                                18
+#define OMAP3630_ST_UART4_MASK                         (1 << 18)
 #define OMAP3430_ST_GPIO6_SHIFT                                17
 #define OMAP3430_ST_GPIO6_MASK                         (1 << 17)
 #define OMAP3430_ST_GPIO5_SHIFT                                16
index c201374..a51846e 100644 (file)
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
-#include <plat/control.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
 #include "cm.h"
 #include "prm.h"
 #include "prm-regbits-24xx.h"
+#include "prm-regbits-44xx.h"
+#include "control.h"
 
 static void __iomem *prm_base;
 static void __iomem *cm_base;
@@ -118,7 +119,7 @@ struct omap3_prcm_regs {
        u32 wkup_pm_wken;
 };
 
-struct omap3_prcm_regs prcm_context;
+static struct omap3_prcm_regs prcm_context;
 
 u32 omap_prcm_get_reset_sources(void)
 {
@@ -161,8 +162,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
                prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
                                                 OMAP2_RM_RSTCTRL);
        if (cpu_is_omap44xx())
-               prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-                                                OMAP4_RM_RSTCTRL);
+               prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
+                                    prcm_offs, OMAP4_RM_RSTCTRL);
 }
 
 static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@@ -215,6 +216,30 @@ u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
        return v;
 }
 
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= mask;
+       v >>= __ffs(mask);
+
+       return v;
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= ~mask;
+       v |= bits;
+       __raw_writel(v, reg);
+
+       return v;
+}
 /* Read a register in a CM module */
 u32 cm_read_mod_reg(s16 module, u16 idx)
 {
index 7fd6023..9e63cb7 100644 (file)
 #define OMAP3430_MEMRETSTATE_MASK                      (1 << 8)
 
 /* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
+#define OMAP3630_GRPSEL_UART4_MASK                     (1 << 18)
 #define OMAP3430_GRPSEL_GPIO6_MASK                     (1 << 17)
 #define OMAP3430_GRPSEL_GPIO5_MASK                     (1 << 16)
 #define OMAP3430_GRPSEL_GPIO4_MASK                     (1 << 15)
index 597be4a..25b19b6 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Power Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_ACT_EXPORT_SHIFT                               1
-#define OMAP4430_ABBOFF_ACT_EXPORT_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_ABBOFF_ACT_EXPORT_MASK                                        (1 << 1)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_SLEEP_EXPORT_SHIFT                             2
-#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK                              BITFIELD(2, 2)
+#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK                              (1 << 2)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_ABB_IVA_DONE_EN_SHIFT                                 31
-#define OMAP4430_ABB_IVA_DONE_EN_MASK                                  BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_EN_MASK                                  (1 << 31)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_ABB_IVA_DONE_ST_SHIFT                                 31
-#define OMAP4430_ABB_IVA_DONE_ST_MASK                                  BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_ST_MASK                                  (1 << 31)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_EN_SHIFT                                 7
-#define OMAP4430_ABB_MPU_DONE_EN_MASK                                  BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_EN_MASK                                  (1 << 7)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_ST_SHIFT                                 7
-#define OMAP4430_ABB_MPU_DONE_ST_MASK                                  BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_ST_MASK                                  (1 << 7)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_FBB_SEL_SHIFT                                  2
-#define OMAP4430_ACTIVE_FBB_SEL_MASK                                   BITFIELD(2, 2)
+#define OMAP4430_ACTIVE_FBB_SEL_MASK                                   (1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_RBB_SEL_SHIFT                                  1
-#define OMAP4430_ACTIVE_RBB_SEL_MASK                                   BITFIELD(1, 1)
+#define OMAP4430_ACTIVE_RBB_SEL_MASK                                   (1 << 1)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_AESSMEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_AESSMEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_AESSMEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_AESSMEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_AESSMEM_STATEST_SHIFT                                 4
-#define OMAP4430_AESSMEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_AESSMEM_STATEST_MASK                                  (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_AIPOFF_SHIFT                                          8
-#define OMAP4430_AIPOFF_MASK                                           BITFIELD(8, 8)
+#define OMAP4430_AIPOFF_MASK                                           (1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_CORE_L_SHIFT                            0
-#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK                             BITFIELD(0, 1)
+#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK                             (0x3 << 0)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_IVA_L_SHIFT                             4
-#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK                              BITFIELD(4, 5)
+#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK                              (0x3 << 4)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT                             2
-#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK                              BITFIELD(2, 3)
+#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK                              (0x3 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_RA_ERR_SHIFT                                     25
+#define OMAP4430_BYPS_RA_ERR_MASK                                      (1 << 25)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_SA_ERR_SHIFT                                     24
+#define OMAP4430_BYPS_SA_ERR_MASK                                      (1 << 24)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_TIMEOUT_ERR_SHIFT                                        26
+#define OMAP4430_BYPS_TIMEOUT_ERR_MASK                                 (1 << 26)
+
+/* Used by PRM_RSTST */
+#define OMAP4430_C2C_RST_SHIFT                                         10
+#define OMAP4430_C2C_RST_MASK                                          (1 << 10)
 
 /* Used by PM_CAM_PWRSTCTRL */
 #define OMAP4430_CAM_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_CAM_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_CAM_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_CAM_PWRSTST */
 #define OMAP4430_CAM_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_CAM_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_CAM_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PRM_CLKREQCTRL */
 #define OMAP4430_CLKREQ_COND_SHIFT                                     0
-#define OMAP4430_CLKREQ_COND_MASK                                      BITFIELD(0, 2)
+#define OMAP4430_CLKREQ_COND_MASK                                      (0x7 << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_CORE_L_SHIFT                                        0
-#define OMAP4430_CMDRA_VDD_CORE_L_MASK                                 BITFIELD(0, 7)
+#define OMAP4430_CMDRA_VDD_CORE_L_MASK                                 (0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_IVA_L_SHIFT                                 8
-#define OMAP4430_CMDRA_VDD_IVA_L_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_CMDRA_VDD_IVA_L_MASK                                  (0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_MPU_L_SHIFT                                 16
-#define OMAP4430_CMDRA_VDD_MPU_L_MASK                                  BITFIELD(16, 23)
+#define OMAP4430_CMDRA_VDD_MPU_L_MASK                                  (0xff << 16)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_CORE_L_SHIFT                                  4
-#define OMAP4430_CMD_VDD_CORE_L_MASK                                   BITFIELD(4, 4)
+#define OMAP4430_CMD_VDD_CORE_L_MASK                                   (1 << 4)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_IVA_L_SHIFT                                   12
-#define OMAP4430_CMD_VDD_IVA_L_MASK                                    BITFIELD(12, 12)
+#define OMAP4430_CMD_VDD_IVA_L_MASK                                    (1 << 12)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_MPU_L_SHIFT                                   17
-#define OMAP4430_CMD_VDD_MPU_L_MASK                                    BITFIELD(17, 17)
+#define OMAP4430_CMD_VDD_MPU_L_MASK                                    (1 << 17)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_ONSTATE_SHIFT                             18
-#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK                              BITFIELD(18, 19)
+#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK                              (0x3 << 18)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_RETSTATE_SHIFT                            9
-#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK                             BITFIELD(9, 9)
+#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK                             (1 << 9)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OCMRAM_STATEST_SHIFT                             6
-#define OMAP4430_CORE_OCMRAM_STATEST_MASK                              BITFIELD(6, 7)
+#define OMAP4430_CORE_OCMRAM_STATEST_MASK                              (0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_ONSTATE_SHIFT                         16
-#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK                          BITFIELD(16, 17)
+#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK                          (0x3 << 16)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_RETSTATE_SHIFT                                8
-#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK                         BITFIELD(8, 8)
+#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK                         (1 << 8)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OTHER_BANK_STATEST_SHIFT                         4
-#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK                          BITFIELD(4, 5)
+#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK                          (0x3 << 4)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_CUSTOM_SHIFT                                          6
+#define OMAP4430_CUSTOM_MASK                                           (0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_DATA_SHIFT                                            16
-#define OMAP4430_DATA_MASK                                             BITFIELD(16, 23)
+#define OMAP4430_DATA_MASK                                             (0xff << 16)
 
 /* Used by PRM_DEVICE_OFF_CTRL */
 #define OMAP4430_DEVICE_OFF_ENABLE_SHIFT                               0
-#define OMAP4430_DEVICE_OFF_ENABLE_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_DEVICE_OFF_ENABLE_MASK                                        (1 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_DFILTEREN_SHIFT                                       6
-#define OMAP4430_DFILTEREN_MASK                                                BITFIELD(6, 6)
+#define OMAP4430_DFILTEREN_MASK                                                (1 << 6)
 
-/* Used by PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
+/*
+ * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
+ * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP
+ */
+#define OMAP4430_DISABLE_RTA_EXPORT_SHIFT                              0
+#define OMAP4430_DISABLE_RTA_EXPORT_MASK                               (1 << 0)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
 #define OMAP4430_DPLL_ABE_RECAL_EN_SHIFT                               4
-#define OMAP4430_DPLL_ABE_RECAL_EN_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_DPLL_ABE_RECAL_EN_MASK                                        (1 << 4)
 
-/* Used by PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_DPLL_ABE_RECAL_ST_SHIFT                               4
-#define OMAP4430_DPLL_ABE_RECAL_ST_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_DPLL_ABE_RECAL_ST_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_CORE_RECAL_EN_SHIFT                              0
-#define OMAP4430_DPLL_CORE_RECAL_EN_MASK                               BITFIELD(0, 0)
+#define OMAP4430_DPLL_CORE_RECAL_EN_MASK                               (1 << 0)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_CORE_RECAL_ST_SHIFT                              0
-#define OMAP4430_DPLL_CORE_RECAL_ST_MASK                               BITFIELD(0, 0)
+#define OMAP4430_DPLL_CORE_RECAL_ST_MASK                               (1 << 0)
 
 /* Used by PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_DDRPHY_RECAL_EN_SHIFT                            6
-#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK                             BITFIELD(6, 6)
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK                             (1 << 6)
 
 /* Used by PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_DDRPHY_RECAL_ST_SHIFT                            6
-#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK                             BITFIELD(6, 6)
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK                             (1 << 6)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
 #define OMAP4430_DPLL_IVA_RECAL_EN_SHIFT                               2
-#define OMAP4430_DPLL_IVA_RECAL_EN_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK                                        (1 << 2)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_DPLL_IVA_RECAL_ST_SHIFT                               2
-#define OMAP4430_DPLL_IVA_RECAL_ST_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK                                        (1 << 2)
 
 /* Used by PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_MPU_RECAL_EN_SHIFT                               1
-#define OMAP4430_DPLL_MPU_RECAL_EN_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_DPLL_MPU_RECAL_EN_MASK                                        (1 << 1)
 
 /* Used by PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_MPU_RECAL_ST_SHIFT                               1
-#define OMAP4430_DPLL_MPU_RECAL_ST_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_DPLL_MPU_RECAL_ST_MASK                                        (1 << 1)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_PER_RECAL_EN_SHIFT                               3
-#define OMAP4430_DPLL_PER_RECAL_EN_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DPLL_PER_RECAL_EN_MASK                                        (1 << 3)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_PER_RECAL_ST_SHIFT                               3
-#define OMAP4430_DPLL_PER_RECAL_ST_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DPLL_PER_RECAL_ST_MASK                                        (1 << 3)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_UNIPRO_RECAL_EN_SHIFT                            7
-#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK                             BITFIELD(7, 7)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK                             (1 << 7)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_UNIPRO_RECAL_ST_SHIFT                            7
-#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK                             BITFIELD(7, 7)
-
-/* Used by PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_USB_RECAL_EN_SHIFT                               5
-#define OMAP4430_DPLL_USB_RECAL_EN_MASK                                        BITFIELD(5, 5)
-
-/* Used by PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_USB_RECAL_ST_SHIFT                               5
-#define OMAP4430_DPLL_USB_RECAL_ST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK                             (1 << 7)
 
 /* Used by PM_DSS_PWRSTCTRL */
 #define OMAP4430_DSS_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_DSS_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_DSS_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_DSS_PWRSTCTRL */
 #define OMAP4430_DSS_MEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_DSS_MEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_DSS_MEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_DSS_PWRSTST */
 #define OMAP4430_DSS_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_DSS_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_DSS_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_L2RAM_ONSTATE_SHIFT                            20
-#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK                             BITFIELD(20, 21)
+#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK                             (0x3 << 20)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_L2RAM_RETSTATE_SHIFT                           10
-#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK                            BITFIELD(10, 10)
+#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK                            (1 << 10)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_DUCATI_L2RAM_STATEST_SHIFT                            8
-#define OMAP4430_DUCATI_L2RAM_STATEST_MASK                             BITFIELD(8, 9)
+#define OMAP4430_DUCATI_L2RAM_STATEST_MASK                             (0x3 << 8)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_UNICACHE_ONSTATE_SHIFT                         22
-#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK                          BITFIELD(22, 23)
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK                          (0x3 << 22)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_UNICACHE_RETSTATE_SHIFT                                11
-#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK                         BITFIELD(11, 11)
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK                         (1 << 11)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT                         10
-#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK                          BITFIELD(10, 11)
+#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK                          (0x3 << 10)
 
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_EMULATION_RST_SHIFT                                   0
-#define OMAP4430_EMULATION_RST_MASK                                    BITFIELD(0, 0)
+#define OMAP4430_EMULATION_RST_MASK                                    (1 << 0)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_EMULATION_RST1ST_SHIFT                                        3
-#define OMAP4430_EMULATION_RST1ST_MASK                                 BITFIELD(3, 3)
+#define OMAP4430_EMULATION_RST1ST_MASK                                 (1 << 3)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_EMULATION_RST2ST_SHIFT                                        4
-#define OMAP4430_EMULATION_RST2ST_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_EMULATION_RST2ST_MASK                                 (1 << 4)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_EMULATION_SEQ1_RST1ST_SHIFT                           3
-#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK                            BITFIELD(3, 3)
+#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK                            (1 << 3)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_EMULATION_SEQ2_RST2ST_SHIFT                           4
-#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK                            BITFIELD(4, 4)
+#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK                            (1 << 4)
 
 /* Used by PM_EMU_PWRSTCTRL */
 #define OMAP4430_EMU_BANK_ONSTATE_SHIFT                                        16
-#define OMAP4430_EMU_BANK_ONSTATE_MASK                                 BITFIELD(16, 17)
+#define OMAP4430_EMU_BANK_ONSTATE_MASK                                 (0x3 << 16)
 
 /* Used by PM_EMU_PWRSTST */
 #define OMAP4430_EMU_BANK_STATEST_SHIFT                                        4
-#define OMAP4430_EMU_BANK_STATEST_MASK                                 BITFIELD(4, 5)
-
-/*
- * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
- * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP
- */
-#define OMAP4430_ENABLE_RTA_EXPORT_SHIFT                               0
-#define OMAP4430_ENABLE_RTA_EXPORT_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_EMU_BANK_STATEST_MASK                                 (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC1_SHIFT                                         3
-#define OMAP4430_ENFUNC1_MASK                                          BITFIELD(3, 3)
+#define OMAP4430_ENFUNC1_EXPORT_SHIFT                                  3
+#define OMAP4430_ENFUNC1_EXPORT_MASK                                   (1 << 3)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC3_SHIFT                                         5
-#define OMAP4430_ENFUNC3_MASK                                          BITFIELD(5, 5)
+#define OMAP4430_ENFUNC3_EXPORT_SHIFT                                  5
+#define OMAP4430_ENFUNC3_EXPORT_MASK                                   (1 << 5)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC4_SHIFT                                         6
-#define OMAP4430_ENFUNC4_MASK                                          BITFIELD(6, 6)
+#define OMAP4430_ENFUNC4_MASK                                          (1 << 6)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC5_SHIFT                                         7
-#define OMAP4430_ENFUNC5_MASK                                          BITFIELD(7, 7)
+#define OMAP4430_ENFUNC5_MASK                                          (1 << 7)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERRORGAIN_SHIFT                                       16
-#define OMAP4430_ERRORGAIN_MASK                                                BITFIELD(16, 23)
+#define OMAP4430_ERRORGAIN_MASK                                                (0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERROROFFSET_SHIFT                                     24
-#define OMAP4430_ERROROFFSET_MASK                                      BITFIELD(24, 31)
+#define OMAP4430_ERROROFFSET_MASK                                      (0xff << 24)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_EXTERNAL_WARM_RST_SHIFT                               5
-#define OMAP4430_EXTERNAL_WARM_RST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_EXTERNAL_WARM_RST_MASK                                        (1 << 5)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_FORCEUPDATE_SHIFT                                     1
-#define OMAP4430_FORCEUPDATE_MASK                                      BITFIELD(1, 1)
+#define OMAP4430_FORCEUPDATE_MASK                                      (1 << 1)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_FORCEUPDATEWAIT_SHIFT                                 8
-#define OMAP4430_FORCEUPDATEWAIT_MASK                                  BITFIELD(8, 31)
+#define OMAP4430_FORCEUPDATEWAIT_MASK                                  (0xffffff << 8)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_TESLA */
 #define OMAP4430_FORCEWKUP_EN_SHIFT                                    10
-#define OMAP4430_FORCEWKUP_EN_MASK                                     BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_EN_MASK                                     (1 << 10)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_FORCEWKUP_ST_SHIFT                                    10
-#define OMAP4430_FORCEWKUP_ST_MASK                                     BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_ST_MASK                                     (1 << 10)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_FUNC_SHIFT                                            16
+#define OMAP4430_FUNC_MASK                                             (0xfff << 16)
 
 /* Used by PM_GFX_PWRSTCTRL */
 #define OMAP4430_GFX_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_GFX_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_GFX_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_GFX_PWRSTST */
 #define OMAP4430_GFX_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_GFX_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_GFX_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_COLD_RST_SHIFT                                 0
-#define OMAP4430_GLOBAL_COLD_RST_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_GLOBAL_COLD_RST_MASK                                  (1 << 0)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT                              1
-#define OMAP4430_GLOBAL_WARM_SW_RST_MASK                               BITFIELD(1, 1)
+#define OMAP4430_GLOBAL_WARM_SW_RST_MASK                               (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_GLOBAL_WUEN_SHIFT                                     16
-#define OMAP4430_GLOBAL_WUEN_MASK                                      BITFIELD(16, 16)
+#define OMAP4430_GLOBAL_WUEN_MASK                                      (1 << 16)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMCODE_SHIFT                                         0
-#define OMAP4430_HSMCODE_MASK                                          BITFIELD(0, 2)
+#define OMAP4430_HSMCODE_MASK                                          (0x7 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMODEEN_SHIFT                                                3
-#define OMAP4430_HSMODEEN_MASK                                         BITFIELD(3, 3)
+#define OMAP4430_HSMODEEN_MASK                                         (1 << 3)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLH_SHIFT                                          16
-#define OMAP4430_HSSCLH_MASK                                           BITFIELD(16, 23)
+#define OMAP4430_HSSCLH_MASK                                           (0xff << 16)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLL_SHIFT                                          24
-#define OMAP4430_HSSCLL_MASK                                           BITFIELD(24, 31)
+#define OMAP4430_HSSCLL_MASK                                           (0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_HWA_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_HWA_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_HWA_MEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_HWA_MEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_HWA_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_HWA_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_HWA_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_ICECRUSHER_MPU_RST_SHIFT                              1
-#define OMAP4430_ICECRUSHER_MPU_RST_MASK                               BITFIELD(1, 1)
+#define OMAP4430_ICECRUSHER_MPU_RST_MASK                               (1 << 1)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST1ST_SHIFT                               5
-#define OMAP4430_ICECRUSHER_RST1ST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_RST1ST_MASK                                        (1 << 5)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST2ST_SHIFT                               6
-#define OMAP4430_ICECRUSHER_RST2ST_MASK                                        BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_RST2ST_MASK                                        (1 << 6)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ1_RST1ST_SHIFT                          5
-#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK                           BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK                           (1 << 5)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ2_RST2ST_SHIFT                          6
-#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK                           BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK                           (1 << 6)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_ICEPICK_RST_SHIFT                                     9
-#define OMAP4430_ICEPICK_RST_MASK                                      BITFIELD(9, 9)
+#define OMAP4430_ICEPICK_RST_MASK                                      (1 << 9)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVDD_SHIFT                                         2
-#define OMAP4430_INITVDD_MASK                                          BITFIELD(2, 2)
+#define OMAP4430_INITVDD_MASK                                          (1 << 2)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVOLTAGE_SHIFT                                     8
-#define OMAP4430_INITVOLTAGE_MASK                                      BITFIELD(8, 15)
+#define OMAP4430_INITVOLTAGE_MASK                                      (0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_INTRANSITION_SHIFT                                    20
-#define OMAP4430_INTRANSITION_MASK                                     BITFIELD(20, 20)
+#define OMAP4430_INTRANSITION_MASK                                     (1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_IO_EN_SHIFT                                           9
-#define OMAP4430_IO_EN_MASK                                            BITFIELD(9, 9)
+#define OMAP4430_IO_EN_MASK                                            (1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_IO_ON_STATUS_SHIFT                                    5
-#define OMAP4430_IO_ON_STATUS_MASK                                     BITFIELD(5, 5)
+#define OMAP4430_IO_ON_STATUS_MASK                                     (1 << 5)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_IO_ST_SHIFT                                           9
-#define OMAP4430_IO_ST_MASK                                            BITFIELD(9, 9)
+#define OMAP4430_IO_ST_MASK                                            (1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_OVERRIDE_SHIFT                                 0
-#define OMAP4430_ISOCLK_OVERRIDE_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_ISOCLK_OVERRIDE_MASK                                  (1 << 0)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_STATUS_SHIFT                                   1
-#define OMAP4430_ISOCLK_STATUS_MASK                                    BITFIELD(1, 1)
+#define OMAP4430_ISOCLK_STATUS_MASK                                    (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOOVR_EXTEND_SHIFT                                   4
-#define OMAP4430_ISOOVR_EXTEND_MASK                                    BITFIELD(4, 4)
+#define OMAP4430_ISOOVR_EXTEND_MASK                                    (1 << 4)
 
 /* Used by PRM_IO_COUNT */
 #define OMAP4430_ISO_2_ON_TIME_SHIFT                                   0
-#define OMAP4430_ISO_2_ON_TIME_MASK                                    BITFIELD(0, 7)
+#define OMAP4430_ISO_2_ON_TIME_MASK                                    (0xff << 0)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_ONSTATE_SHIFT                            16
-#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK                             BITFIELD(16, 17)
+#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK                             (0x3 << 16)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_RETSTATE_SHIFT                           8
-#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK                            BITFIELD(8, 8)
+#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK                            (1 << 8)
 
 /* Used by PM_L3INIT_PWRSTST */
 #define OMAP4430_L3INIT_BANK1_STATEST_SHIFT                            4
-#define OMAP4430_L3INIT_BANK1_STATEST_MASK                             BITFIELD(4, 5)
+#define OMAP4430_L3INIT_BANK1_STATEST_MASK                             (0x3 << 4)
+
+/*
+ * Used by PM_ABE_PWRSTST, PM_CORE_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
+ */
+#define OMAP4430_LASTPOWERSTATEENTERED_SHIFT                           24
+#define OMAP4430_LASTPOWERSTATEENTERED_MASK                            (0x3 << 24)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL,
- * PM_MPU_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL,
- * PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOGICRETSTATE_SHIFT                                   2
-#define OMAP4430_LOGICRETSTATE_MASK                                    BITFIELD(2, 2)
+#define OMAP4430_LOGICRETSTATE_MASK                                    (1 << 2)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_LOGICSTATEST_SHIFT                                    2
-#define OMAP4430_LOGICSTATEST_MASK                                     BITFIELD(2, 2)
+#define OMAP4430_LOGICSTATEST_MASK                                     (1 << 2)
 
 /*
- * Used by RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT,
- * RM_WKUP_L4WKUP_CONTEXT, RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT,
- * RM_WKUP_SYNCTIMER_CONTEXT, RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT,
- * RM_WKUP_USIM_CONTEXT, RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT,
- * RM_EMU_DEBUGSS_CONTEXT, RM_D2D_SAD2D_CONTEXT, RM_D2D_SAD2D_FW_CONTEXT,
- * RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
- * RM_L3INSTR_L3_INSTR_CONTEXT, RM_L3INSTR_OCP_WP1_CONTEXT,
- * RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT, RM_L3_2_OCMC_RAM_CONTEXT,
- * RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT, RM_MEMIF_DLL_CONTEXT,
- * RM_MEMIF_DLL_H_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT,
- * RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
- * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
- * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
- * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
- * RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
+ * Used by RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
  * RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT, RM_ABE_MCBSP3_CONTEXT,
  * RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT, RM_ABE_TIMER5_CONTEXT,
  * RM_ABE_TIMER6_CONTEXT, RM_ABE_TIMER7_CONTEXT, RM_ABE_TIMER8_CONTEXT,
- * RM_ABE_WDT3_CONTEXT, RM_GFX_GFX_CONTEXT, RM_MPU_MPU_CONTEXT,
- * RM_CEFUSE_CEFUSE_CONTEXT, RM_ALWON_MDMINTC_CONTEXT,
- * RM_ALWON_SR_CORE_CONTEXT, RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT,
- * RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT, RM_L4PER_ADC_CONTEXT,
- * RM_L4PER_DMTIMER10_CONTEXT, RM_L4PER_DMTIMER11_CONTEXT,
- * RM_L4PER_DMTIMER2_CONTEXT, RM_L4PER_DMTIMER3_CONTEXT,
- * RM_L4PER_DMTIMER4_CONTEXT, RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT,
- * RM_L4PER_HDQ1W_CONTEXT, RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
- * RM_L4PER_I2C2_CONTEXT, RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT,
- * RM_L4PER_I2C5_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT,
- * RM_L4PER_MCASP3_CONTEXT, RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT,
- * RM_L4PER_MCSPI2_CONTEXT, RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT,
- * RM_L4PER_MGATE_CONTEXT, RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT,
- * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_MSPROHG_CONTEXT,
- * RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT,
- * RM_TESLA_TESLA_CONTEXT, RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT
+ * RM_ABE_WDT3_CONTEXT, RM_ALWON_MDMINTC_CONTEXT, RM_ALWON_SR_CORE_CONTEXT,
+ * RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT, RM_CAM_FDIF_CONTEXT,
+ * RM_CAM_ISS_CONTEXT, RM_CEFUSE_CEFUSE_CONTEXT, RM_D2D_SAD2D_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT,
+ * RM_DUCATI_DUCATI_CONTEXT, RM_EMU_DEBUGSS_CONTEXT, RM_GFX_GFX_CONTEXT,
+ * RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
+ * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
+ * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
+ * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
+ * RM_L3INSTR_L3_3_CONTEXT, RM_L3INSTR_L3_INSTR_CONTEXT,
+ * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT,
+ * RM_L3_2_OCMC_RAM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT,
+ * RM_L4PER_ADC_CONTEXT, RM_L4PER_DMTIMER10_CONTEXT,
+ * RM_L4PER_DMTIMER11_CONTEXT, RM_L4PER_DMTIMER2_CONTEXT,
+ * RM_L4PER_DMTIMER3_CONTEXT, RM_L4PER_DMTIMER4_CONTEXT,
+ * RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT, RM_L4PER_HDQ1W_CONTEXT,
+ * RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT, RM_L4PER_I2C2_CONTEXT,
+ * RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT, RM_L4PER_I2C5_CONTEXT,
+ * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT, RM_L4PER_MCASP3_CONTEXT,
+ * RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT, RM_L4PER_MCSPI2_CONTEXT,
+ * RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT, RM_L4PER_MGATE_CONTEXT,
+ * RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT, RM_L4PER_MMCSD5_CONTEXT,
+ * RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT,
+ * RM_L4SEC_PKAEIP29_CONTEXT, RM_MEMIF_DLL_CONTEXT, RM_MEMIF_DLL_H_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MPU_MPU_CONTEXT, RM_TESLA_TESLA_CONTEXT,
+ * RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT, RM_WKUP_L4WKUP_CONTEXT,
+ * RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT, RM_WKUP_SYNCTIMER_CONTEXT,
+ * RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT, RM_WKUP_USIM_CONTEXT,
+ * RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_DFF_SHIFT                                 0
-#define OMAP4430_LOSTCONTEXT_DFF_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_LOSTCONTEXT_DFF_MASK                                  (1 << 0)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_D2D_SAD2D_CONTEXT,
- * RM_D2D_SAD2D_FW_CONTEXT, RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DSS_CONTEXT, RM_DUCATI_DUCATI_CONTEXT,
+ * RM_L3INIT_HSI_CONTEXT, RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT,
+ * RM_L3INIT_MMC6_CONTEXT, RM_L3INIT_USB_HOST_CONTEXT,
+ * RM_L3INIT_USB_HOST_FS_CONTEXT, RM_L3INIT_USB_OTG_CONTEXT,
+ * RM_L3INIT_USB_TLL_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
  * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_GPMC_CONTEXT,
  * RM_L3_2_L3_2_CONTEXT, RM_L4CFG_HW_SEM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT,
- * RM_L4CFG_MAILBOX_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT,
- * RM_MEMIF_EMIF_2_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
- * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_L3INIT_HSI_CONTEXT,
- * RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT, RM_L3INIT_MMC6_CONTEXT,
- * RM_L3INIT_USB_HOST_CONTEXT, RM_L3INIT_USB_HOST_FS_CONTEXT,
- * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_USB_TLL_CONTEXT, RM_DSS_DSS_CONTEXT,
- * RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT, RM_L4PER_GPIO4_CONTEXT,
- * RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT, RM_L4PER_I2C1_CONTEXT,
- * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT, RM_L4PER_UART2_CONTEXT,
- * RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT, RM_L4SEC_AES1_CONTEXT,
- * RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT, RM_L4SEC_DES3DES_CONTEXT,
- * RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT, RM_TESLA_TESLA_CONTEXT
+ * RM_L4CFG_MAILBOX_CONTEXT, RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT,
+ * RM_L4PER_GPIO4_CONTEXT, RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT,
+ * RM_L4PER_I2C1_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT,
+ * RM_L4PER_UART2_CONTEXT, RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT,
+ * RM_L4SEC_AES1_CONTEXT, RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT,
+ * RM_L4SEC_DES3DES_CONTEXT, RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
+ * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_TESLA_TESLA_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_RFF_SHIFT                                 1
-#define OMAP4430_LOSTCONTEXT_RFF_MASK                                  BITFIELD(1, 1)
+#define OMAP4430_LOSTCONTEXT_RFF_MASK                                  (1 << 1)
 
 /* Used by RM_ABE_AESS_CONTEXT */
 #define OMAP4430_LOSTMEM_AESSMEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_AESSMEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_AESSMEM_MASK                                  (1 << 8)
 
 /* Used by RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT */
 #define OMAP4430_LOSTMEM_CAM_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_CAM_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CAM_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_L3INSTR_OCP_WP1_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_SHIFT                          8
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK                           BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK                           (1 << 8)
 
 /* Renamed from LOSTMEM_CORE_NRET_BANK Used by RM_MEMIF_DMM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_SHIFT                      9
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK                       BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK                       (1 << 9)
 
 /* Used by RM_L3_2_OCMC_RAM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_OCMRAM_SHIFT                             8
-#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK                              BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK                              (1 << 8)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_MEMIF_DMM_CONTEXT,
  * RM_SDMA_SDMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_CORE_OTHER_BANK_SHIFT                         8
-#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK                          BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK                          (1 << 8)
 
 /* Used by RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT */
 #define OMAP4430_LOSTMEM_DSS_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_DSS_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DSS_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_L2RAM_SHIFT                            9
-#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK                             BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK                             (1 << 9)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_UNICACHE_SHIFT                         8
-#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK                          BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK                          (1 << 8)
 
 /* Used by RM_EMU_DEBUGSS_CONTEXT */
 #define OMAP4430_LOSTMEM_EMU_BANK_SHIFT                                        8
-#define OMAP4430_LOSTMEM_EMU_BANK_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_EMU_BANK_MASK                                 (1 << 8)
 
 /* Used by RM_GFX_GFX_CONTEXT */
 #define OMAP4430_LOSTMEM_GFX_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_GFX_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_GFX_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_HWA_MEM_SHIFT                                 10
-#define OMAP4430_LOSTMEM_HWA_MEM_MASK                                  BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_HWA_MEM_MASK                                  (1 << 10)
 
 /*
  * Used by RM_L3INIT_CCPTX_CONTEXT, RM_L3INIT_EMAC_CONTEXT,
  * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_XHPI_CONTEXT
  */
 #define OMAP4430_LOSTMEM_L3INIT_BANK1_SHIFT                            8
-#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK                             BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK                             (1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L1_SHIFT                                  8
-#define OMAP4430_LOSTMEM_MPU_L1_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_MPU_L1_MASK                                   (1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L2_SHIFT                                  9
-#define OMAP4430_LOSTMEM_MPU_L2_MASK                                   BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_MPU_L2_MASK                                   (1 << 9)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_RAM_SHIFT                                 10
-#define OMAP4430_LOSTMEM_MPU_RAM_MASK                                  BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_MPU_RAM_MASK                                  (1 << 10)
 
 /*
  * Used by RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
  * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT
  */
 #define OMAP4430_LOSTMEM_NONRETAINED_BANK_SHIFT                                8
-#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK                         BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK                         (1 << 8)
 
 /*
  * Used by RM_ABE_DMIC_CONTEXT, RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT,
  * RM_ABE_MCBSP3_CONTEXT, RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT
  */
 #define OMAP4430_LOSTMEM_PERIHPMEM_SHIFT                               8
-#define OMAP4430_LOSTMEM_PERIHPMEM_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_PERIHPMEM_MASK                                        (1 << 8)
 
 /*
  * Used by RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_UART1_CONTEXT,
  * RM_L4SEC_CRYPTODMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_RETAINED_BANK_SHIFT                           8
-#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK                            BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK                            (1 << 8)
 
 /* Used by RM_IVAHD_SL2_CONTEXT */
 #define OMAP4430_LOSTMEM_SL2_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_SL2_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_SL2_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM1_MEM_SHIFT                                        8
-#define OMAP4430_LOSTMEM_TCM1_MEM_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TCM1_MEM_MASK                                 (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM2_MEM_SHIFT                                        9
-#define OMAP4430_LOSTMEM_TCM2_MEM_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TCM2_MEM_MASK                                 (1 << 9)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_EDMA_SHIFT                              10
-#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK                               BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK                               (1 << 10)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L1_SHIFT                                        8
-#define OMAP4430_LOSTMEM_TESLA_L1_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TESLA_L1_MASK                                 (1 << 8)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L2_SHIFT                                        9
-#define OMAP4430_LOSTMEM_TESLA_L2_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TESLA_L2_MASK                                 (1 << 9)
 
 /* Used by RM_WKUP_SARRAM_CONTEXT */
 #define OMAP4430_LOSTMEM_WKUP_BANK_SHIFT                               8
-#define OMAP4430_LOSTMEM_WKUP_BANK_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_WKUP_BANK_MASK                                        (1 << 8)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_L3INIT_PWRSTCTRL,
- * PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
- * PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_IVAHD_PWRSTCTRL,
+ * PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOWPOWERSTATECHANGE_SHIFT                             4
-#define OMAP4430_LOWPOWERSTATECHANGE_MASK                              BITFIELD(4, 4)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_MEMORYCHANGE_SHIFT                                    3
-#define OMAP4430_MEMORYCHANGE_MASK                                     BITFIELD(3, 3)
+#define OMAP4430_LOWPOWERSTATECHANGE_MASK                              (1 << 4)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_READY_SHIFT                                     1
-#define OMAP4430_MODEM_READY_MASK                                      BITFIELD(1, 1)
+#define OMAP4430_MODEM_READY_MASK                                      (1 << 1)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SHUTDOWN_IRQ_SHIFT                              9
-#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK                               BITFIELD(9, 9)
+#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK                               (1 << 9)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SLEEP_ST_SHIFT                                  16
-#define OMAP4430_MODEM_SLEEP_ST_MASK                                   BITFIELD(16, 16)
+#define OMAP4430_MODEM_SLEEP_ST_MASK                                   (1 << 16)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_WAKE_IRQ_SHIFT                                  8
-#define OMAP4430_MODEM_WAKE_IRQ_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_MODEM_WAKE_IRQ_MASK                                   (1 << 8)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_ONSTATE_SHIFT                                  16
-#define OMAP4430_MPU_L1_ONSTATE_MASK                                   BITFIELD(16, 17)
+#define OMAP4430_MPU_L1_ONSTATE_MASK                                   (0x3 << 16)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_RETSTATE_SHIFT                                 8
-#define OMAP4430_MPU_L1_RETSTATE_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_MPU_L1_RETSTATE_MASK                                  (1 << 8)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L1_STATEST_SHIFT                                  4
-#define OMAP4430_MPU_L1_STATEST_MASK                                   BITFIELD(4, 5)
+#define OMAP4430_MPU_L1_STATEST_MASK                                   (0x3 << 4)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_ONSTATE_SHIFT                                  18
-#define OMAP4430_MPU_L2_ONSTATE_MASK                                   BITFIELD(18, 19)
+#define OMAP4430_MPU_L2_ONSTATE_MASK                                   (0x3 << 18)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_RETSTATE_SHIFT                                 9
-#define OMAP4430_MPU_L2_RETSTATE_MASK                                  BITFIELD(9, 9)
+#define OMAP4430_MPU_L2_RETSTATE_MASK                                  (1 << 9)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L2_STATEST_SHIFT                                  6
-#define OMAP4430_MPU_L2_STATEST_MASK                                   BITFIELD(6, 7)
+#define OMAP4430_MPU_L2_STATEST_MASK                                   (0x3 << 6)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_ONSTATE_SHIFT                                 20
-#define OMAP4430_MPU_RAM_ONSTATE_MASK                                  BITFIELD(20, 21)
+#define OMAP4430_MPU_RAM_ONSTATE_MASK                                  (0x3 << 20)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_RETSTATE_SHIFT                                        10
-#define OMAP4430_MPU_RAM_RETSTATE_MASK                                 BITFIELD(10, 10)
+#define OMAP4430_MPU_RAM_RETSTATE_MASK                                 (1 << 10)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_RAM_STATEST_SHIFT                                 8
-#define OMAP4430_MPU_RAM_STATEST_MASK                                  BITFIELD(8, 9)
+#define OMAP4430_MPU_RAM_STATEST_MASK                                  (0x3 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT                           2
-#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK                            BITFIELD(2, 2)
+#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK                            (1 << 2)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_WDT_RST_SHIFT                                     3
-#define OMAP4430_MPU_WDT_RST_MASK                                      BITFIELD(3, 3)
+#define OMAP4430_MPU_WDT_RST_MASK                                      (1 << 3)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_ONSTATE_SHIFT                                18
-#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK                         BITFIELD(18, 19)
+#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK                         (0x3 << 18)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_RETSTATE_SHIFT                       9
-#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK                                BITFIELD(9, 9)
+#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK                                (1 << 9)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_NONRETAINED_BANK_STATEST_SHIFT                                6
-#define OMAP4430_NONRETAINED_BANK_STATEST_MASK                         BITFIELD(6, 7)
+#define OMAP4430_NONRETAINED_BANK_STATEST_MASK                         (0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_ONSTATE_SHIFT                           24
-#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK                            BITFIELD(24, 25)
+#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK                            (0x3 << 24)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_RETSTATE_SHIFT                          12
-#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK                           BITFIELD(12, 12)
+#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK                           (1 << 12)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_OCP_NRET_BANK_STATEST_SHIFT                           12
-#define OMAP4430_OCP_NRET_BANK_STATEST_MASK                            BITFIELD(12, 13)
+#define OMAP4430_OCP_NRET_BANK_STATEST_MASK                            (0x3 << 12)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_OFF_SHIFT                                             0
-#define OMAP4430_OFF_MASK                                              BITFIELD(0, 7)
-
-/* Used by PRM_LDO_BANDGAP_CTRL */
-#define OMAP4430_OFF_ENABLE_SHIFT                                      0
-#define OMAP4430_OFF_ENABLE_MASK                                       BITFIELD(0, 0)
+#define OMAP4430_OFF_MASK                                              (0xff << 0)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ON_SHIFT                                              24
-#define OMAP4430_ON_MASK                                               BITFIELD(24, 31)
+#define OMAP4430_ON_MASK                                               (0xff << 24)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ONLP_SHIFT                                            16
-#define OMAP4430_ONLP_MASK                                             BITFIELD(16, 23)
+#define OMAP4430_ONLP_MASK                                             (0xff << 16)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_CHANGE_SHIFT                                      2
-#define OMAP4430_OPP_CHANGE_MASK                                       BITFIELD(2, 2)
+#define OMAP4430_OPP_CHANGE_MASK                                       (1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_SEL_SHIFT                                         0
-#define OMAP4430_OPP_SEL_MASK                                          BITFIELD(0, 1)
+#define OMAP4430_OPP_SEL_MASK                                          (0x3 << 0)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_PCHARGECNT_VALUE_SHIFT                                        0
-#define OMAP4430_PCHARGECNT_VALUE_MASK                                 BITFIELD(0, 5)
+#define OMAP4430_PCHARGECNT_VALUE_MASK                                 (0x3f << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PCHARGE_TIME_SHIFT                                    0
-#define OMAP4430_PCHARGE_TIME_MASK                                     BITFIELD(0, 7)
+#define OMAP4430_PCHARGE_TIME_MASK                                     (0xff << 0)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_ONSTATE_SHIFT                               20
-#define OMAP4430_PERIPHMEM_ONSTATE_MASK                                        BITFIELD(20, 21)
+#define OMAP4430_PERIPHMEM_ONSTATE_MASK                                        (0x3 << 20)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_RETSTATE_SHIFT                              10
-#define OMAP4430_PERIPHMEM_RETSTATE_MASK                               BITFIELD(10, 10)
+#define OMAP4430_PERIPHMEM_RETSTATE_MASK                               (1 << 10)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_PERIPHMEM_STATEST_SHIFT                               8
-#define OMAP4430_PERIPHMEM_STATEST_MASK                                        BITFIELD(8, 9)
+#define OMAP4430_PERIPHMEM_STATEST_MASK                                        (0x3 << 8)
 
 /* Used by PRM_PHASE1_CNDP */
 #define OMAP4430_PHASE1_CNDP_SHIFT                                     0
-#define OMAP4430_PHASE1_CNDP_MASK                                      BITFIELD(0, 31)
+#define OMAP4430_PHASE1_CNDP_MASK                                      (0xffffffff << 0)
 
 /* Used by PRM_PHASE2A_CNDP */
 #define OMAP4430_PHASE2A_CNDP_SHIFT                                    0
-#define OMAP4430_PHASE2A_CNDP_MASK                                     BITFIELD(0, 31)
+#define OMAP4430_PHASE2A_CNDP_MASK                                     (0xffffffff << 0)
 
 /* Used by PRM_PHASE2B_CNDP */
 #define OMAP4430_PHASE2B_CNDP_SHIFT                                    0
-#define OMAP4430_PHASE2B_CNDP_MASK                                     BITFIELD(0, 31)
+#define OMAP4430_PHASE2B_CNDP_MASK                                     (0xffffffff << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PONOUT_2_PGOODIN_TIME_SHIFT                           8
-#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK                            BITFIELD(8, 15)
+#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK                            (0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL,
- * PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL,
- * PM_CEFUSE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
- * PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_EMU_PWRSTCTRL, PM_GFX_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_POWERSTATE_SHIFT                                      0
-#define OMAP4430_POWERSTATE_MASK                                       BITFIELD(0, 1)
+#define OMAP4430_POWERSTATE_MASK                                       (0x3 << 0)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_POWERSTATEST_SHIFT                                    0
-#define OMAP4430_POWERSTATEST_MASK                                     BITFIELD(0, 1)
+#define OMAP4430_POWERSTATEST_MASK                                     (0x3 << 0)
 
 /* Used by PRM_PWRREQCTRL */
 #define OMAP4430_PWRREQ_COND_SHIFT                                     0
-#define OMAP4430_PWRREQ_COND_MASK                                      BITFIELD(0, 1)
+#define OMAP4430_PWRREQ_COND_MASK                                      (0x3 << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_CORE_L_SHIFT                                        3
-#define OMAP4430_RACEN_VDD_CORE_L_MASK                                 BITFIELD(3, 3)
+#define OMAP4430_RACEN_VDD_CORE_L_MASK                                 (1 << 3)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_IVA_L_SHIFT                                 11
-#define OMAP4430_RACEN_VDD_IVA_L_MASK                                  BITFIELD(11, 11)
+#define OMAP4430_RACEN_VDD_IVA_L_MASK                                  (1 << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_MPU_L_SHIFT                                 20
-#define OMAP4430_RACEN_VDD_MPU_L_MASK                                  BITFIELD(20, 20)
+#define OMAP4430_RACEN_VDD_MPU_L_MASK                                  (1 << 20)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_CORE_L_SHIFT                                  2
-#define OMAP4430_RAC_VDD_CORE_L_MASK                                   BITFIELD(2, 2)
+#define OMAP4430_RAC_VDD_CORE_L_MASK                                   (1 << 2)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_IVA_L_SHIFT                                   10
-#define OMAP4430_RAC_VDD_IVA_L_MASK                                    BITFIELD(10, 10)
+#define OMAP4430_RAC_VDD_IVA_L_MASK                                    (1 << 10)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_MPU_L_SHIFT                                   19
-#define OMAP4430_RAC_VDD_MPU_L_MASK                                    BITFIELD(19, 19)
+#define OMAP4430_RAC_VDD_MPU_L_MASK                                    (1 << 19)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_COUNT_SHIFT                                 16
-#define OMAP4430_RAMP_DOWN_COUNT_MASK                                  BITFIELD(16, 21)
+#define OMAP4430_RAMP_DOWN_COUNT_MASK                                  (0x3f << 16)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_PRESCAL_SHIFT                               24
-#define OMAP4430_RAMP_DOWN_PRESCAL_MASK                                        BITFIELD(24, 25)
+#define OMAP4430_RAMP_DOWN_PRESCAL_MASK                                        (0x3 << 24)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_COUNT_SHIFT                                   0
-#define OMAP4430_RAMP_UP_COUNT_MASK                                    BITFIELD(0, 5)
+#define OMAP4430_RAMP_UP_COUNT_MASK                                    (0x3f << 0)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_PRESCAL_SHIFT                                 8
-#define OMAP4430_RAMP_UP_PRESCAL_MASK                                  BITFIELD(8, 9)
+#define OMAP4430_RAMP_UP_PRESCAL_MASK                                  (0x3 << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_CORE_L_SHIFT                                  1
-#define OMAP4430_RAV_VDD_CORE_L_MASK                                   BITFIELD(1, 1)
+#define OMAP4430_RAV_VDD_CORE_L_MASK                                   (1 << 1)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_IVA_L_SHIFT                                   9
-#define OMAP4430_RAV_VDD_IVA_L_MASK                                    BITFIELD(9, 9)
+#define OMAP4430_RAV_VDD_IVA_L_MASK                                    (1 << 9)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_MPU_L_SHIFT                                   18
-#define OMAP4430_RAV_VDD_MPU_L_MASK                                    BITFIELD(18, 18)
+#define OMAP4430_RAV_VDD_MPU_L_MASK                                    (1 << 18)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_REGADDR_SHIFT                                         8
-#define OMAP4430_REGADDR_MASK                                          BITFIELD(8, 15)
+#define OMAP4430_REGADDR_MASK                                          (0xff << 8)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_RET_SHIFT                                             8
-#define OMAP4430_RET_MASK                                              BITFIELD(8, 15)
+#define OMAP4430_RET_MASK                                              (0xff << 8)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_ONSTATE_SHIFT                           16
-#define OMAP4430_RETAINED_BANK_ONSTATE_MASK                            BITFIELD(16, 17)
+#define OMAP4430_RETAINED_BANK_ONSTATE_MASK                            (0x3 << 16)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_RETSTATE_SHIFT                          8
-#define OMAP4430_RETAINED_BANK_RETSTATE_MASK                           BITFIELD(8, 8)
+#define OMAP4430_RETAINED_BANK_RETSTATE_MASK                           (1 << 8)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_RETAINED_BANK_STATEST_SHIFT                           4
-#define OMAP4430_RETAINED_BANK_STATEST_MASK                            BITFIELD(4, 5)
+#define OMAP4430_RETAINED_BANK_STATEST_MASK                            (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_RETMODE_ENABLE_SHIFT                                  0
-#define OMAP4430_RETMODE_ENABLE_MASK                                   BITFIELD(0, 0)
+#define OMAP4430_RETMODE_ENABLE_MASK                                   (1 << 0)
 
-/* Used by REVISION_PRM */
-#define OMAP4430_REV_SHIFT                                             0
-#define OMAP4430_REV_MASK                                              BITFIELD(0, 7)
-
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST1_SHIFT                                            0
-#define OMAP4430_RST1_MASK                                             BITFIELD(0, 0)
+#define OMAP4430_RST1_MASK                                             (1 << 0)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST1ST_SHIFT                                          0
-#define OMAP4430_RST1ST_MASK                                           BITFIELD(0, 0)
+#define OMAP4430_RST1ST_MASK                                           (1 << 0)
 
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST2_SHIFT                                            1
-#define OMAP4430_RST2_MASK                                             BITFIELD(1, 1)
+#define OMAP4430_RST2_MASK                                             (1 << 1)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST2ST_SHIFT                                          1
-#define OMAP4430_RST2ST_MASK                                           BITFIELD(1, 1)
+#define OMAP4430_RST2ST_MASK                                           (1 << 1)
 
 /* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL */
 #define OMAP4430_RST3_SHIFT                                            2
-#define OMAP4430_RST3_MASK                                             BITFIELD(2, 2)
+#define OMAP4430_RST3_MASK                                             (1 << 2)
 
 /* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST */
 #define OMAP4430_RST3ST_SHIFT                                          2
-#define OMAP4430_RST3ST_MASK                                           BITFIELD(2, 2)
+#define OMAP4430_RST3ST_MASK                                           (1 << 2)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME1_SHIFT                                                0
-#define OMAP4430_RSTTIME1_MASK                                         BITFIELD(0, 9)
+#define OMAP4430_RSTTIME1_MASK                                         (0x3ff << 0)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME2_SHIFT                                                10
-#define OMAP4430_RSTTIME2_MASK                                         BITFIELD(10, 14)
+#define OMAP4430_RSTTIME2_MASK                                         (0x1f << 10)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_COLD_SW_SHIFT                              1
-#define OMAP4430_RST_GLOBAL_COLD_SW_MASK                               BITFIELD(1, 1)
+#define OMAP4430_RST_GLOBAL_COLD_SW_MASK                               (1 << 1)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_WARM_SW_SHIFT                              0
-#define OMAP4430_RST_GLOBAL_WARM_SW_MASK                               BITFIELD(0, 0)
+#define OMAP4430_RST_GLOBAL_WARM_SW_MASK                               (1 << 0)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_R_RTL_SHIFT                                           11
+#define OMAP4430_R_RTL_MASK                                            (0x1f << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_CORE_L_SHIFT                                   0
-#define OMAP4430_SA_VDD_CORE_L_MASK                                    BITFIELD(0, 0)
+#define OMAP4430_SA_VDD_CORE_L_MASK                                    (1 << 0)
 
 /* Renamed from SA_VDD_CORE_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_CORE_L_0_6_SHIFT                               0
-#define OMAP4430_SA_VDD_CORE_L_0_6_MASK                                        BITFIELD(0, 6)
+#define OMAP4430_SA_VDD_CORE_L_0_6_MASK                                        (0x7f << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_IVA_L_SHIFT                                    8
-#define OMAP4430_SA_VDD_IVA_L_MASK                                     BITFIELD(8, 8)
+#define OMAP4430_SA_VDD_IVA_L_MASK                                     (1 << 8)
 
 /* Renamed from SA_VDD_IVA_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT                     8
-#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK                      BITFIELD(8, 14)
+#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK                      (0x7f << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_MPU_L_SHIFT                                    16
-#define OMAP4430_SA_VDD_MPU_L_MASK                                     BITFIELD(16, 16)
+#define OMAP4430_SA_VDD_MPU_L_MASK                                     (1 << 16)
 
 /* Renamed from SA_VDD_MPU_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT                     16
-#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK                      BITFIELD(16, 22)
+#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK                      (0x7f << 16)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_SCHEME_SHIFT                                          30
+#define OMAP4430_SCHEME_MASK                                           (0x3 << 30)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLH_SHIFT                                            0
-#define OMAP4430_SCLH_MASK                                             BITFIELD(0, 7)
+#define OMAP4430_SCLH_MASK                                             (0xff << 0)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLL_SHIFT                                            8
-#define OMAP4430_SCLL_MASK                                             BITFIELD(8, 15)
+#define OMAP4430_SCLL_MASK                                             (0xff << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_SECURE_WDT_RST_SHIFT                                  4
-#define OMAP4430_SECURE_WDT_RST_MASK                                   BITFIELD(4, 4)
+#define OMAP4430_SECURE_WDT_RST_MASK                                   (1 << 4)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_ONSTATE_SHIFT                                 18
-#define OMAP4430_SL2_MEM_ONSTATE_MASK                                  BITFIELD(18, 19)
+#define OMAP4430_SL2_MEM_ONSTATE_MASK                                  (0x3 << 18)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_RETSTATE_SHIFT                                        9
-#define OMAP4430_SL2_MEM_RETSTATE_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_SL2_MEM_RETSTATE_MASK                                 (1 << 9)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_SL2_MEM_STATEST_SHIFT                                 6
-#define OMAP4430_SL2_MEM_STATEST_MASK                                  BITFIELD(6, 7)
+#define OMAP4430_SL2_MEM_STATEST_MASK                                  (0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_SLAVEADDR_SHIFT                                       0
-#define OMAP4430_SLAVEADDR_MASK                                                BITFIELD(0, 6)
+#define OMAP4430_SLAVEADDR_MASK                                                (0x7f << 0)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SLEEP_RBB_SEL_SHIFT                                   3
-#define OMAP4430_SLEEP_RBB_SEL_MASK                                    BITFIELD(3, 3)
+#define OMAP4430_SLEEP_RBB_SEL_MASK                                    (1 << 3)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_SLPCNT_VALUE_SHIFT                                    16
-#define OMAP4430_SLPCNT_VALUE_MASK                                     BITFIELD(16, 23)
+#define OMAP4430_SLPCNT_VALUE_MASK                                     (0xff << 16)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_SMPSWAITTIMEMAX_SHIFT                                 8
-#define OMAP4430_SMPSWAITTIMEMAX_MASK                                  BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMAX_MASK                                  (0xffff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_SMPSWAITTIMEMIN_SHIFT                                 8
-#define OMAP4430_SMPSWAITTIMEMIN_MASK                                  BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMIN_MASK                                  (0xffff << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_CORE_SHIFT                                        1
+#define OMAP4430_SMPS_RA_ERR_CORE_MASK                                 (1 << 1)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_IVA_SHIFT                                 9
+#define OMAP4430_SMPS_RA_ERR_IVA_MASK                                  (1 << 9)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_MPU_SHIFT                                 17
+#define OMAP4430_SMPS_RA_ERR_MPU_MASK                                  (1 << 17)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_CORE_SHIFT                                        0
+#define OMAP4430_SMPS_SA_ERR_CORE_MASK                                 (1 << 0)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_IVA_SHIFT                                 8
+#define OMAP4430_SMPS_SA_ERR_IVA_MASK                                  (1 << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_MPU_SHIFT                                 16
+#define OMAP4430_SMPS_SA_ERR_MPU_MASK                                  (1 << 16)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_SHIFT                           2
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_MASK                            (1 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_SHIFT                            10
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_MASK                             (1 << 10)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_SHIFT                            18
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_MASK                             (1 << 18)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2EN_SHIFT                                           0
-#define OMAP4430_SR2EN_MASK                                            BITFIELD(0, 0)
+#define OMAP4430_SR2EN_MASK                                            (1 << 0)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_IN_TRANSITION_SHIFT                               6
-#define OMAP4430_SR2_IN_TRANSITION_MASK                                        BITFIELD(6, 6)
+#define OMAP4430_SR2_IN_TRANSITION_MASK                                        (1 << 6)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_STATUS_SHIFT                                      3
-#define OMAP4430_SR2_STATUS_MASK                                       BITFIELD(3, 4)
+#define OMAP4430_SR2_STATUS_MASK                                       (0x3 << 3)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2_WTCNT_VALUE_SHIFT                                 8
-#define OMAP4430_SR2_WTCNT_VALUE_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_SR2_WTCNT_VALUE_MASK                                  (0xff << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAMLDO_STATUS_SHIFT                                  8
-#define OMAP4430_SRAMLDO_STATUS_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_SRAMLDO_STATUS_MASK                                   (1 << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAM_IN_TRANSITION_SHIFT                              9
-#define OMAP4430_SRAM_IN_TRANSITION_MASK                               BITFIELD(9, 9)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK                               (1 << 9)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_SRMODEEN_SHIFT                                                4
-#define OMAP4430_SRMODEEN_MASK                                         BITFIELD(4, 4)
+#define OMAP4430_SRMODEEN_MASK                                         (1 << 4)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_COUNT_SHIFT                                    0
-#define OMAP4430_STABLE_COUNT_MASK                                     BITFIELD(0, 5)
+#define OMAP4430_STABLE_COUNT_MASK                                     (0x3f << 0)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_PRESCAL_SHIFT                                  8
-#define OMAP4430_STABLE_PRESCAL_MASK                                   BITFIELD(8, 9)
+#define OMAP4430_STABLE_PRESCAL_MASK                                   (0x3 << 8)
+
+/* Used by PRM_LDO_BANDGAP_SETUP */
+#define OMAP4430_STARTUP_COUNT_SHIFT                                   0
+#define OMAP4430_STARTUP_COUNT_MASK                                    (0xff << 0)
+
+/* Renamed from STARTUP_COUNT Used by PRM_SRAM_COUNT */
+#define OMAP4430_STARTUP_COUNT_24_31_SHIFT                             24
+#define OMAP4430_STARTUP_COUNT_24_31_MASK                              (0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_ONSTATE_SHIFT                                        20
-#define OMAP4430_TCM1_MEM_ONSTATE_MASK                                 BITFIELD(20, 21)
+#define OMAP4430_TCM1_MEM_ONSTATE_MASK                                 (0x3 << 20)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_RETSTATE_SHIFT                               10
-#define OMAP4430_TCM1_MEM_RETSTATE_MASK                                        BITFIELD(10, 10)
+#define OMAP4430_TCM1_MEM_RETSTATE_MASK                                        (1 << 10)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM1_MEM_STATEST_SHIFT                                        8
-#define OMAP4430_TCM1_MEM_STATEST_MASK                                 BITFIELD(8, 9)
+#define OMAP4430_TCM1_MEM_STATEST_MASK                                 (0x3 << 8)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_ONSTATE_SHIFT                                        22
-#define OMAP4430_TCM2_MEM_ONSTATE_MASK                                 BITFIELD(22, 23)
+#define OMAP4430_TCM2_MEM_ONSTATE_MASK                                 (0x3 << 22)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_RETSTATE_SHIFT                               11
-#define OMAP4430_TCM2_MEM_RETSTATE_MASK                                        BITFIELD(11, 11)
+#define OMAP4430_TCM2_MEM_RETSTATE_MASK                                        (1 << 11)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM2_MEM_STATEST_SHIFT                                        10
-#define OMAP4430_TCM2_MEM_STATEST_MASK                                 BITFIELD(10, 11)
+#define OMAP4430_TCM2_MEM_STATEST_MASK                                 (0x3 << 10)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLASS_EMU_RSTST_SHIFT                               2
-#define OMAP4430_TESLASS_EMU_RSTST_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_TESLASS_EMU_RSTST_MASK                                        (1 << 2)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_SHIFT                         3
-#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK                          BITFIELD(3, 3)
+#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK                          (1 << 3)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_ONSTATE_SHIFT                              20
-#define OMAP4430_TESLA_EDMA_ONSTATE_MASK                               BITFIELD(20, 21)
+#define OMAP4430_TESLA_EDMA_ONSTATE_MASK                               (0x3 << 20)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_RETSTATE_SHIFT                             10
-#define OMAP4430_TESLA_EDMA_RETSTATE_MASK                              BITFIELD(10, 10)
+#define OMAP4430_TESLA_EDMA_RETSTATE_MASK                              (1 << 10)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_EDMA_STATEST_SHIFT                              8
-#define OMAP4430_TESLA_EDMA_STATEST_MASK                               BITFIELD(8, 9)
+#define OMAP4430_TESLA_EDMA_STATEST_MASK                               (0x3 << 8)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_ONSTATE_SHIFT                                        16
-#define OMAP4430_TESLA_L1_ONSTATE_MASK                                 BITFIELD(16, 17)
+#define OMAP4430_TESLA_L1_ONSTATE_MASK                                 (0x3 << 16)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_RETSTATE_SHIFT                               8
-#define OMAP4430_TESLA_L1_RETSTATE_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_TESLA_L1_RETSTATE_MASK                                        (1 << 8)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L1_STATEST_SHIFT                                        4
-#define OMAP4430_TESLA_L1_STATEST_MASK                                 BITFIELD(4, 5)
+#define OMAP4430_TESLA_L1_STATEST_MASK                                 (0x3 << 4)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_ONSTATE_SHIFT                                        18
-#define OMAP4430_TESLA_L2_ONSTATE_MASK                                 BITFIELD(18, 19)
+#define OMAP4430_TESLA_L2_ONSTATE_MASK                                 (0x3 << 18)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_RETSTATE_SHIFT                               9
-#define OMAP4430_TESLA_L2_RETSTATE_MASK                                        BITFIELD(9, 9)
+#define OMAP4430_TESLA_L2_RETSTATE_MASK                                        (1 << 9)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L2_STATEST_SHIFT                                        6
-#define OMAP4430_TESLA_L2_STATEST_MASK                                 BITFIELD(6, 7)
+#define OMAP4430_TESLA_L2_STATEST_MASK                                 (0x3 << 6)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_TIMEOUT_SHIFT                                         0
-#define OMAP4430_TIMEOUT_MASK                                          BITFIELD(0, 15)
+#define OMAP4430_TIMEOUT_MASK                                          (0xffff << 0)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_TIMEOUTEN_SHIFT                                       3
-#define OMAP4430_TIMEOUTEN_MASK                                                BITFIELD(3, 3)
+#define OMAP4430_TIMEOUTEN_MASK                                                (1 << 3)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_TRANSITION_EN_SHIFT                                   8
-#define OMAP4430_TRANSITION_EN_MASK                                    BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_EN_MASK                                    (1 << 8)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_TRANSITION_ST_SHIFT                                   8
-#define OMAP4430_TRANSITION_ST_MASK                                    BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_ST_MASK                                    (1 << 8)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_VALID_SHIFT                                           24
-#define OMAP4430_VALID_MASK                                            BITFIELD(24, 24)
+#define OMAP4430_VALID_MASK                                            (1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_BYPASSACK_EN_SHIFT                                 14
-#define OMAP4430_VC_BYPASSACK_EN_MASK                                  BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_EN_MASK                                  (1 << 14)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_BYPASSACK_ST_SHIFT                                 14
-#define OMAP4430_VC_BYPASSACK_ST_MASK                                  BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_ST_MASK                                  (1 << 14)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_VC_CORE_VPACK_EN_SHIFT                                        22
+#define OMAP4430_VC_CORE_VPACK_EN_MASK                                 (1 << 22)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_VC_CORE_VPACK_ST_SHIFT                                        22
+#define OMAP4430_VC_CORE_VPACK_ST_MASK                                 (1 << 22)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_IVA_VPACK_EN_SHIFT                                 30
-#define OMAP4430_VC_IVA_VPACK_EN_MASK                                  BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_EN_MASK                                  (1 << 30)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_IVA_VPACK_ST_SHIFT                                 30
-#define OMAP4430_VC_IVA_VPACK_ST_MASK                                  BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_ST_MASK                                  (1 << 30)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_EN_SHIFT                                 6
-#define OMAP4430_VC_MPU_VPACK_EN_MASK                                  BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_EN_MASK                                  (1 << 6)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_ST_SHIFT                                 6
-#define OMAP4430_VC_MPU_VPACK_ST_MASK                                  BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_ST_MASK                                  (1 << 6)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_RAERR_EN_SHIFT                                     12
-#define OMAP4430_VC_RAERR_EN_MASK                                      BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_EN_MASK                                      (1 << 12)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_RAERR_ST_SHIFT                                     12
-#define OMAP4430_VC_RAERR_ST_MASK                                      BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_ST_MASK                                      (1 << 12)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_SAERR_EN_SHIFT                                     11
-#define OMAP4430_VC_SAERR_EN_MASK                                      BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_EN_MASK                                      (1 << 11)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_SAERR_ST_SHIFT                                     11
-#define OMAP4430_VC_SAERR_ST_MASK                                      BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_ST_MASK                                      (1 << 11)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_TOERR_EN_SHIFT                                     13
-#define OMAP4430_VC_TOERR_EN_MASK                                      BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_EN_MASK                                      (1 << 13)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_TOERR_ST_SHIFT                                     13
-#define OMAP4430_VC_TOERR_ST_MASK                                      BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_ST_MASK                                      (1 << 13)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMAX_SHIFT                                          24
-#define OMAP4430_VDDMAX_MASK                                           BITFIELD(24, 31)
+#define OMAP4430_VDDMAX_MASK                                           (0xff << 24)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMIN_SHIFT                                          16
-#define OMAP4430_VDDMIN_MASK                                           BITFIELD(16, 23)
+#define OMAP4430_VDDMIN_MASK                                           (0xff << 16)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_CORE_I2C_DISABLE_SHIFT                            12
-#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK                             BITFIELD(12, 12)
+#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK                             (1 << 12)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT                           8
-#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK                            BITFIELD(8, 8)
+#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK                            (1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_I2C_DISABLE_SHIFT                             14
-#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK                              BITFIELD(14, 14)
+#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK                              (1 << 14)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_PRESENCE_SHIFT                                        9
-#define OMAP4430_VDD_IVA_PRESENCE_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_VDD_IVA_PRESENCE_MASK                                 (1 << 9)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT                            7
-#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK                             BITFIELD(7, 7)
+#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK                             (1 << 7)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_I2C_DISABLE_SHIFT                             13
-#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK                              BITFIELD(13, 13)
+#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK                              (1 << 13)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_PRESENCE_SHIFT                                        8
-#define OMAP4430_VDD_MPU_PRESENCE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_VDD_MPU_PRESENCE_MASK                                 (1 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT                            6
-#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK                             BITFIELD(6, 6)
+#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK                             (1 << 6)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_CORE_SHIFT                                        4
+#define OMAP4430_VFSM_RA_ERR_CORE_MASK                                 (1 << 4)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_IVA_SHIFT                                 12
+#define OMAP4430_VFSM_RA_ERR_IVA_MASK                                  (1 << 12)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_MPU_SHIFT                                 20
+#define OMAP4430_VFSM_RA_ERR_MPU_MASK                                  (1 << 20)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_CORE_SHIFT                                        3
+#define OMAP4430_VFSM_SA_ERR_CORE_MASK                                 (1 << 3)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_IVA_SHIFT                                 11
+#define OMAP4430_VFSM_SA_ERR_IVA_MASK                                  (1 << 11)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_MPU_SHIFT                                 19
+#define OMAP4430_VFSM_SA_ERR_MPU_MASK                                  (1 << 19)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_SHIFT                           5
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_MASK                            (1 << 5)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_SHIFT                            13
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_MASK                             (1 << 13)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_SHIFT                            21
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_MASK                             (1 << 21)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_CORE_L_SHIFT                                        0
-#define OMAP4430_VOLRA_VDD_CORE_L_MASK                                 BITFIELD(0, 7)
+#define OMAP4430_VOLRA_VDD_CORE_L_MASK                                 (0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_IVA_L_SHIFT                                 8
-#define OMAP4430_VOLRA_VDD_IVA_L_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_VOLRA_VDD_IVA_L_MASK                                  (0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_MPU_L_SHIFT                                 16
-#define OMAP4430_VOLRA_VDD_MPU_L_MASK                                  BITFIELD(16, 23)
+#define OMAP4430_VOLRA_VDD_MPU_L_MASK                                  (0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_VPENABLE_SHIFT                                                0
-#define OMAP4430_VPENABLE_MASK                                         BITFIELD(0, 0)
+#define OMAP4430_VPENABLE_MASK                                         (1 << 0)
 
 /* Used by PRM_VP_CORE_STATUS, PRM_VP_IVA_STATUS, PRM_VP_MPU_STATUS */
 #define OMAP4430_VPINIDLE_SHIFT                                                0
-#define OMAP4430_VPINIDLE_MASK                                         BITFIELD(0, 0)
+#define OMAP4430_VPINIDLE_MASK                                         (1 << 0)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_VPVOLTAGE_SHIFT                                       0
-#define OMAP4430_VPVOLTAGE_MASK                                                BITFIELD(0, 7)
+#define OMAP4430_VPVOLTAGE_MASK                                                (0xff << 0)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_EN_SHIFT                              20
-#define OMAP4430_VP_CORE_EQVALUE_EN_MASK                               BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_EN_MASK                               (1 << 20)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_ST_SHIFT                              20
-#define OMAP4430_VP_CORE_EQVALUE_ST_MASK                               BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_ST_MASK                               (1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_EN_SHIFT                               18
-#define OMAP4430_VP_CORE_MAXVDD_EN_MASK                                        BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_EN_MASK                                        (1 << 18)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_ST_SHIFT                               18
-#define OMAP4430_VP_CORE_MAXVDD_ST_MASK                                        BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_ST_MASK                                        (1 << 18)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MINVDD_EN_SHIFT                               17
-#define OMAP4430_VP_CORE_MINVDD_EN_MASK                                        BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_EN_MASK                                        (1 << 17)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MINVDD_ST_SHIFT                               17
-#define OMAP4430_VP_CORE_MINVDD_ST_MASK                                        BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_ST_MASK                                        (1 << 17)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_EN_SHIFT                            19
-#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK                             BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK                             (1 << 19)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_ST_SHIFT                            19
-#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK                             BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK                             (1 << 19)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_SHIFT                                16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK                         BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK                         (1 << 16)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_SHIFT                                16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK                         BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK                         (1 << 16)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_EN_SHIFT                            21
-#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK                             BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK                             (1 << 21)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_ST_SHIFT                            21
-#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK                             BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK                             (1 << 21)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_EN_SHIFT                               28
-#define OMAP4430_VP_IVA_EQVALUE_EN_MASK                                        BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_EN_MASK                                        (1 << 28)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_ST_SHIFT                               28
-#define OMAP4430_VP_IVA_EQVALUE_ST_MASK                                        BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_ST_MASK                                        (1 << 28)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_EN_SHIFT                                        26
-#define OMAP4430_VP_IVA_MAXVDD_EN_MASK                                 BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_EN_MASK                                 (1 << 26)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_ST_SHIFT                                        26
-#define OMAP4430_VP_IVA_MAXVDD_ST_MASK                                 BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_ST_MASK                                 (1 << 26)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MINVDD_EN_SHIFT                                        25
-#define OMAP4430_VP_IVA_MINVDD_EN_MASK                                 BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_EN_MASK                                 (1 << 25)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MINVDD_ST_SHIFT                                        25
-#define OMAP4430_VP_IVA_MINVDD_ST_MASK                                 BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_ST_MASK                                 (1 << 25)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_EN_SHIFT                             27
-#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK                              BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK                              (1 << 27)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_ST_SHIFT                             27
-#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK                              BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK                              (1 << 27)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_SHIFT                         24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK                          BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK                          (1 << 24)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_SHIFT                         24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK                          BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK                          (1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_EN_SHIFT                             29
-#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK                              BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK                              (1 << 29)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_ST_SHIFT                             29
-#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK                              BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK                              (1 << 29)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_EN_SHIFT                               4
-#define OMAP4430_VP_MPU_EQVALUE_EN_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_EN_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_ST_SHIFT                               4
-#define OMAP4430_VP_MPU_EQVALUE_ST_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_ST_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_EN_SHIFT                                        2
-#define OMAP4430_VP_MPU_MAXVDD_EN_MASK                                 BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_EN_MASK                                 (1 << 2)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_ST_SHIFT                                        2
-#define OMAP4430_VP_MPU_MAXVDD_ST_MASK                                 BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_ST_MASK                                 (1 << 2)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_EN_SHIFT                                        1
-#define OMAP4430_VP_MPU_MINVDD_EN_MASK                                 BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_EN_MASK                                 (1 << 1)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_ST_SHIFT                                        1
-#define OMAP4430_VP_MPU_MINVDD_ST_MASK                                 BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_ST_MASK                                 (1 << 1)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_EN_SHIFT                             3
-#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK                              BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK                              (1 << 3)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_ST_SHIFT                             3
-#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK                              BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK                              (1 << 3)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_SHIFT                         0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK                          BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK                          (1 << 0)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_SHIFT                         0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK                          BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK                          (1 << 0)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_EN_SHIFT                             5
-#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK                              BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK                              (1 << 5)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_ST_SHIFT                             5
-#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK                              BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK                              (1 << 5)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_VSETUPCNT_VALUE_SHIFT                                 8
-#define OMAP4430_VSETUPCNT_VALUE_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_VSETUPCNT_VALUE_MASK                                  (0xff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_VSTEPMAX_SHIFT                                                0
-#define OMAP4430_VSTEPMAX_MASK                                         BITFIELD(0, 7)
+#define OMAP4430_VSTEPMAX_MASK                                         (0xff << 0)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_VSTEPMIN_SHIFT                                                0
-#define OMAP4430_VSTEPMIN_MASK                                         BITFIELD(0, 7)
+#define OMAP4430_VSTEPMIN_MASK                                         (0xff << 0)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_WAKE_MODEM_SHIFT                                      0
-#define OMAP4430_WAKE_MODEM_MASK                                       BITFIELD(0, 0)
+#define OMAP4430_WAKE_MODEM_MASK                                       (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_DUCATI_SHIFT                            1
-#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK                             BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK                             (1 << 1)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_DISPC_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DISPC_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_TESLA_SHIFT                             2
-#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK                              BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK                              (1 << 2)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_SHIFT                          6
-#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK                           BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK                           (1 << 6)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_SHIFT                          2
-#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK                           BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK                           (1 << 2)
 
 /* Used by PM_L4PER_DMTIMER10_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER10_MPU_SHIFT                           0
-#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK                            BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK                            (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_SHIFT                                1
-#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK                         BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK                         (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_MPU_SHIFT                           0
-#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK                            BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK                            (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER2_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER2_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK                             (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_DUCATI_SHIFT                             5
-#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK                              BITFIELD(5, 5)
+#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK                              (1 << 5)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_MPU_SHIFT                                        4
-#define OMAP4430_WKUPDEP_DSI1_MPU_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_WKUPDEP_DSI1_MPU_MASK                                 (1 << 4)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_SDMA_SHIFT                               7
-#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK                                        BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK                                        (1 << 7)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_TESLA_SHIFT                              6
-#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK                               BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK                               (1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_DUCATI_SHIFT                             9
-#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK                              BITFIELD(9, 9)
+#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK                              (1 << 9)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_MPU_SHIFT                                        8
-#define OMAP4430_WKUPDEP_DSI2_MPU_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_DSI2_MPU_MASK                                 (1 << 8)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_SDMA_SHIFT                               11
-#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK                                        BITFIELD(11, 11)
+#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK                                        (1 << 11)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_TESLA_SHIFT                              10
-#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK                               BITFIELD(10, 10)
+#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK                               (1 << 10)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_SHIFT                       1
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK                                BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK                                (1 << 1)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_SHIFT                       1
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK                                BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK                                (1 << 1)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIDMA_SDMA_SHIFT                            19
-#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK                             BITFIELD(19, 19)
+#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK                             (1 << 19)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_SHIFT                          13
-#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK                           BITFIELD(13, 13)
+#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK                           (1 << 13)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_MPU_SHIFT                             12
-#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK                              BITFIELD(12, 12)
+#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK                              (1 << 12)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_SHIFT                           14
-#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK                            BITFIELD(14, 14)
+#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK                            (1 << 14)
 
 /* Used by PM_L4PER_HECC1_WKDEP */
 #define OMAP4430_WKUPDEP_HECC1_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_HECC1_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC1_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_HECC2_WKDEP */
 #define OMAP4430_WKUPDEP_HECC2_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_HECC2_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC2_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_DSP_TESLA_SHIFT                           6
-#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK                            BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK                            (1 << 6)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_WKUP_KEYBOARD_WKDEP */
 #define OMAP4430_WKUPDEP_KEYBOARD_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK                             (1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC1_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC1_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC2_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC2_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC6_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC6_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_SDMA_SHIFT                            7
-#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK                             BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK                             (1 << 7)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_TESLA_SHIFT                           6
-#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK                            BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK                            (1 << 6)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK                              (1 << 0)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_SHIFT                           2
-#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK                            BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK                            (1 << 2)
 
 /* Used by PM_WKUP_RTC_WKDEP */
 #define OMAP4430_WKUPDEP_RTC_MPU_SHIFT                                 0
-#define OMAP4430_WKUPDEP_RTC_MPU_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_RTC_MPU_MASK                                  (1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_SATA_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SATA_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_SATA_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SATA_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_SHIFT                       7
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK                                BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK                                (1 << 7)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_SHIFT                      6
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK                       BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK                       (1 << 6)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_SHIFT                                0
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK                         BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK                         (1 << 0)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_SHIFT                      2
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK                       BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK                       (1 << 2)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_SHIFT                       7
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK                                BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK                                (1 << 7)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_SHIFT                      6
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK                       BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK                       (1 << 6)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_SHIFT                                0
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK                         BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK                         (1 << 0)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_SHIFT                      2
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK                       BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK                       (1 << 2)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK                              (1 << 0)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ALWON_SR_MPU_WKDEP */
 #define OMAP4430_WKUPDEP_SR_MPU_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK                               (1 << 0)
 
 /* Used by PM_WKUP_TIMER12_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER12_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK                              (1 << 0)
 
 /* Used by PM_WKUP_TIMER1_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART1_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART1_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART1_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART1_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART2_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART2_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART2_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART2_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_DUCATI_SHIFT                            1
-#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK                             BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK                             (1 << 1)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART3_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART3_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART3_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART3_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_TESLA_SHIFT                             2
-#define OMAP4430_WKUPDEP_UART3_TESLA_MASK                              BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_UART3_TESLA_MASK                              (1 << 2)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART4_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART4_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART4_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART4_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_SHIFT                      1
-#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK                       BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK                       (1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_SHIFT                         0
-#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK                          BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK                          (1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK                              (1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_USIM_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USIM_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_USIM_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_USIM_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_WDT2_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT2_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_ABE_WDT3_WKDEP */
 #define OMAP4430_WKUPDEP_WDT3_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_WDT3_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT3_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_SHIFT                                8
-#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK                         BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK                         (1 << 8)
 
 /* Used by PM_L3INIT_XHPI_WKDEP */
 #define OMAP4430_WKUPDEP_XHPI_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK                              (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_CTRL_SHIFT                                      8
-#define OMAP4430_WUCLK_CTRL_MASK                                       BITFIELD(8, 8)
+#define OMAP4430_WUCLK_CTRL_MASK                                       (1 << 8)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_STATUS_SHIFT                                    9
-#define OMAP4430_WUCLK_STATUS_MASK                                     BITFIELD(9, 9)
+#define OMAP4430_WUCLK_STATUS_MASK                                     (1 << 9)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_X_MAJOR_SHIFT                                         8
+#define OMAP4430_X_MAJOR_MASK                                          (0x7 << 8)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_Y_MINOR_SHIFT                                         0
+#define OMAP4430_Y_MINOR_MASK                                          (0x3f << 0)
 #endif
index 588873b..7be040b 100644 (file)
@@ -5,7 +5,7 @@
  * OMAP2/3 Power/Reset Management (PRM) register definitions
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -246,6 +246,15 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
        return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
 }
 
+/* These omap2_ PRM functions apply to both OMAP2 and 3 */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+
 #endif
 
 /*
@@ -398,4 +407,11 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
 #define OMAP_POWERSTATE_MASK                           (0x3 << 0)
 
 
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT              10000
+
+
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
new file mode 100644 (file)
index 0000000..421771e
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * OMAP2/3 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+
+/**
+ * omap2_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL if called while running on a non-OMAP2/3 chip.
+ */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
+                                      (1 << shift));
+}
+
+/**
+ * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+       prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
+
+       return 0;
+}
+
+/**
+ * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+       int c;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+       /* de-assert the reset control line */
+       prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+       /* wait the status to be set */
+       omap_test_timeout(prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
+                                                 mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
new file mode 100644 (file)
index 0000000..a1ff918
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * OMAP4 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET               4
+
+/**
+ * omap4_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
+{
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
+}
+
+/**
+ * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       mask = 1 << shift;
+       omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
+
+       return 0;
+}
+
+/**
+ * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+       void __iomem *rstst_reg;
+       int c;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
+       /* de-assert the reset control line */
+       omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
+       /* wait the status to be set */
+       omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
index fe8ef26..59839db 100644 (file)
 #define OMAP4430_PRM_IRQSTATUS_TESLA                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0030)
 #define OMAP4_PRM_IRQENABLE_TESLA_OFFSET               0x0038
 #define OMAP4430_PRM_IRQENABLE_TESLA                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0038)
-#define OMAP4_PRM_PRM_PROFILING_CLKCTRL_OFFSET         0x0040
-#define OMAP4430_PRM_PRM_PROFILING_CLKCTRL             OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
+#define OMAP4_CM_PRM_PROFILING_CLKCTRL_OFFSET          0x0040
+#define OMAP4430_CM_PRM_PROFILING_CLKCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
 
 /* PRM.CKGEN_PRM register offsets */
 #define OMAP4_CM_ABE_DSS_SYS_CLKSEL_OFFSET             0x0000
 #define OMAP4430_CM_ABE_DSS_SYS_CLKSEL                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0000)
-#define OMAP4_CM_DPLL_SYS_REF_CLKSEL_OFFSET            0x0004
-#define OMAP4430_CM_DPLL_SYS_REF_CLKSEL                        OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0004)
 #define OMAP4_CM_L4_WKUP_CLKSEL_OFFSET                 0x0008
 #define OMAP4430_CM_L4_WKUP_CLKSEL                     OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0008)
 #define OMAP4_CM_ABE_PLL_REF_CLKSEL_OFFSET             0x000c
 #define OMAP4430_PRM_LDO_ABB_IVA_SETUP                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d8)
 #define OMAP4_PRM_LDO_ABB_IVA_CTRL_OFFSET              0x00dc
 #define OMAP4430_PRM_LDO_ABB_IVA_CTRL                  OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00dc)
-#define OMAP4_PRM_LDO_BANDGAP_CTRL_OFFSET              0x00e0
-#define OMAP4430_PRM_LDO_BANDGAP_CTRL                  OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
+#define OMAP4_PRM_LDO_BANDGAP_SETUP_OFFSET             0x00e0
+#define OMAP4430_PRM_LDO_BANDGAP_SETUP                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
 #define OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET               0x00e4
 #define OMAP4430_PRM_DEVICE_OFF_CTRL                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e4)
 #define OMAP4_PRM_PHASE1_CNDP_OFFSET                   0x00e8
 #define OMAP4430_PRM_PHASE2B_CNDP                      OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f0)
 #define OMAP4_PRM_MODEM_IF_CTRL_OFFSET                 0x00f4
 #define OMAP4430_PRM_MODEM_IF_CTRL                     OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f4)
+#define OMAP4_PRM_VC_ERRST_OFFSET                      0x00f8
+#define OMAP4430_PRM_VC_ERRST                          OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f8)
 
 /*
  * PRCM_MPU
 /* PRCM_MPU.DEVICE_PRM register offsets */
 #define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET                        0x0000
 #define OMAP4430_PRCM_MPU_PRM_RSTST                    OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET          0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT              OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0004)
 
 /* PRCM_MPU.CPU0 register offsets */
 #define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET                 0x0000
index 566e991..becf0e3 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_SERIAL_OMAP
+#include <plat/omap-serial.h>
+#endif
 
 #include <plat/common.h>
 #include <plat/board.h>
 #include <plat/clock.h>
-#include <plat/control.h>
+#include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "prm.h"
 #include "pm.h"
+#include "cm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV    0x52
 #define UART_OMAP_WER          0x17    /* Wake-up enable register */
@@ -48,6 +59,8 @@
  */
 #define DEFAULT_TIMEOUT 0
 
+#define MAX_UART_HWMOD_NAME_LEN                16
+
 struct omap_uart_state {
        int num;
        int can_sleep;
@@ -58,14 +71,21 @@ struct omap_uart_state {
        void __iomem *wk_en;
        u32 wk_mask;
        u32 padconf;
+       u32 dma_enabled;
 
        struct clk *ick;
        struct clk *fck;
        int clocked;
 
-       struct plat_serial8250_port *p;
+       int irq;
+       int regshift;
+       int irqflags;
+       void __iomem *membase;
+       resource_size_t mapbase;
+
        struct list_head node;
-       struct platform_device pdev;
+       struct omap_hwmod *oh;
+       struct platform_device *pdev;
 
        u32 errata;
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
@@ -83,75 +103,47 @@ struct omap_uart_state {
 };
 
 static LIST_HEAD(uart_list);
+static u8 num_uarts;
 
-static struct plat_serial8250_port serial_platform_data0[] = {
-       {
-               .irq            = 72,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+/*
+ * Since these idle/enable hooks are used in the idle path itself
+ * which has interrupts disabled, use the non-locking versions of
+ * the hwmod enable/disable functions.
+ */
+static int uart_idle_hwmod(struct omap_device *od)
+{
+       _omap_hwmod_idle(od->hwmods[0]);
 
-static struct plat_serial8250_port serial_platform_data1[] = {
-       {
-               .irq            = 73,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+       return 0;
+}
 
-static struct plat_serial8250_port serial_platform_data2[] = {
-       {
-               .irq            = 74,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+static int uart_enable_hwmod(struct omap_device *od)
+{
+       _omap_hwmod_enable(od->hwmods[0]);
 
-static struct plat_serial8250_port serial_platform_data3[] = {
+       return 0;
+}
+
+static struct omap_device_pm_latency omap_uart_latency[] = {
        {
-               .irq            = 70,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
+               .deactivate_func = uart_idle_hwmod,
+               .activate_func   = uart_enable_hwmod,
+               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
 };
 
-void __init omap2_set_globals_uart(struct omap_globals *omap2_globals)
-{
-       serial_platform_data0[0].mapbase = omap2_globals->uart1_phys;
-       serial_platform_data1[0].mapbase = omap2_globals->uart2_phys;
-       serial_platform_data2[0].mapbase = omap2_globals->uart3_phys;
-       serial_platform_data3[0].mapbase = omap2_globals->uart4_phys;
-}
-
 static inline unsigned int __serial_read_reg(struct uart_port *up,
-                                          int offset)
+                                            int offset)
 {
        offset <<= up->regshift;
        return (unsigned int)__raw_readb(up->membase + offset);
 }
 
-static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
                                           int offset)
 {
-       offset <<= up->regshift;
-       return (unsigned int)__raw_readb(up->membase + offset);
+       offset <<= uart->regshift;
+       return (unsigned int)__raw_readb(uart->membase + offset);
 }
 
 static inline void __serial_write_reg(struct uart_port *up, int offset,
@@ -161,11 +153,11 @@ static inline void __serial_write_reg(struct uart_port *up, int offset,
        __raw_writeb(value, up->membase + offset);
 }
 
-static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
                                    int value)
 {
-       offset <<= p->regshift;
-       __raw_writeb(value, p->membase + offset);
+       offset <<= uart->regshift;
+       __raw_writeb(value, uart->membase + offset);
 }
 
 /*
@@ -173,14 +165,12 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
  * properly. Note that the TX watermark initialization may not be needed
  * once the 8250.c watermark handling code is merged.
  */
+
 static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
-       struct plat_serial8250_port *p = uart->p;
-
-       serial_write_reg(p, UART_OMAP_MDR1, 0x07);
-       serial_write_reg(p, UART_OMAP_SCR, 0x08);
-       serial_write_reg(p, UART_OMAP_MDR1, 0x00);
-       serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
+       serial_write_reg(uart, UART_OMAP_MDR1, 0x07);
+       serial_write_reg(uart, UART_OMAP_SCR, 0x08);
+       serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
@@ -197,24 +187,23 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
                u8 fcr_val)
 {
-       struct plat_serial8250_port *p = uart->p;
        u8 timeout = 255;
 
-       serial_write_reg(p, UART_OMAP_MDR1, mdr1_val);
+       serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
        udelay(2);
-       serial_write_reg(p, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
+       serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
                        UART_FCR_CLEAR_RCVR);
        /*
         * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
         * TX_FIFO_E bit is 1.
         */
-       while (UART_LSR_THRE != (serial_read_reg(p, UART_LSR) &
+       while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
                                (UART_LSR_THRE | UART_LSR_DR))) {
                timeout--;
                if (!timeout) {
                        /* Should *never* happen. we warn and carry on */
-                       dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n",
-                               serial_read_reg(p, UART_LSR));
+                       dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
+                       serial_read_reg(uart, UART_LSR));
                        break;
                }
                udelay(1);
@@ -224,23 +213,22 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
 static void omap_uart_save_context(struct omap_uart_state *uart)
 {
        u16 lcr = 0;
-       struct plat_serial8250_port *p = uart->p;
 
        if (!enable_off_mode)
                return;
 
-       lcr = serial_read_reg(p, UART_LCR);
-       serial_write_reg(p, UART_LCR, 0xBF);
-       uart->dll = serial_read_reg(p, UART_DLL);
-       uart->dlh = serial_read_reg(p, UART_DLM);
-       serial_write_reg(p, UART_LCR, lcr);
-       uart->ier = serial_read_reg(p, UART_IER);
-       uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
-       uart->scr = serial_read_reg(p, UART_OMAP_SCR);
-       uart->wer = serial_read_reg(p, UART_OMAP_WER);
-       serial_write_reg(p, UART_LCR, 0x80);
-       uart->mcr = serial_read_reg(p, UART_MCR);
-       serial_write_reg(p, UART_LCR, lcr);
+       lcr = serial_read_reg(uart, UART_LCR);
+       serial_write_reg(uart, UART_LCR, 0xBF);
+       uart->dll = serial_read_reg(uart, UART_DLL);
+       uart->dlh = serial_read_reg(uart, UART_DLM);
+       serial_write_reg(uart, UART_LCR, lcr);
+       uart->ier = serial_read_reg(uart, UART_IER);
+       uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
+       uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
+       uart->wer = serial_read_reg(uart, UART_OMAP_WER);
+       serial_write_reg(uart, UART_LCR, 0x80);
+       uart->mcr = serial_read_reg(uart, UART_MCR);
+       serial_write_reg(uart, UART_LCR, lcr);
 
        uart->context_valid = 1;
 }
@@ -248,7 +236,6 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
 static void omap_uart_restore_context(struct omap_uart_state *uart)
 {
        u16 efr = 0;
-       struct plat_serial8250_port *p = uart->p;
 
        if (!enable_off_mode)
                return;
@@ -261,29 +248,30 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
        if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
                omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
        else
-               serial_write_reg(p, UART_OMAP_MDR1, 0x7);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       efr = serial_read_reg(p, UART_EFR);
-       serial_write_reg(p, UART_EFR, UART_EFR_ECB);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, 0x0);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_DLL, uart->dll);
-       serial_write_reg(p, UART_DLM, uart->dlh);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, uart->ier);
-       serial_write_reg(p, UART_LCR, 0x80);
-       serial_write_reg(p, UART_MCR, uart->mcr);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_EFR, efr);
-       serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
-       serial_write_reg(p, UART_OMAP_SCR, uart->scr);
-       serial_write_reg(p, UART_OMAP_WER, uart->wer);
-       serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
+               serial_write_reg(uart, UART_OMAP_MDR1, 0x7);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       efr = serial_read_reg(uart, UART_EFR);
+       serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
+       serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+       serial_write_reg(uart, UART_IER, 0x0);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       serial_write_reg(uart, UART_DLL, uart->dll);
+       serial_write_reg(uart, UART_DLM, uart->dlh);
+       serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+       serial_write_reg(uart, UART_IER, uart->ier);
+       serial_write_reg(uart, UART_LCR, 0x80);
+       serial_write_reg(uart, UART_MCR, uart->mcr);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       serial_write_reg(uart, UART_EFR, efr);
+       serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
+       serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
+       serial_write_reg(uart, UART_OMAP_WER, uart->wer);
+       serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
        if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
                omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
        else
-               serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+               /* UART 16x mode */
+               serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 #else
 static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
@@ -295,8 +283,7 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
        if (uart->clocked)
                return;
 
-       clk_enable(uart->ick);
-       clk_enable(uart->fck);
+       omap_device_enable(uart->pdev);
        uart->clocked = 1;
        omap_uart_restore_context(uart);
 }
@@ -310,8 +297,7 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
 
        omap_uart_save_context(uart);
        uart->clocked = 0;
-       clk_disable(uart->ick);
-       clk_disable(uart->fck);
+       omap_device_idle(uart->pdev);
 }
 
 static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
@@ -349,18 +335,24 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
 }
 
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
-                                         int enable)
+                                              int enable)
 {
-       struct plat_serial8250_port *p = uart->p;
-       u16 sysc;
+       u8 idlemode;
 
-       sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
-       if (enable)
-               sysc |= 0x2 << 3;
-       else
-               sysc |= 0x1 << 3;
+       if (enable) {
+               /**
+                * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
+                * in Smartidle Mode When Configured for DMA Operations.
+                */
+               if (uart->dma_enabled)
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               else
+                       idlemode = HWMOD_IDLEMODE_SMART;
+       } else {
+               idlemode = HWMOD_IDLEMODE_NO;
+       }
 
-       serial_write_reg(p, UART_OMAP_SYSC, sysc);
+       omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
 }
 
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -377,7 +369,7 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
 {
-       if (device_may_wakeup(&uart->pdev.dev))
+       if (device_may_wakeup(&uart->pdev->dev))
                omap_uart_enable_wakeup(uart);
        else
                omap_uart_disable_wakeup(uart);
@@ -472,6 +464,7 @@ int omap_uart_can_sleep(void)
  * UART will not idle or sleep for its timeout period.
  *
  **/
+/* static int first_interrupt; */
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
        struct omap_uart_state *uart = dev_id;
@@ -483,7 +476,6 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
-       struct plat_serial8250_port *p = uart->p;
        int ret;
 
        uart->can_sleep = 0;
@@ -495,7 +487,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
        omap_uart_smart_idle_enable(uart, 0);
 
        if (cpu_is_omap34xx()) {
-               u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+               u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
                u32 wk_mask = 0;
                u32 padconf = 0;
 
@@ -514,19 +506,17 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                        wk_mask = OMAP3430_ST_UART3_MASK;
                        padconf = 0x19e;
                        break;
+               case 3:
+                       wk_mask = OMAP3630_ST_UART4_MASK;
+                       padconf = 0x0d2;
+                       break;
                }
                uart->wk_mask = wk_mask;
                uart->padconf = padconf;
        } else if (cpu_is_omap24xx()) {
                u32 wk_mask = 0;
+               u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-               if (cpu_is_omap2430()) {
-                       uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-                       uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
-               } else if (cpu_is_omap2420()) {
-                       uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-                       uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
-               }
                switch (uart->num) {
                case 0:
                        wk_mask = OMAP24XX_ST_UART1_MASK;
@@ -535,10 +525,19 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                        wk_mask = OMAP24XX_ST_UART2_MASK;
                        break;
                case 2:
+                       wk_en = OMAP24XX_PM_WKEN2;
+                       wk_st = OMAP24XX_PM_WKST2;
                        wk_mask = OMAP24XX_ST_UART3_MASK;
                        break;
                }
                uart->wk_mask = wk_mask;
+               if (cpu_is_omap2430()) {
+                       uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
+                       uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
+               } else if (cpu_is_omap2420()) {
+                       uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
+                       uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
+               }
        } else {
                uart->wk_en = NULL;
                uart->wk_st = NULL;
@@ -546,9 +545,9 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                uart->padconf = 0;
        }
 
-       p->irqflags |= IRQF_SHARED;
-       ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
-                         "serial idle", (void *)uart);
+       uart->irqflags |= IRQF_SHARED;
+       ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
+                                  IRQF_SHARED, "serial idle", (void *)uart);
        WARN_ON(ret);
 }
 
@@ -558,11 +557,17 @@ void omap_uart_enable_irqs(int enable)
        struct omap_uart_state *uart;
 
        list_for_each_entry(uart, &uart_list, node) {
-               if (enable)
-                       ret = request_irq(uart->p->irq, omap_uart_interrupt,
-                               IRQF_SHARED, "serial idle", (void *)uart);
-               else
-                       free_irq(uart->p->irq, (void *)uart);
+               if (enable) {
+                       pm_runtime_put_sync(&uart->pdev->dev);
+                       ret = request_threaded_irq(uart->irq, NULL,
+                                                  omap_uart_interrupt,
+                                                  IRQF_SHARED,
+                                                  "serial idle",
+                                                  (void *)uart);
+               } else {
+                       pm_runtime_get_noresume(&uart->pdev->dev);
+                       free_irq(uart->irq, (void *)uart);
+               }
        }
 }
 
@@ -570,10 +575,9 @@ static ssize_t sleep_timeout_show(struct device *dev,
                                  struct device_attribute *attr,
                                  char *buf)
 {
-       struct platform_device *pdev = container_of(dev,
-                                       struct platform_device, dev);
-       struct omap_uart_state *uart = container_of(pdev,
-                                       struct omap_uart_state, pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *odev = to_omap_device(pdev);
+       struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
 
        return sprintf(buf, "%u\n", uart->timeout / HZ);
 }
@@ -582,10 +586,9 @@ static ssize_t sleep_timeout_store(struct device *dev,
                                   struct device_attribute *attr,
                                   const char *buf, size_t n)
 {
-       struct platform_device *pdev = container_of(dev,
-                                       struct platform_device, dev);
-       struct omap_uart_state *uart = container_of(pdev,
-                                       struct omap_uart_state, pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *odev = to_omap_device(pdev);
+       struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
        unsigned int value;
 
        if (sscanf(buf, "%u", &value) != 1) {
@@ -608,48 +611,15 @@ static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
 #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+static void omap_uart_block_sleep(struct omap_uart_state *uart)
+{
+       /* Needed to enable UART clocks when built without CONFIG_PM */
+       omap_uart_enable_clocks(uart);
+}
 #define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
-static struct omap_uart_state omap_uart[] = {
-       {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data0,
-                       },
-               },
-       }, {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM1,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data1,
-                       },
-               },
-       }, {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM2,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data2,
-                       },
-               },
-       },
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-       {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = 3,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data3,
-                       },
-               },
-       },
-#endif
-};
-
+#ifndef CONFIG_SERIAL_OMAP
 /*
  * Override the default 8250 read handler: mem_serial_in()
  * Empty RX fifo read causes an abort on omap3630 and omap4
@@ -682,71 +652,44 @@ static void serial_out_override(struct uart_port *up, int offset, int value)
        }
        __serial_write_reg(up, offset, value);
 }
+#endif
+
 void __init omap_serial_early_init(void)
 {
-       int i, nr_ports;
-       char name[16];
+       int i = 0;
 
-       if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-               nr_ports = 3;
-       else
-               nr_ports = ARRAY_SIZE(omap_uart);
+       do {
+               char oh_name[MAX_UART_HWMOD_NAME_LEN];
+               struct omap_hwmod *oh;
+               struct omap_uart_state *uart;
 
-       /*
-        * Make sure the serial ports are muxed on at this point.
-        * You have to mux them off in device drivers later on
-        * if not needed.
-        */
+               snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
+                        "uart%d", i + 1);
+               oh = omap_hwmod_lookup(oh_name);
+               if (!oh)
+                       break;
 
-       for (i = 0; i < nr_ports; i++) {
-               struct omap_uart_state *uart = &omap_uart[i];
-               struct platform_device *pdev = &uart->pdev;
-               struct device *dev = &pdev->dev;
-               struct plat_serial8250_port *p = dev->platform_data;
+               uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
+               if (WARN_ON(!uart))
+                       return;
+
+               uart->oh = oh;
+               uart->num = i++;
+               list_add_tail(&uart->node, &uart_list);
+               num_uarts++;
 
-               /* Don't map zero-based physical address */
-               if (p->mapbase == 0) {
-                       dev_warn(dev, "no physical address for uart#%d,"
-                                " so skipping early_init...\n", i);
-                       continue;
-               }
                /*
-                * Module 4KB + L4 interconnect 4KB
-                * Static mapping, never released
+                * NOTE: omap_hwmod_init() has not yet been called,
+                *       so no hwmod functions will work yet.
                 */
-               p->membase = ioremap(p->mapbase, SZ_8K);
-               if (!p->membase) {
-                       dev_err(dev, "ioremap failed for uart%i\n", i + 1);
-                       continue;
-               }
-
-               sprintf(name, "uart%d_ick", i + 1);
-               uart->ick = clk_get(NULL, name);
-               if (IS_ERR(uart->ick)) {
-                       dev_err(dev, "Could not get uart%d_ick\n", i + 1);
-                       uart->ick = NULL;
-               }
 
-               sprintf(name, "uart%d_fck", i+1);
-               uart->fck = clk_get(NULL, name);
-               if (IS_ERR(uart->fck)) {
-                       dev_err(dev, "Could not get uart%d_fck\n", i + 1);
-                       uart->fck = NULL;
-               }
-
-               /* FIXME: Remove this once the clkdev is ready */
-               if (!cpu_is_omap44xx()) {
-                       if (!uart->ick || !uart->fck)
-                               continue;
-               }
-
-               uart->num = i;
-               p->private_data = uart;
-               uart->p = p;
-
-               if (cpu_is_omap44xx())
-                       p->irq += 32;
-       }
+               /*
+                * During UART early init, device need to be probed
+                * to determine SoC specific init before omap_device
+                * is ready.  Therefore, don't allow idle here
+                */
+               uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+       } while (1);
 }
 
 /**
@@ -763,53 +706,135 @@ void __init omap_serial_early_init(void)
 void __init omap_serial_init_port(int port)
 {
        struct omap_uart_state *uart;
-       struct platform_device *pdev;
-       struct device *dev;
-
-       BUG_ON(port < 0);
-       BUG_ON(port >= ARRAY_SIZE(omap_uart));
-
-       uart = &omap_uart[port];
-       pdev = &uart->pdev;
-       dev = &pdev->dev;
+       struct omap_hwmod *oh;
+       struct omap_device *od;
+       void *pdata = NULL;
+       u32 pdata_size = 0;
+       char *name;
+#ifndef CONFIG_SERIAL_OMAP
+       struct plat_serial8250_port ports[2] = {
+               {},
+               {.flags = 0},
+       };
+       struct plat_serial8250_port *p = &ports[0];
+#else
+       struct omap_uart_port_info omap_up;
+#endif
 
-       /* Don't proceed if there's no clocks available */
-       if (unlikely(!uart->ick || !uart->fck)) {
-               WARN(1, "%s: can't init uart%d, no clocks available\n",
-                    kobject_name(&dev->kobj), port);
+       if (WARN_ON(port < 0))
+               return;
+       if (WARN_ON(port >= num_uarts))
                return;
-       }
-
-       omap_uart_enable_clocks(uart);
-
-       omap_uart_reset(uart);
-       omap_uart_idle_init(uart);
 
-       list_add_tail(&uart->node, &uart_list);
+       list_for_each_entry(uart, &uart_list, node)
+               if (port == uart->num)
+                       break;
 
-       if (WARN_ON(platform_device_register(pdev)))
-               return;
+       oh = uart->oh;
+       uart->dma_enabled = 0;
+#ifndef CONFIG_SERIAL_OMAP
+       name = "serial8250";
 
-       if ((cpu_is_omap34xx() && uart->padconf) ||
-           (uart->wk_en && uart->wk_mask)) {
-               device_init_wakeup(dev, true);
-               DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
-       }
+       /*
+        * !! 8250 driver does not use standard IORESOURCE* It
+        * has it's own custom pdata that can be taken from
+        * the hwmod resource data.  But, this needs to be
+        * done after the build.
+        *
+        * ?? does it have to be done before the register ??
+        * YES, because platform_device_data_add() copies
+        * pdata, it does not use a pointer.
+        */
+       p->flags = UPF_BOOT_AUTOCONF;
+       p->iotype = UPIO_MEM;
+       p->regshift = 2;
+       p->uartclk = OMAP24XX_BASE_BAUD * 16;
+       p->irq = oh->mpu_irqs[0].irq;
+       p->mapbase = oh->slaves[0]->addr->pa_start;
+       p->membase = omap_hwmod_get_mpu_rt_va(oh);
+       p->irqflags = IRQF_SHARED;
+       p->private_data = uart;
 
        /*
         * omap44xx: Never read empty UART fifo
         * omap3xxx: Never read empty UART fifo on UARTs
         * with IP rev >=0x52
         */
+       uart->regshift = p->regshift;
+       uart->membase = p->membase;
        if (cpu_is_omap44xx())
                uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-       else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
+       else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
                        >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
                uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
 
        if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
-               uart->p->serial_in = serial_in_override;
-               uart->p->serial_out = serial_out_override;
+               p->serial_in = serial_in_override;
+               p->serial_out = serial_out_override;
+       }
+
+       pdata = &ports[0];
+       pdata_size = 2 * sizeof(struct plat_serial8250_port);
+#else
+
+       name = DRIVER_NAME;
+
+       omap_up.dma_enabled = uart->dma_enabled;
+       omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
+       omap_up.mapbase = oh->slaves[0]->addr->pa_start;
+       omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
+       omap_up.irqflags = IRQF_SHARED;
+       omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+
+       pdata = &omap_up;
+       pdata_size = sizeof(struct omap_uart_port_info);
+#endif
+
+       if (WARN_ON(!oh))
+               return;
+
+       od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+                              omap_uart_latency,
+                              ARRAY_SIZE(omap_uart_latency), false);
+       WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+            name, oh->name);
+
+       uart->irq = oh->mpu_irqs[0].irq;
+       uart->regshift = 2;
+       uart->mapbase = oh->slaves[0]->addr->pa_start;
+       uart->membase = omap_hwmod_get_mpu_rt_va(oh);
+       uart->pdev = &od->pdev;
+
+       oh->dev_attr = uart;
+
+       /*
+        * Because of early UART probing, UART did not get idled
+        * on init.  Now that omap_device is ready, ensure full idle
+        * before doing omap_device_enable().
+        */
+       omap_hwmod_idle(uart->oh);
+
+       omap_device_enable(uart->pdev);
+       omap_uart_idle_init(uart);
+       omap_uart_reset(uart);
+       omap_hwmod_enable_wakeup(uart->oh);
+       omap_device_idle(uart->pdev);
+
+       /*
+        * Need to block sleep long enough for interrupt driven
+        * driver to start.  Console driver is in polling mode
+        * so device needs to be kept enabled while polling driver
+        * is in use.
+        */
+       if (uart->timeout)
+               uart->timeout = (30 * HZ);
+       omap_uart_block_sleep(uart);
+       uart->timeout = DEFAULT_TIMEOUT;
+
+       if ((cpu_is_omap34xx() && uart->padconf) ||
+           (uart->wk_en && uart->wk_mask)) {
+               device_init_wakeup(&od->pdev.dev, true);
+               DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
        }
 
        /* Enable the MDR1 errata for OMAP3 */
@@ -826,13 +851,8 @@ void __init omap_serial_init_port(int port)
  */
 void __init omap_serial_init(void)
 {
-       int i, nr_ports;
-
-       if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-               nr_ports = 3;
-       else
-               nr_ports = ARRAY_SIZE(omap_uart);
+       struct omap_uart_state *uart;
 
-       for (i = 0; i < nr_ports; i++)
-               omap_serial_init_port(i);
+       list_for_each_entry(uart, &uart_list, node)
+               omap_serial_init_port(uart->num);
 }
index ba53191..2fb205a 100644 (file)
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <plat/control.h>
 
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define SDRC_SCRATCHPAD_SEM_V  0xfa00291c
 
index de99ba2..3637274 100644 (file)
@@ -129,8 +129,11 @@ ENTRY(omap3_sram_configure_core_dpll)
        ldr     r4, [sp, #80]
        str     r4, omap_sdrc_mr_1_val
 skip_cs1_params:
+       mrc     p15, 0, r8, c1, c0, 0   @ read ctrl register
+       bic     r10, r8, #0x800         @ clear Z-bit, disable branch prediction
+       mcr     p15, 0, r10, c1, c0, 0  @ write ctrl register
        dsb                             @ flush buffered writes to interconnect
-
+       isb                             @ prevent speculative exec past here
        cmp     r3, #1                  @ if increasing SDRC clk rate,
        bleq    configure_sdrc          @ program the SDRC regs early (for RFR)
        cmp     r1, #SDRC_UNLOCK_DLL    @ set the intended DLL state
@@ -148,6 +151,7 @@ skip_cs1_params:
        beq     return_to_sdram         @ return to SDRAM code, otherwise,
        bl      configure_sdrc          @ reprogram SDRC regs now
 return_to_sdram:
+       mcr     p15, 0, r8, c1, c0, 0   @ restore ctrl register
        isb                             @ prevent speculative exec past here
        mov     r0, #0                  @ return value
        ldmfd   sp!, {r1-r12, pc}       @ restore regs and return
index 74fbed8..e13c29e 100644 (file)
@@ -40,6 +40,8 @@
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 
+#include "timer-gp.h"
+
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID         12
 
@@ -228,8 +230,10 @@ static void __init omap2_gp_clocksource_init(void)
 static void __init omap2_gp_timer_init(void)
 {
 #ifdef CONFIG_LOCAL_TIMERS
-       twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
-       BUG_ON(!twd_base);
+       if (cpu_is_omap44xx()) {
+               twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+               BUG_ON(!twd_base);
+       }
 #endif
        omap_dm_timer_init();
 
similarity index 86%
rename from arch/arm/plat-omap/include/plat/timer-gp.h
rename to arch/arm/mach-omap2/timer-gp.h
index c88d346..5c1072c 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
 
-int __init omap2_gp_clockevent_set_gptimer(u8 id);
+extern int __init omap2_gp_clockevent_set_gptimer(u8 id);
 
 #endif
-
index a216d88..1481078 100644 (file)
 
 #include <asm/irq.h>
 
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 
+#include "control.h"
+#include "mux.h"
+
 #define INT_USB_IRQ_GEN                INT_24XX_USB_IRQ_GEN
 #define INT_USB_IRQ_NISO       INT_24XX_USB_IRQ_NISO
 #define INT_USB_IRQ_ISO                INT_24XX_USB_IRQ_ISO
 #define INT_USB_IRQ_HGEN       INT_24XX_USB_IRQ_HGEN
 #define INT_USB_IRQ_OTG                INT_24XX_USB_IRQ_OTG
 
-#include "mux.h"
-
 #if defined(CONFIG_ARCH_OMAP2)
 
 #ifdef CONFIG_USB_GADGET_OMAP
index 08b4103..aaa1166 100644 (file)
@@ -382,6 +382,31 @@ struct platform_device pxa_device_i2s = {
        .num_resources  = ARRAY_SIZE(pxai2s_resources),
 };
 
+struct platform_device pxa_device_asoc_ssp1 = {
+       .name           = "pxa-ssp-dai",
+       .id             = 0,
+};
+
+struct platform_device pxa_device_asoc_ssp2= {
+       .name           = "pxa-ssp-dai",
+       .id             = 1,
+};
+
+struct platform_device pxa_device_asoc_ssp3 = {
+       .name           = "pxa-ssp-dai",
+       .id             = 2,
+};
+
+struct platform_device pxa_device_asoc_ssp4 = {
+       .name           = "pxa-ssp-dai",
+       .id             = 3,
+};
+
+struct platform_device pxa_device_asoc_platform = {
+       .name           = "pxa-pcm-audio",
+       .id             = -1,
+};
+
 static u64 pxaficp_dmamask = ~(u32)0;
 
 struct platform_device pxa_device_ficp = {
index 715e8bd..2fd5a8b 100644 (file)
@@ -39,4 +39,10 @@ extern struct platform_device pxa3xx_device_i2c_power;
 
 extern struct platform_device pxa3xx_device_gcu;
 
+extern struct platform_device pxa_device_asoc_platform;
+extern struct platform_device pxa_device_asoc_ssp1;
+extern struct platform_device pxa_device_asoc_ssp2;
+extern struct platform_device pxa_device_asoc_ssp3;
+extern struct platform_device pxa_device_asoc_ssp4;
+
 void __init pxa_register_device(struct platform_device *dev, void *data);
index 12e5b9f..d1fbf29 100644 (file)
@@ -385,6 +385,10 @@ static struct platform_device *devices[] __initdata = {
        &pxa27x_device_udc,
        &pxa_device_pmu,
        &pxa_device_i2s,
+       &pxa_device_asoc_ssp1,
+       &pxa_device_asoc_ssp2,
+       &pxa_device_asoc_ssp3,
+       &pxa_device_asoc_platform,
        &sa1100_device_rtc,
        &pxa_device_rtc,
        &pxa27x_device_ssp1,
index c85c3a7..d1c747c 100644 (file)
@@ -593,6 +593,11 @@ static struct platform_device *devices[] __initdata = {
        &pxa27x_device_udc,
        &pxa_device_pmu,
        &pxa_device_i2s,
+       &pxa_device_asoc_ssp1,
+       &pxa_device_asoc_ssp2,
+       &pxa_device_asoc_ssp3,
+       &pxa_device_asoc_ssp4,
+       &pxa_device_asoc_platform,
        &sa1100_device_rtc,
        &pxa_device_rtc,
        &pxa27x_device_ssp1,
index f25fb62..702f7a6 100644 (file)
@@ -45,6 +45,16 @@ int wm9713_irq;
 int lcd_id;
 int lcd_orientation;
 
+struct platform_device pxa_device_wm9713_audio = {
+       .name           = "wm9713-codec",
+       .id             = -1,
+};
+
+static void __init zylonite_init_wm9713_audio(void)
+{
+       platform_device_register(&pxa_device_wm9713_audio);
+}
+
 static struct resource smc91x_resources[] = {
        [0] = {
                .start  = ZYLONITE_ETH_PHYS + 0x300,
@@ -408,6 +418,7 @@ static void __init zylonite_init(void)
        zylonite_init_nand();
        zylonite_init_leds();
        zylonite_init_ohci();
+       zylonite_init_wm9713_audio();
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
index 9648fbc..3838335 100644 (file)
@@ -43,8 +43,10 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
                s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
                s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
                s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
+               break;
        default:
-               printk(KERN_DEBUG "Invalid I2S Controller number!");
+               printk(KERN_DEBUG "Invalid I2S Controller number: %d\n",
+                       pdev->id);
                return -EINVAL;
        }
 
@@ -184,7 +186,8 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
                s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
                break;
        default:
-               printk(KERN_DEBUG "Invalid PCM Controller number!");
+               printk(KERN_DEBUG "Invalid PCM Controller number: %d\n",
+                       pdev->id);
                return -EINVAL;
        }
 
@@ -333,3 +336,16 @@ void __init s3c64xx_ac97_setup_gpio(int num)
        else
                s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
 }
+
+static u64 s3c_device_audio_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_pcm = {
+       .name             = "s3c24xx-pcm-audio",
+       .id               = -1,
+       .dev              = {
+               .dma_mask = &s3c_device_audio_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+EXPORT_SYMBOL(s3c_device_pcm);
+
index ec8865c..77488fa 100644 (file)
@@ -283,6 +283,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
        &s3c_device_fb,
        &s3c_device_ohci,
        &s3c_device_usb_hsotg,
+       &s3c_device_pcm,
        &s3c64xx_device_iisv4,
        &samsung_device_keypad,
 
index a57713c..acd9552 100644 (file)
@@ -16,6 +16,10 @@ config ARCH_TEGRA_2x_SOC
 
 endchoice
 
+config TEGRA_PCI
+       bool "PCI Express support"
+       select PCI
+
 comment "Tegra board type"
 
 config MACH_HARMONY
@@ -47,4 +51,11 @@ config TEGRA_DEBUG_UARTE
 
 endchoice
 
+config TEGRA_SYSTEM_DMA
+       bool "Enable system DMA driver for NVIDIA Tegra SoCs"
+       default y
+       help
+         Adds system DMA functionality for NVIDIA Tegra SoCs, used by
+         several Tegra device drivers
+
 endif
index 51e9370..cdbc68e 100644 (file)
@@ -1,14 +1,21 @@
 obj-y                                   += common.o
 obj-y                                   += io.o
-obj-y                                   += irq.o
+obj-y                                   += irq.o legacy_irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
 obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
+obj-y                                  += fuse.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_dvfs.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += pinmux-t2-tables.o
 obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o
+obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
+obj-$(CONFIG_TEGRA_PCI)                        += pcie.o
 
 obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-pcie.o
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
new file mode 100644 (file)
index 0000000..f7e7d45
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-tegra/board-harmony-pcie.c
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/pinmux.h>
+#include "board.h"
+
+#ifdef CONFIG_TEGRA_PCI
+
+static int __init harmony_pcie_init(void)
+{
+       int err;
+
+       if (!machine_is_harmony())
+               return 0;
+
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL);
+
+       err = tegra_pcie_init(true, true);
+       if (err)
+               goto err_pcie;
+
+       return 0;
+
+err_pcie:
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_TRISTATE);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE);
+
+       return err;
+}
+
+subsys_initcall(harmony_pcie_init);
+
+#endif
index 3d06354..0de565c 100644 (file)
@@ -27,6 +27,7 @@ void __init tegra_common_init(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
+int __init tegra_pcie_init(bool init_port0, bool init_port1);
 
 extern struct sys_timer tegra_timer;
 #endif
index 03ad578..ae19f95 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/regulator/consumer.h>
 #include <asm/clkdev.h>
 
 #include "clock.h"
+#include "board.h"
+#include "fuse.h"
 
 static LIST_HEAD(clocks);
 
 static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(dvfs_lock);
+
+static int clk_is_dvfs(struct clk *c)
+{
+       return (c->dvfs != NULL);
+};
+
+static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
+{
+       struct dvfs_table *t;
+
+       if (d->table == NULL)
+               return -ENODEV;
+
+       for (t = d->table; t->rate != 0; t++) {
+               if (rate <= t->rate) {
+                       if (!d->reg)
+                               return 0;
+
+                       return regulator_set_voltage(d->reg,
+                               t->millivolts * 1000,
+                               d->max_millivolts * 1000);
+               }
+       }
+
+       return -EINVAL;
+}
+
+static void dvfs_init(struct clk *c)
+{
+       int process_id;
+       int i;
+       struct dvfs_table *table;
+
+       process_id = c->dvfs->cpu ? tegra_core_process_id() :
+               tegra_cpu_process_id();
+
+       for (i = 0; i < c->dvfs->process_id_table_length; i++)
+               if (process_id == c->dvfs->process_id_table[i].process_id)
+                       c->dvfs->table = c->dvfs->process_id_table[i].table;
+
+       if (c->dvfs->table == NULL) {
+               pr_err("Failed to find dvfs table for clock %s process %d\n",
+                       c->name, process_id);
+               return;
+       }
+
+       c->dvfs->max_millivolts = 0;
+       for (table = c->dvfs->table; table->rate != 0; table++)
+               if (c->dvfs->max_millivolts < table->millivolts)
+                       c->dvfs->max_millivolts = table->millivolts;
+
+       c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
+
+       if (IS_ERR(c->dvfs->reg)) {
+               pr_err("Failed to get regulator %s for clock %s\n",
+                       c->dvfs->reg_id, c->name);
+               c->dvfs->reg = NULL;
+               return;
+       }
+
+       if (c->refcnt > 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+}
 
 struct clk *tegra_get_clock_by_name(const char *name)
 {
@@ -48,14 +115,31 @@ struct clk *tegra_get_clock_by_name(const char *name)
        return ret;
 }
 
+static void clk_recalculate_rate(struct clk *c)
+{
+       u64 rate;
+
+       if (!c->parent)
+               return;
+
+       rate = c->parent->rate;
+
+       if (c->mul != 0 && c->div != 0) {
+               rate = rate * c->mul;
+               do_div(rate, c->div);
+       }
+
+       if (rate > c->max_rate)
+               pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
+                       c->name, rate, c->max_rate);
+
+       c->rate = rate;
+}
+
 int clk_reparent(struct clk *c, struct clk *parent)
 {
        pr_debug("%s: %s\n", __func__, c->name);
-       if (c->refcnt && c->parent)
-               clk_disable_locked(c->parent);
        c->parent = parent;
-       if (c->refcnt && c->parent)
-               clk_enable_locked(c->parent);
        list_del(&c->sibling);
        list_add_tail(&c->sibling, &parent->children);
        return 0;
@@ -67,8 +151,7 @@ static void propagate_rate(struct clk *c)
        pr_debug("%s: %s\n", __func__, c->name);
        list_for_each_entry(clkp, &c->children, sibling) {
                pr_debug("   %s\n", clkp->name);
-               if (clkp->ops->recalculate_rate)
-                       clkp->ops->recalculate_rate(clkp);
+               clk_recalculate_rate(clkp);
                propagate_rate(clkp);
        }
 }
@@ -77,6 +160,8 @@ void clk_init(struct clk *c)
 {
        unsigned long flags;
 
+       pr_debug("%s: %s\n", __func__, c->name);
+
        spin_lock_irqsave(&clock_lock, flags);
 
        INIT_LIST_HEAD(&c->children);
@@ -85,6 +170,8 @@ void clk_init(struct clk *c)
        if (c->ops && c->ops->init)
                c->ops->init(c);
 
+       clk_recalculate_rate(c);
+
        list_add(&c->node, &clocks);
 
        if (c->parent)
@@ -122,13 +209,38 @@ int clk_enable_locked(struct clk *c)
        return 0;
 }
 
+int clk_enable_cansleep(struct clk *c)
+{
+       int ret;
+       unsigned long flags;
+
+       mutex_lock(&dvfs_lock);
+
+       if (clk_is_dvfs(c) && c->refcnt > 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_enable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       mutex_unlock(&dvfs_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_enable_cansleep);
+
 int clk_enable(struct clk *c)
 {
        int ret;
        unsigned long flags;
+
+       if (clk_is_dvfs(c))
+               BUG();
+
        spin_lock_irqsave(&clock_lock, flags);
        ret = clk_enable_locked(c);
        spin_unlock_irqrestore(&clock_lock, flags);
+
        return ret;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -152,9 +264,30 @@ void clk_disable_locked(struct clk *c)
        c->refcnt--;
 }
 
+void clk_disable_cansleep(struct clk *c)
+{
+       unsigned long flags;
+
+       mutex_lock(&dvfs_lock);
+
+       spin_lock_irqsave(&clock_lock, flags);
+       clk_disable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       if (clk_is_dvfs(c) && c->refcnt == 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+
+       mutex_unlock(&dvfs_lock);
+}
+EXPORT_SYMBOL(clk_disable_cansleep);
+
 void clk_disable(struct clk *c)
 {
        unsigned long flags;
+
+       if (clk_is_dvfs(c))
+               BUG();
+
        spin_lock_irqsave(&clock_lock, flags);
        clk_disable_locked(c);
        spin_unlock_irqrestore(&clock_lock, flags);
@@ -175,6 +308,8 @@ int clk_set_parent_locked(struct clk *c, struct clk *parent)
        if (ret)
                return ret;
 
+       clk_recalculate_rate(c);
+
        propagate_rate(c);
 
        return 0;
@@ -197,22 +332,69 @@ struct clk *clk_get_parent(struct clk *c)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
-int clk_set_rate(struct clk *c, unsigned long rate)
+int clk_set_rate_locked(struct clk *c, unsigned long rate)
+{
+       int ret;
+
+       if (rate > c->max_rate)
+               rate = c->max_rate;
+
+       if (!c->ops || !c->ops->set_rate)
+               return -ENOSYS;
+
+       ret = c->ops->set_rate(c, rate);
+
+       if (ret)
+               return ret;
+
+       clk_recalculate_rate(c);
+
+       propagate_rate(c);
+
+       return 0;
+}
+
+int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
 {
        int ret = 0;
        unsigned long flags;
 
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       mutex_lock(&dvfs_lock);
+
+       if (rate > c->rate)
+               ret = dvfs_set_rate(c->dvfs, rate);
+       if (ret)
+               goto out;
+
        spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_set_rate_locked(c, rate);
+       spin_unlock_irqrestore(&clock_lock, flags);
 
-       pr_debug("%s: %s\n", __func__, c->name);
+       if (ret)
+               goto out;
 
-       if (c->ops && c->ops->set_rate)
-               ret = c->ops->set_rate(c, rate);
-       else
-               ret = -ENOSYS;
+       ret = dvfs_set_rate(c->dvfs, rate);
 
-       propagate_rate(c);
+out:
+       mutex_unlock(&dvfs_lock);
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate_cansleep);
+
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (clk_is_dvfs(c))
+               BUG();
 
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_set_rate_locked(c, rate);
        spin_unlock_irqrestore(&clock_lock, flags);
 
        return ret;
@@ -235,6 +417,20 @@ unsigned long clk_get_rate(struct clk *c)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+long clk_round_rate(struct clk *c, unsigned long rate)
+{
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (!c->ops || !c->ops->round_rate)
+               return -ENOSYS;
+
+       if (rate > c->max_rate)
+               rate = c->max_rate;
+
+       return c->ops->round_rate(c, rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
 {
        struct clk *c;
@@ -308,13 +504,28 @@ void tegra_periph_reset_assert(struct clk *c)
 }
 EXPORT_SYMBOL(tegra_periph_reset_assert);
 
-int __init tegra_init_clock(void)
+void __init tegra_init_clock(void)
 {
        tegra2_init_clocks();
+}
+
+int __init tegra_init_dvfs(void)
+{
+       struct clk *c, *safe;
+
+       mutex_lock(&dvfs_lock);
+
+       list_for_each_entry_safe(c, safe, &clocks, node)
+               if (c->dvfs)
+                       dvfs_init(c);
+
+       mutex_unlock(&dvfs_lock);
 
        return 0;
 }
 
+late_initcall(tegra_init_dvfs);
+
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *clk_debugfs_root;
 
@@ -324,7 +535,7 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
        struct clk *child;
        struct clk *safe;
        const char *state = "uninit";
-       char div[5] = {0};
+       char div[8] = {0};
 
        if (c->state == ON)
                state = "on";
@@ -332,16 +543,26 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
                state = "off";
 
        if (c->mul != 0 && c->div != 0) {
-               BUG_ON(c->mul > 2);
-               if (c->mul > c->div)
-                       snprintf(div, sizeof(div), "x%d", c->mul / c->div);
-               else
+               if (c->mul > c->div) {
+                       int mul = c->mul / c->div;
+                       int mul2 = (c->mul * 10 / c->div) % 10;
+                       int mul3 = (c->mul * 10) % c->div;
+                       if (mul2 == 0 && mul3 == 0)
+                               snprintf(div, sizeof(div), "x%d", mul);
+                       else if (mul3 == 0)
+                               snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
+                       else
+                               snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
+               } else {
                        snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
                                (c->div % c->mul) ? ".5" : "");
+               }
        }
 
-       seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
-               level * 3 + 1, c->set ? "" : "*",
+       seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
+               level * 3 + 1, "",
+               c->rate > c->max_rate ? '!' : ' ',
+               !c->set ? '*' : ' ',
                30 - level * 3, c->name,
                state, c->refcnt, div, c->rate);
        list_for_each_entry_safe(child, safe, &c->children, sibling) {
@@ -353,8 +574,8 @@ static int clock_tree_show(struct seq_file *s, void *data)
 {
        struct clk *c;
        unsigned long flags;
-       seq_printf(s, " clock                          state  ref div   rate      \n");
-       seq_printf(s, "-----------------------------------------------------------\n");
+       seq_printf(s, "   clock                          state  ref div      rate\n");
+       seq_printf(s, "--------------------------------------------------------------\n");
        spin_lock_irqsave(&clock_lock, flags);
        list_for_each_entry(c, &clocks, node)
                if (c->parent == NULL)
index af7c70e..94fd859 100644 (file)
 #define DIV_U71                        (1 << 1)
 #define DIV_U71_FIXED          (1 << 2)
 #define DIV_2                  (1 << 3)
-#define PLL_FIXED              (1 << 4)
-#define PLL_HAS_CPCON          (1 << 5)
-#define MUX                    (1 << 6)
-#define PLLD                   (1 << 7)
-#define PERIPH_NO_RESET                (1 << 8)
-#define PERIPH_NO_ENB          (1 << 9)
-#define PERIPH_EMC_ENB         (1 << 10)
-#define PERIPH_MANUAL_RESET    (1 << 11)
-#define PLL_ALT_MISC_REG       (1 << 12)
+#define DIV_U16                        (1 << 4)
+#define PLL_FIXED              (1 << 5)
+#define PLL_HAS_CPCON          (1 << 6)
+#define MUX                    (1 << 7)
+#define PLLD                   (1 << 8)
+#define PERIPH_NO_RESET                (1 << 9)
+#define PERIPH_NO_ENB          (1 << 10)
+#define PERIPH_EMC_ENB         (1 << 11)
+#define PERIPH_MANUAL_RESET    (1 << 12)
+#define PLL_ALT_MISC_REG       (1 << 13)
+#define PLLU                   (1 << 14)
 #define ENABLE_ON_INIT         (1 << 28)
 
 struct clk;
+struct regulator;
+
+struct dvfs_table {
+       unsigned long rate;
+       int millivolts;
+};
+
+struct dvfs_process_id_table {
+       int process_id;
+       struct dvfs_table *table;
+};
+
+
+struct dvfs {
+       struct regulator *reg;
+       struct dvfs_table *table;
+       int max_millivolts;
+
+       int process_id_table_length;
+       const char *reg_id;
+       bool cpu;
+       struct dvfs_process_id_table process_id_table[];
+};
 
 struct clk_mux_sel {
        struct clk      *input;
@@ -58,12 +83,9 @@ struct clk_ops {
        void            (*init)(struct clk *);
        int             (*enable)(struct clk *);
        void            (*disable)(struct clk *);
-       void            (*recalc)(struct clk *);
        int             (*set_parent)(struct clk *, struct clk *);
        int             (*set_rate)(struct clk *, unsigned long);
-       unsigned long   (*get_rate)(struct clk *);
        long            (*round_rate)(struct clk *, unsigned long);
-       unsigned long   (*recalculate_rate)(struct clk *);
 };
 
 enum clk_state {
@@ -85,6 +107,7 @@ struct clk {
        struct clk                      *parent;
        struct clk_lookup               lookup;
        unsigned long                   rate;
+       unsigned long                   max_rate;
        u32                             flags;
        u32                             refcnt;
        const char                      *name;
@@ -103,10 +126,6 @@ struct clk {
        unsigned long                   cf_max;
        unsigned long                   vco_min;
        unsigned long                   vco_max;
-       u32                             m;
-       u32                             n;
-       u32                             p;
-       u32                             cpcon;
        const struct clk_pll_table      *pll_table;
 
        /* DIV */
@@ -117,6 +136,12 @@ struct clk {
        const struct clk_mux_sel        *inputs;
        u32                             sel;
        u32                             reg_mask;
+
+       /* Virtual cpu clock */
+       struct clk                      *main;
+       struct clk                      *backup;
+
+       struct dvfs                     *dvfs;
 };
 
 
@@ -141,6 +166,7 @@ unsigned long clk_measure_input_freq(void);
 void clk_disable_locked(struct clk *c);
 int clk_enable_locked(struct clk *c);
 int clk_set_parent_locked(struct clk *c, struct clk *parent);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
 int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
 
index 039a514..7c91e2b 100644 (file)
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
 
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/iomap.h>
+#include <mach/dma.h>
 
 #include "board.h"
 #include "clock.h"
+#include "fuse.h"
 
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
        /* name         parent          rate            enabled */
@@ -35,8 +39,8 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
        { "pll_p_out2", "pll_p",        48000000,       true },
        { "pll_p_out3", "pll_p",        72000000,       true },
        { "pll_p_out4", "pll_p",        108000000,      true },
-       { "sys",        "pll_p_out4",   108000000,      true },
-       { "hclk",       "sys",          108000000,      true },
+       { "sclk",       "pll_p_out4",   108000000,      true },
+       { "hclk",       "sclk",         108000000,      true },
        { "pclk",       "hclk",         54000000,       true },
        { NULL,         NULL,           0,              0},
 };
@@ -51,11 +55,16 @@ void __init tegra_init_cache(void)
 
        l2x0_init(p, 0x6C080001, 0x8200c3fe);
 #endif
+
 }
 
 void __init tegra_common_init(void)
 {
+       tegra_init_fuse();
        tegra_init_clock();
        tegra_clk_init_from_table(common_clk_init_table);
        tegra_init_cache();
+#ifdef CONFIG_TEGRA_SYSTEM_DMA
+       tegra_dma_init();
+#endif
 }
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
new file mode 100644 (file)
index 0000000..fea5719
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * arch/arm/mach-tegra/cpu-tegra.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/hardware.h>
+#include <mach/clk.h>
+
+/* Frequency table index must be sequential starting at 0 */
+static struct cpufreq_frequency_table freq_table[] = {
+       { 0, 312000 },
+       { 1, 456000 },
+       { 2, 608000 },
+       { 3, 760000 },
+       { 4, 816000 },
+       { 5, 912000 },
+       { 6, 1000000 },
+       { 7, CPUFREQ_TABLE_END },
+};
+
+#define NUM_CPUS       2
+
+static struct clk *cpu_clk;
+
+static unsigned long target_cpu_speed[NUM_CPUS];
+
+int tegra_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+unsigned int tegra_getspeed(unsigned int cpu)
+{
+       unsigned long rate;
+
+       if (cpu >= NUM_CPUS)
+               return 0;
+
+       rate = clk_get_rate(cpu_clk) / 1000;
+       return rate;
+}
+
+static int tegra_update_cpu_speed(void)
+{
+       int i;
+       unsigned long rate = 0;
+       int ret = 0;
+       struct cpufreq_freqs freqs;
+
+       for_each_online_cpu(i)
+               rate = max(rate, target_cpu_speed[i]);
+
+       freqs.old = tegra_getspeed(0);
+       freqs.new = rate;
+
+       if (freqs.old == freqs.new)
+               return ret;
+
+       for_each_online_cpu(freqs.cpu)
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+       printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
+              freqs.old, freqs.new);
+#endif
+
+       ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000);
+       if (ret) {
+               pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
+                       freqs.new);
+               return ret;
+       }
+
+       for_each_online_cpu(freqs.cpu)
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       return 0;
+}
+
+static int tegra_target(struct cpufreq_policy *policy,
+                      unsigned int target_freq,
+                      unsigned int relation)
+{
+       int idx;
+       unsigned int freq;
+
+       cpufreq_frequency_table_target(policy, freq_table, target_freq,
+               relation, &idx);
+
+       freq = freq_table[idx].frequency;
+
+       target_cpu_speed[policy->cpu] = freq;
+
+       return tegra_update_cpu_speed();
+}
+
+static int tegra_cpu_init(struct cpufreq_policy *policy)
+{
+       if (policy->cpu >= NUM_CPUS)
+               return -EINVAL;
+
+       cpu_clk = clk_get_sys(NULL, "cpu");
+       if (IS_ERR(cpu_clk))
+               return PTR_ERR(cpu_clk);
+
+       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+       policy->cur = tegra_getspeed(policy->cpu);
+       target_cpu_speed[policy->cpu] = policy->cur;
+
+       /* FIXME: what's the actual transition time? */
+       policy->cpuinfo.transition_latency = 300 * 1000;
+
+       policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+       cpumask_copy(policy->related_cpus, cpu_possible_mask);
+
+       return 0;
+}
+
+static int tegra_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       clk_put(cpu_clk);
+       return 0;
+}
+
+static struct freq_attr *tegra_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver tegra_cpufreq_driver = {
+       .verify         = tegra_verify_speed,
+       .target         = tegra_target,
+       .get            = tegra_getspeed,
+       .init           = tegra_cpu_init,
+       .exit           = tegra_cpu_exit,
+       .name           = "tegra",
+       .attr           = tegra_cpufreq_attr,
+};
+
+static int __init tegra_cpufreq_init(void)
+{
+       return cpufreq_register_driver(&tegra_cpufreq_driver);
+}
+
+static void __exit tegra_cpufreq_exit(void)
+{
+        cpufreq_unregister_driver(&tegra_cpufreq_driver);
+}
+
+
+MODULE_AUTHOR("Colin Cross <ccross@android.com>");
+MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2");
+MODULE_LICENSE("GPL");
+module_init(tegra_cpufreq_init);
+module_exit(tegra_cpufreq_exit);
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
new file mode 100644 (file)
index 0000000..edda6ec
--- /dev/null
@@ -0,0 +1,752 @@
+/*
+ * arch/arm/mach-tegra/dma.c
+ *
+ * System DMA driver for NVIDIA Tegra SoCs
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+
+#define APB_DMA_GEN                            0x000
+#define GEN_ENABLE                             (1<<31)
+
+#define APB_DMA_CNTRL                          0x010
+
+#define APB_DMA_IRQ_MASK                       0x01c
+
+#define APB_DMA_IRQ_MASK_SET                   0x020
+
+#define APB_DMA_CHAN_CSR                       0x000
+#define CSR_ENB                                        (1<<31)
+#define CSR_IE_EOC                             (1<<30)
+#define CSR_HOLD                               (1<<29)
+#define CSR_DIR                                        (1<<28)
+#define CSR_ONCE                               (1<<27)
+#define CSR_FLOW                               (1<<21)
+#define CSR_REQ_SEL_SHIFT                      16
+#define CSR_REQ_SEL_MASK                       (0x1F<<CSR_REQ_SEL_SHIFT)
+#define CSR_REQ_SEL_INVALID                    (31<<CSR_REQ_SEL_SHIFT)
+#define CSR_WCOUNT_SHIFT                       2
+#define CSR_WCOUNT_MASK                                0xFFFC
+
+#define APB_DMA_CHAN_STA                               0x004
+#define STA_BUSY                               (1<<31)
+#define STA_ISE_EOC                            (1<<30)
+#define STA_HALT                               (1<<29)
+#define STA_PING_PONG                          (1<<28)
+#define STA_COUNT_SHIFT                                2
+#define STA_COUNT_MASK                         0xFFFC
+
+#define APB_DMA_CHAN_AHB_PTR                           0x010
+
+#define APB_DMA_CHAN_AHB_SEQ                           0x014
+#define AHB_SEQ_INTR_ENB                       (1<<31)
+#define AHB_SEQ_BUS_WIDTH_SHIFT                        28
+#define AHB_SEQ_BUS_WIDTH_MASK                 (0x7<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_8                    (0<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_16                   (1<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_32                   (2<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_64                   (3<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_128                  (4<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_DATA_SWAP                      (1<<27)
+#define AHB_SEQ_BURST_MASK                     (0x7<<24)
+#define AHB_SEQ_BURST_1                                (4<<24)
+#define AHB_SEQ_BURST_4                                (5<<24)
+#define AHB_SEQ_BURST_8                                (6<<24)
+#define AHB_SEQ_DBL_BUF                                (1<<19)
+#define AHB_SEQ_WRAP_SHIFT                     16
+#define AHB_SEQ_WRAP_MASK                      (0x7<<AHB_SEQ_WRAP_SHIFT)
+
+#define APB_DMA_CHAN_APB_PTR                           0x018
+
+#define APB_DMA_CHAN_APB_SEQ                           0x01c
+#define APB_SEQ_BUS_WIDTH_SHIFT                        28
+#define APB_SEQ_BUS_WIDTH_MASK                 (0x7<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_8                    (0<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_16                   (1<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_32                   (2<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_64                   (3<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_128                  (4<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_DATA_SWAP                      (1<<27)
+#define APB_SEQ_WRAP_SHIFT                     16
+#define APB_SEQ_WRAP_MASK                      (0x7<<APB_SEQ_WRAP_SHIFT)
+
+#define TEGRA_SYSTEM_DMA_CH_NR                 16
+#define TEGRA_SYSTEM_DMA_AVP_CH_NUM            4
+#define TEGRA_SYSTEM_DMA_CH_MIN                        0
+#define TEGRA_SYSTEM_DMA_CH_MAX        \
+       (TEGRA_SYSTEM_DMA_CH_NR - TEGRA_SYSTEM_DMA_AVP_CH_NUM - 1)
+
+#define NV_DMA_MAX_TRASFER_SIZE 0x10000
+
+const unsigned int ahb_addr_wrap_table[8] = {
+       0, 32, 64, 128, 256, 512, 1024, 2048
+};
+
+const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+
+const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+
+#define TEGRA_DMA_NAME_SIZE 16
+struct tegra_dma_channel {
+       struct list_head        list;
+       int                     id;
+       spinlock_t              lock;
+       char                    name[TEGRA_DMA_NAME_SIZE];
+       void  __iomem           *addr;
+       int                     mode;
+       int                     irq;
+
+       /* Register shadow */
+       u32                     csr;
+       u32                     ahb_seq;
+       u32                     ahb_ptr;
+       u32                     apb_seq;
+       u32                     apb_ptr;
+};
+
+#define  NV_DMA_MAX_CHANNELS  32
+
+static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
+static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
+static void tegra_dma_stop(struct tegra_dma_channel *ch);
+
+void tegra_dma_flush(struct tegra_dma_channel *ch)
+{
+}
+EXPORT_SYMBOL(tegra_dma_flush);
+
+void tegra_dma_dequeue(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+
+       tegra_dma_dequeue_req(ch, req);
+       return;
+}
+
+void tegra_dma_stop(struct tegra_dma_channel *ch)
+{
+       unsigned int csr;
+       unsigned int status;
+
+       csr = ch->csr;
+       csr &= ~CSR_IE_EOC;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       csr &= ~CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       if (status & STA_ISE_EOC)
+               writel(status, ch->addr + APB_DMA_CHAN_STA);
+}
+
+int tegra_dma_cancel(struct tegra_dma_channel *ch)
+{
+       unsigned int csr;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       while (!list_empty(&ch->list))
+               list_del(ch->list.next);
+
+       csr = ch->csr;
+       csr &= ~CSR_REQ_SEL_MASK;
+       csr |= CSR_REQ_SEL_INVALID;
+
+       /* Set the enable as that is not shadowed */
+       csr |= CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       tegra_dma_stop(ch);
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return 0;
+}
+
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *_req)
+{
+       unsigned int csr;
+       unsigned int status;
+       struct tegra_dma_req *req = NULL;
+       int found = 0;
+       unsigned long irq_flags;
+       int to_transfer;
+       int req_transfer_count;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       list_for_each_entry(req, &ch->list, node) {
+               if (req == _req) {
+                       list_del(&req->node);
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found) {
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               return 0;
+       }
+
+       /* STOP the DMA and get the transfer count.
+        * Getting the transfer count is tricky.
+        *  - Change the source selector to invalid to stop the DMA from
+        *    FIFO to memory.
+        *  - Read the status register to know the number of pending
+        *    bytes to be transfered.
+        *  - Finally stop or program the DMA to the next buffer in the
+        *    list.
+        */
+       csr = ch->csr;
+       csr &= ~CSR_REQ_SEL_MASK;
+       csr |= CSR_REQ_SEL_INVALID;
+
+       /* Set the enable as that is not shadowed */
+       csr |= CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       /* Get the transfer count */
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
+       req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+       req_transfer_count += 1;
+       to_transfer += 1;
+
+       req->bytes_transferred = req_transfer_count;
+
+       if (status & STA_BUSY)
+               req->bytes_transferred -= to_transfer;
+
+       /* In continous transfer mode, DMA only tracks the count of the
+        * half DMA buffer. So, if the DMA already finished half the DMA
+        * then add the half buffer to the completed count.
+        *
+        *      FIXME: There can be a race here. What if the req to
+        *      dequue happens at the same time as the DMA just moved to
+        *      the new buffer and SW didn't yet received the interrupt?
+        */
+       if (ch->mode & TEGRA_DMA_MODE_CONTINOUS)
+               if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
+                       req->bytes_transferred += req_transfer_count;
+
+       req->bytes_transferred *= 4;
+
+       tegra_dma_stop(ch);
+       if (!list_empty(&ch->list)) {
+               /* if the list is not empty, queue the next request */
+               struct tegra_dma_req *next_req;
+               next_req = list_entry(ch->list.next,
+                       typeof(*next_req), node);
+               tegra_dma_update_hw(ch, next_req);
+       }
+       req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       /* Callback should be called without any lock */
+       req->complete(req);
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dma_dequeue_req);
+
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch)
+{
+       unsigned long irq_flags;
+       bool is_empty;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       if (list_empty(&ch->list))
+               is_empty = true;
+       else
+               is_empty = false;
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return is_empty;
+}
+EXPORT_SYMBOL(tegra_dma_is_empty);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *_req)
+{
+       unsigned long irq_flags;
+       struct tegra_dma_req *req;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       list_for_each_entry(req, &ch->list, node) {
+               if (req == _req) {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return true;
+               }
+       }
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return false;
+}
+EXPORT_SYMBOL(tegra_dma_is_req_inflight);
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       unsigned long irq_flags;
+       int start_dma = 0;
+
+       if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
+               req->source_addr & 0x3 || req->dest_addr & 0x3) {
+               pr_err("Invalid DMA request for channel %d\n", ch->id);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+
+       req->bytes_transferred = 0;
+       req->status = 0;
+       req->buffer_status = 0;
+       if (list_empty(&ch->list))
+               start_dma = 1;
+
+       list_add_tail(&req->node, &ch->list);
+
+       if (start_dma)
+               tegra_dma_update_hw(ch, req);
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dma_enqueue_req);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
+{
+       int channel;
+       struct tegra_dma_channel *ch;
+
+       /* first channel is the shared channel */
+       if (mode & TEGRA_DMA_SHARED) {
+               channel = TEGRA_SYSTEM_DMA_CH_MIN;
+       } else {
+               channel = find_first_zero_bit(channel_usage,
+                       ARRAY_SIZE(dma_channels));
+               if (channel >= ARRAY_SIZE(dma_channels))
+                       return NULL;
+       }
+       __set_bit(channel, channel_usage);
+       ch = &dma_channels[channel];
+       ch->mode = mode;
+       return ch;
+}
+EXPORT_SYMBOL(tegra_dma_allocate_channel);
+
+void tegra_dma_free_channel(struct tegra_dma_channel *ch)
+{
+       if (ch->mode & TEGRA_DMA_SHARED)
+               return;
+       tegra_dma_cancel(ch);
+       __clear_bit(ch->id, channel_usage);
+}
+EXPORT_SYMBOL(tegra_dma_free_channel);
+
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       if (req->to_memory) {
+               ch->apb_ptr = req->source_addr;
+               ch->ahb_ptr = req->dest_addr;
+       } else {
+               ch->apb_ptr = req->dest_addr;
+               ch->ahb_ptr = req->source_addr;
+       }
+       writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+       writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+       req->status = TEGRA_DMA_REQ_INFLIGHT;
+       return;
+}
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       int ahb_addr_wrap;
+       int apb_addr_wrap;
+       int ahb_bus_width;
+       int apb_bus_width;
+       int index;
+       unsigned long csr;
+
+
+       ch->csr |= CSR_FLOW;
+       ch->csr &= ~CSR_REQ_SEL_MASK;
+       ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
+       ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
+       ch->ahb_seq |= AHB_SEQ_BURST_1;
+
+       /* One shot mode is always single buffered,
+        * continuous mode is always double buffered
+        * */
+       if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
+               ch->csr |= CSR_ONCE;
+               ch->ahb_seq &= ~AHB_SEQ_DBL_BUF;
+               ch->csr &= ~CSR_WCOUNT_MASK;
+               ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
+       } else {
+               ch->csr &= ~CSR_ONCE;
+               ch->ahb_seq |= AHB_SEQ_DBL_BUF;
+
+               /* In double buffered mode, we set the size to half the
+                * requested size and interrupt when half the buffer
+                * is full */
+               ch->csr &= ~CSR_WCOUNT_MASK;
+               ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
+       }
+
+       if (req->to_memory) {
+               ch->csr &= ~CSR_DIR;
+               ch->apb_ptr = req->source_addr;
+               ch->ahb_ptr = req->dest_addr;
+
+               apb_addr_wrap = req->source_wrap;
+               ahb_addr_wrap = req->dest_wrap;
+               apb_bus_width = req->source_bus_width;
+               ahb_bus_width = req->dest_bus_width;
+
+       } else {
+               ch->csr |= CSR_DIR;
+               ch->apb_ptr = req->dest_addr;
+               ch->ahb_ptr = req->source_addr;
+
+               apb_addr_wrap = req->dest_wrap;
+               ahb_addr_wrap = req->source_wrap;
+               apb_bus_width = req->dest_bus_width;
+               ahb_bus_width = req->source_bus_width;
+       }
+
+       apb_addr_wrap >>= 2;
+       ahb_addr_wrap >>= 2;
+
+       /* set address wrap for APB size */
+       index = 0;
+       do  {
+               if (apb_addr_wrap_table[index] == apb_addr_wrap)
+                       break;
+               index++;
+       } while (index < ARRAY_SIZE(apb_addr_wrap_table));
+       BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
+       ch->apb_seq &= ~APB_SEQ_WRAP_MASK;
+       ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
+
+       /* set address wrap for AHB size */
+       index = 0;
+       do  {
+               if (ahb_addr_wrap_table[index] == ahb_addr_wrap)
+                       break;
+               index++;
+       } while (index < ARRAY_SIZE(ahb_addr_wrap_table));
+       BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
+       ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK;
+       ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
+
+       for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+               if (bus_width_table[index] == ahb_bus_width)
+                       break;
+       }
+       BUG_ON(index == ARRAY_SIZE(bus_width_table));
+       ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK;
+       ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
+
+       for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+               if (bus_width_table[index] == apb_bus_width)
+                       break;
+       }
+       BUG_ON(index == ARRAY_SIZE(bus_width_table));
+       ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK;
+       ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
+
+       ch->csr |= CSR_IE_EOC;
+
+       /* update hw registers with the shadow */
+       writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR);
+       writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
+       writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+       writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
+       writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+       csr = ch->csr | CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       req->status = TEGRA_DMA_REQ_INFLIGHT;
+}
+
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
+{
+       /* One shot with an interrupt to CPU after transfer */
+       ch->csr = CSR_ONCE | CSR_IE_EOC;
+       ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
+       ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
+}
+
+static void handle_oneshot_dma(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       spin_lock(&ch->lock);
+       if (list_empty(&ch->list)) {
+               spin_unlock(&ch->lock);
+               return;
+       }
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+       if (req) {
+               int bytes_transferred;
+
+               bytes_transferred =
+                       (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+               bytes_transferred += 1;
+               bytes_transferred <<= 2;
+
+               list_del(&req->node);
+               req->bytes_transferred = bytes_transferred;
+               req->status = TEGRA_DMA_REQ_SUCCESS;
+
+               spin_unlock(&ch->lock);
+               /* Callback should be called without any lock */
+               pr_debug("%s: transferred %d bytes\n", __func__,
+                       req->bytes_transferred);
+               req->complete(req);
+               spin_lock(&ch->lock);
+       }
+
+       if (!list_empty(&ch->list)) {
+               req = list_entry(ch->list.next, typeof(*req), node);
+               /* the complete function we just called may have enqueued
+                  another req, in which case dma has already started */
+               if (req->status != TEGRA_DMA_REQ_INFLIGHT)
+                       tegra_dma_update_hw(ch, req);
+       }
+       spin_unlock(&ch->lock);
+}
+
+static void handle_continuous_dma(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       spin_lock(&ch->lock);
+       if (list_empty(&ch->list)) {
+               spin_unlock(&ch->lock);
+               return;
+       }
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+       if (req) {
+               if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
+                       /* Load the next request into the hardware, if available
+                        * */
+                       if (!list_is_last(&req->node, &ch->list)) {
+                               struct tegra_dma_req *next_req;
+
+                               next_req = list_entry(req->node.next,
+                                       typeof(*next_req), node);
+                               tegra_dma_update_hw_partial(ch, next_req);
+                       }
+                       req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
+                       req->status = TEGRA_DMA_REQ_SUCCESS;
+                       /* DMA lock is NOT held when callback is called */
+                       spin_unlock(&ch->lock);
+                       if (likely(req->threshold))
+                               req->threshold(req);
+                       return;
+
+               } else if (req->buffer_status ==
+                       TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) {
+                       /* Callback when the buffer is completely full (i.e on
+                        * the second  interrupt */
+                       int bytes_transferred;
+
+                       bytes_transferred =
+                               (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+                       bytes_transferred += 1;
+                       bytes_transferred <<= 3;
+
+                       req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
+                       req->bytes_transferred = bytes_transferred;
+                       req->status = TEGRA_DMA_REQ_SUCCESS;
+                       list_del(&req->node);
+
+                       /* DMA lock is NOT held when callbak is called */
+                       spin_unlock(&ch->lock);
+                       req->complete(req);
+                       return;
+
+               } else {
+                       BUG();
+               }
+       }
+       spin_unlock(&ch->lock);
+}
+
+static irqreturn_t dma_isr(int irq, void *data)
+{
+       struct tegra_dma_channel *ch = data;
+       unsigned long status;
+
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       if (status & STA_ISE_EOC)
+               writel(status, ch->addr + APB_DMA_CHAN_STA);
+       else {
+               pr_warning("Got a spurious ISR for DMA channel %d\n", ch->id);
+               return IRQ_HANDLED;
+       }
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t dma_thread_fn(int irq, void *data)
+{
+       struct tegra_dma_channel *ch = data;
+
+       if (ch->mode & TEGRA_DMA_MODE_ONESHOT)
+               handle_oneshot_dma(ch);
+       else
+               handle_continuous_dma(ch);
+
+
+       return IRQ_HANDLED;
+}
+
+int __init tegra_dma_init(void)
+{
+       int ret = 0;
+       int i;
+       unsigned int irq;
+       void __iomem *addr;
+
+       addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       writel(GEN_ENABLE, addr + APB_DMA_GEN);
+       writel(0, addr + APB_DMA_CNTRL);
+       writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
+              addr + APB_DMA_IRQ_MASK_SET);
+
+       memset(channel_usage, 0, sizeof(channel_usage));
+       memset(dma_channels, 0, sizeof(dma_channels));
+
+       /* Reserve all the channels we are not supposed to touch */
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++)
+               __set_bit(i, channel_usage);
+
+       for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+               struct tegra_dma_channel *ch = &dma_channels[i];
+
+               __clear_bit(i, channel_usage);
+
+               ch->id = i;
+               snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
+
+               ch->addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                       TEGRA_APB_DMA_CH0_SIZE * i);
+
+               spin_lock_init(&ch->lock);
+               INIT_LIST_HEAD(&ch->list);
+               tegra_dma_init_hw(ch);
+
+               irq = INT_APB_DMA_CH0 + i;
+               ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
+                       dma_channels[i].name, ch);
+               if (ret) {
+                       pr_err("Failed to register IRQ %d for DMA %d\n",
+                               irq, i);
+                       goto fail;
+               }
+               ch->irq = irq;
+       }
+       /* mark the shared channel allocated */
+       __set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
+
+       for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++)
+               __set_bit(i, channel_usage);
+
+       return ret;
+fail:
+       writel(0, addr + APB_DMA_GEN);
+       for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+               struct tegra_dma_channel *ch = &dma_channels[i];
+               if (ch->irq)
+                       free_irq(ch->irq, ch);
+       }
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
+
+void tegra_dma_suspend(void)
+{
+       void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       u32 *ctx = apb_dma;
+       int i;
+
+       *ctx++ = readl(addr + APB_DMA_GEN);
+       *ctx++ = readl(addr + APB_DMA_CNTRL);
+       *ctx++ = readl(addr + APB_DMA_IRQ_MASK);
+
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+               addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                                 TEGRA_APB_DMA_CH0_SIZE * i);
+
+               *ctx++ = readl(addr + APB_DMA_CHAN_CSR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_AHB_PTR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_AHB_SEQ);
+               *ctx++ = readl(addr + APB_DMA_CHAN_APB_PTR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_APB_SEQ);
+       }
+}
+
+void tegra_dma_resume(void)
+{
+       void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       u32 *ctx = apb_dma;
+       int i;
+
+       writel(*ctx++, addr + APB_DMA_GEN);
+       writel(*ctx++, addr + APB_DMA_CNTRL);
+       writel(*ctx++, addr + APB_DMA_IRQ_MASK);
+
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+               addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                                 TEGRA_APB_DMA_CH0_SIZE * i);
+
+               writel(*ctx++, addr + APB_DMA_CHAN_CSR);
+               writel(*ctx++, addr + APB_DMA_CHAN_AHB_PTR);
+               writel(*ctx++, addr + APB_DMA_CHAN_AHB_SEQ);
+               writel(*ctx++, addr + APB_DMA_CHAN_APB_PTR);
+               writel(*ctx++, addr + APB_DMA_CHAN_APB_SEQ);
+       }
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
new file mode 100644 (file)
index 0000000..1fa26d9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+
+#include "fuse.h"
+
+#define FUSE_UID_LOW           0x108
+#define FUSE_UID_HIGH          0x10c
+#define FUSE_SKU_INFO          0x110
+#define FUSE_SPARE_BIT         0x200
+
+static inline u32 fuse_readl(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+static inline void fuse_writel(u32 value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+void tegra_init_fuse(void)
+{
+       u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+       reg |= 1 << 28;
+       writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+
+       pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
+               tegra_sku_id(), tegra_cpu_process_id(),
+               tegra_core_process_id());
+}
+
+unsigned long long tegra_chip_uid(void)
+{
+       unsigned long long lo, hi;
+
+       lo = fuse_readl(FUSE_UID_LOW);
+       hi = fuse_readl(FUSE_UID_HIGH);
+       return (hi << 32ull) | lo;
+}
+
+int tegra_sku_id(void)
+{
+       int sku_id;
+       u32 reg = fuse_readl(FUSE_SKU_INFO);
+       sku_id = reg & 0xFF;
+       return sku_id;
+}
+
+int tegra_cpu_process_id(void)
+{
+       int cpu_process_id;
+       u32 reg = fuse_readl(FUSE_SPARE_BIT);
+       cpu_process_id = (reg >> 6) & 3;
+       return cpu_process_id;
+}
+
+int tegra_core_process_id(void)
+{
+       int core_process_id;
+       u32 reg = fuse_readl(FUSE_SPARE_BIT);
+       core_process_id = (reg >> 12) & 3;
+       return core_process_id;
+}
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
new file mode 100644 (file)
index 0000000..584b2e2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+unsigned long long tegra_chip_uid(void);
+int tegra_sku_id(void);
+int tegra_cpu_process_id(void);
+int tegra_core_process_id(void);
+void tegra_init_fuse(void);
index fe78fba..0775265 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -60,6 +61,13 @@ struct tegra_gpio_bank {
        int bank;
        int irq;
        spinlock_t lvl_lock[4];
+#ifdef CONFIG_PM
+       u32 cnf[4];
+       u32 out[4];
+       u32 oe[4];
+       u32 int_enb[4];
+       u32 int_lvl[4];
+#endif
 };
 
 
@@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = {
        .direction_output       = tegra_gpio_direction_output,
        .set                    = tegra_gpio_set,
        .base                   = 0,
-       .ngpio                  = ARCH_NR_GPIOS,
+       .ngpio                  = TEGRA_NR_GPIOS,
 };
 
 static void tegra_gpio_irq_ack(unsigned int irq)
@@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 }
 
+#ifdef CONFIG_PM
+void tegra_gpio_resume(void)
+{
+       unsigned long flags;
+       int b, p, i;
+
+       local_irq_save(flags);
+
+       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+               struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+               for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+                       unsigned int gpio = (b<<5) | (p<<3);
+                       __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
+                       __raw_writel(bank->out[p], GPIO_OUT(gpio));
+                       __raw_writel(bank->oe[p], GPIO_OE(gpio));
+                       __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+                       __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+               }
+       }
+
+       local_irq_restore(flags);
+
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc || (desc->status & IRQ_WAKEUP))
+                       continue;
+               enable_irq(i);
+       }
+}
+
+void tegra_gpio_suspend(void)
+{
+       unsigned long flags;
+       int b, p, i;
+
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc)
+                       continue;
+               if (desc->status & IRQ_WAKEUP) {
+                       int gpio = i - INT_GPIO_BASE;
+                       pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
+                       continue;
+               }
+               disable_irq(i);
+       }
+
+       local_irq_save(flags);
+       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+               struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+               for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+                       unsigned int gpio = (b<<5) | (p<<3);
+                       bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
+                       bank->out[p] = __raw_readl(GPIO_OUT(gpio));
+                       bank->oe[p] = __raw_readl(GPIO_OE(gpio));
+                       bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
+                       bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+               }
+       }
+       local_irq_restore(flags);
+}
+
+static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+       struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+       return set_irq_wake(bank->irq, enable);
+}
+#endif
 
 static struct irq_chip tegra_gpio_irq_chip = {
        .name           = "GPIO",
@@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = {
        .mask           = tegra_gpio_irq_mask,
        .unmask         = tegra_gpio_irq_unmask,
        .set_type       = tegra_gpio_irq_set_type,
+#ifdef CONFIG_PM
+       .set_wake       = tegra_gpio_wake_enable,
+#endif
 };
 
 
@@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void)
 
        gpiochip_add(&tegra_gpio_chip);
 
-       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
                bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
 
                lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
@@ -312,15 +393,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
        for (i = 0; i < 7; i++) {
                for (j = 0; j < 4; j++) {
                        int gpio = tegra_gpio_compose(i, j, 0);
-                       seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
-                              i, j,
-                              __raw_readl(GPIO_CNF(gpio)),
-                              __raw_readl(GPIO_OE(gpio)),
-                              __raw_readl(GPIO_OUT(gpio)),
-                              __raw_readl(GPIO_IN(gpio)),
-                              __raw_readl(GPIO_INT_STA(gpio)),
-                              __raw_readl(GPIO_INT_ENB(gpio)),
-                              __raw_readl(GPIO_INT_LVL(gpio)));
+                       seq_printf(s,
+                               "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+                               i, j,
+                               __raw_readl(GPIO_CNF(gpio)),
+                               __raw_readl(GPIO_OE(gpio)),
+                               __raw_readl(GPIO_OUT(gpio)),
+                               __raw_readl(GPIO_IN(gpio)),
+                               __raw_readl(GPIO_INT_STA(gpio)),
+                               __raw_readl(GPIO_INT_ENB(gpio)),
+                               __raw_readl(GPIO_INT_LVL(gpio)));
                }
        }
        return 0;
index 2896f25..d772395 100644 (file)
@@ -23,4 +23,9 @@
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
+int clk_enable_cansleep(struct clk *clk);
+void clk_disable_cansleep(struct clk *clk);
+int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
+int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
+
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
new file mode 100644 (file)
index 0000000..39011bd
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-tegra/include/mach/dma.h
+ *
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __MACH_TEGRA_DMA_H
+#define __MACH_TEGRA_DMA_H
+
+#include <linux/list.h>
+
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+
+struct tegra_dma_req;
+struct tegra_dma_channel;
+
+#define TEGRA_DMA_REQ_SEL_CNTR                 0
+#define TEGRA_DMA_REQ_SEL_I2S_2                        1
+#define TEGRA_DMA_REQ_SEL_I2S_1                        2
+#define TEGRA_DMA_REQ_SEL_SPD_I                        3
+#define TEGRA_DMA_REQ_SEL_UI_I                 4
+#define TEGRA_DMA_REQ_SEL_MIPI                 5
+#define TEGRA_DMA_REQ_SEL_I2S2_2               6
+#define TEGRA_DMA_REQ_SEL_I2S2_1               7
+#define TEGRA_DMA_REQ_SEL_UARTA                        8
+#define TEGRA_DMA_REQ_SEL_UARTB                        9
+#define TEGRA_DMA_REQ_SEL_UARTC                        10
+#define TEGRA_DMA_REQ_SEL_SPI                  11
+#define TEGRA_DMA_REQ_SEL_AC97                 12
+#define TEGRA_DMA_REQ_SEL_ACMODEM              13
+#define TEGRA_DMA_REQ_SEL_SL4B                 14
+#define TEGRA_DMA_REQ_SEL_SL2B1                        15
+#define TEGRA_DMA_REQ_SEL_SL2B2                        16
+#define TEGRA_DMA_REQ_SEL_SL2B3                        17
+#define TEGRA_DMA_REQ_SEL_SL2B4                        18
+#define TEGRA_DMA_REQ_SEL_UARTD                        19
+#define TEGRA_DMA_REQ_SEL_UARTE                        20
+#define TEGRA_DMA_REQ_SEL_I2C                  21
+#define TEGRA_DMA_REQ_SEL_I2C2                 22
+#define TEGRA_DMA_REQ_SEL_I2C3                 23
+#define TEGRA_DMA_REQ_SEL_DVC_I2C              24
+#define TEGRA_DMA_REQ_SEL_OWR                  25
+#define TEGRA_DMA_REQ_SEL_INVALID              31
+
+enum tegra_dma_mode {
+       TEGRA_DMA_SHARED = 1,
+       TEGRA_DMA_MODE_CONTINOUS = 2,
+       TEGRA_DMA_MODE_ONESHOT = 4,
+};
+
+enum tegra_dma_req_error {
+       TEGRA_DMA_REQ_SUCCESS = 0,
+       TEGRA_DMA_REQ_ERROR_ABORTED,
+       TEGRA_DMA_REQ_INFLIGHT,
+};
+
+enum tegra_dma_req_buff_status {
+       TEGRA_DMA_REQ_BUF_STATUS_EMPTY = 0,
+       TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL,
+       TEGRA_DMA_REQ_BUF_STATUS_FULL,
+};
+
+struct tegra_dma_req {
+       struct list_head node;
+       unsigned int modid;
+       int instance;
+
+       /* Called when the req is complete and from the DMA ISR context.
+        * When this is called the req structure is no longer queued by
+        * the DMA channel.
+        *
+        * State of the DMA depends on the number of req it has. If there are
+        * no DMA requests queued up, then it will STOP the DMA. It there are
+        * more requests in the DMA, then it will queue the next request.
+        */
+       void (*complete)(struct tegra_dma_req *req);
+
+       /*  This is a called from the DMA ISR context when the DMA is still in
+        *  progress and is actively filling same buffer.
+        *
+        *  In case of continous mode receive, this threshold is 1/2 the buffer
+        *  size. In other cases, this will not even be called as there is no
+        *  hardware support for it.
+        *
+        * In the case of continous mode receive, if there is next req already
+        * queued, DMA programs the HW to use that req when this req is
+        * completed. If there is no "next req" queued, then DMA ISR doesn't do
+        * anything before calling this callback.
+        *
+        *      This is mainly used by the cases, where the clients has queued
+        *      only one req and want to get some sort of DMA threshold
+        *      callback to program the next buffer.
+        *
+        */
+       void (*threshold)(struct tegra_dma_req *req);
+
+       /* 1 to copy to memory.
+        * 0 to copy from the memory to device FIFO */
+       int to_memory;
+
+       void *virt_addr;
+
+       unsigned long source_addr;
+       unsigned long dest_addr;
+       unsigned long dest_wrap;
+       unsigned long source_wrap;
+       unsigned long source_bus_width;
+       unsigned long dest_bus_width;
+       unsigned long req_sel;
+       unsigned int size;
+
+       /* Updated by the DMA driver on the conpletion of the request. */
+       int bytes_transferred;
+       int status;
+
+       /* DMA completion tracking information */
+       int buffer_status;
+
+       /* Client specific data */
+       void *dev;
+};
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+void tegra_dma_dequeue(struct tegra_dma_channel *ch);
+void tegra_dma_flush(struct tegra_dma_channel *ch);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode);
+void tegra_dma_free_channel(struct tegra_dma_channel *ch);
+
+int __init tegra_dma_init(void);
+
+#endif
+
+#endif
index 540e822..e31f486 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <mach/irqs.h>
 
-#define ARCH_NR_GPIOS          INT_GPIO_NR
+#define TEGRA_NR_GPIOS         INT_GPIO_NR
 
 #include <asm-generic/gpio.h>
 
@@ -35,7 +35,7 @@
 
 static inline int gpio_to_irq(unsigned int gpio)
 {
-       if (gpio < ARCH_NR_GPIOS)
+       if (gpio < TEGRA_NR_GPIOS)
                return INT_GPIO_BASE + gpio;
        return -EINVAL;
 }
index 6014edf..56e43b3 100644 (file)
@@ -21,4 +21,8 @@
 #ifndef __MACH_TEGRA_HARDWARE_H
 #define __MACH_TEGRA_HARDWARE_H
 
+#define PCIBIOS_MIN_IO                 0x1000
+#define PCIBIOS_MIN_MEM                        0
+#define pcibios_assign_all_busses()    1
+
 #endif
index 35edfc3..f0981b1 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __MACH_TEGRA_IO_H
 #define __MACH_TEGRA_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT 0xffff
 
 /* On TEGRA, many peripherals are very closely packed in
  * two 256MB io windows (that actually only use about 64KB
  *
  */
 
+#define IO_IRAM_PHYS   0x40000000
+#define IO_IRAM_VIRT   0xFE400000
+#define IO_IRAM_SIZE   SZ_256K
+
 #define IO_CPU_PHYS     0x50040000
 #define IO_CPU_VIRT     0xFE000000
 #define IO_CPU_SIZE    SZ_16K
@@ -55,6 +59,8 @@
                IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :       \
        IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?             \
                IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :       \
+       IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?           \
+               IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :     \
        0)
 
 #ifndef __ASSEMBLER__
@@ -67,10 +73,20 @@ void tegra_iounmap(volatile void __iomem *addr);
 
 #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
 
+#ifdef CONFIG_TEGRA_PCI
+extern void __iomem *tegra_pcie_io_base;
+
+static inline void __iomem *__io(unsigned long addr)
+{
+       return tegra_pcie_io_base + (addr & IO_SPACE_LIMIT);
+}
+#else
 static inline void __iomem *__io(unsigned long addr)
 {
        return (void __iomem *)addr;
 }
+#endif
+
 #define __io(a)         __io(a)
 #define __mem_pci(a)    (a)
 
index 1741f7d..44a4f4b 100644 (file)
 
 #include <asm/sizes.h>
 
+#define TEGRA_IRAM_BASE                        0x40000000
+#define TEGRA_IRAM_SIZE                        SZ_256K
+
 #define TEGRA_ARM_PERIF_BASE           0x50040000
 #define TEGRA_ARM_PERIF_SIZE           SZ_8K
 
+#define TEGRA_ARM_PL310_BASE           0x50043000
+#define TEGRA_ARM_PL310_SIZE           SZ_4K
+
 #define TEGRA_ARM_INT_DIST_BASE                0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE                SZ_4K
 
 #define TEGRA_FLOW_CTRL_BASE           0x60007000
 #define TEGRA_FLOW_CTRL_SIZE           20
 
-#define TEGRA_STATMON_BASE             0x6000C4000
+#define TEGRA_AHB_DMA_BASE             0x60008000
+#define TEGRA_AHB_DMA_SIZE             SZ_4K
+
+#define TEGRA_AHB_DMA_CH0_BASE         0x60009000
+#define TEGRA_AHB_DMA_CH0_SIZE         32
+
+#define TEGRA_APB_DMA_BASE             0x6000A000
+#define TEGRA_APB_DMA_SIZE             SZ_4K
+
+#define TEGRA_APB_DMA_CH0_BASE         0x6000B000
+#define TEGRA_APB_DMA_CH0_SIZE         32
+
+#define TEGRA_AHB_GIZMO_BASE           0x6000C004
+#define TEGRA_AHB_GIZMO_SIZE           0x10C
+
+#define TEGRA_STATMON_BASE             0x6000C400
 #define TEGRA_STATMON_SIZE             SZ_1K
 
 #define TEGRA_GPIO_BASE                        0x6000D000
 #define TEGRA_I2C3_BASE                        0x7000C500
 #define TEGRA_I2C3_SIZE                        SZ_256
 
-#define TEGRA_OWR_BASE                 0x7000D000
+#define TEGRA_OWR_BASE                 0x7000C600
 #define TEGRA_OWR_SIZE                 80
 
 #define TEGRA_DVC_BASE                 0x7000D000
 #define TEGRA_USB_BASE                 0xC5000000
 #define TEGRA_USB_SIZE                 SZ_16K
 
-#define TEGRA_USB1_BASE                        0xC5004000
-#define TEGRA_USB1_SIZE                        SZ_16K
-
-#define TEGRA_USB2_BASE                        0xC5008000
+#define TEGRA_USB2_BASE                        0xC5004000
 #define TEGRA_USB2_SIZE                        SZ_16K
 
+#define TEGRA_USB3_BASE                        0xC5008000
+#define TEGRA_USB3_SIZE                        SZ_16K
+
 #define TEGRA_SDMMC1_BASE              0xC8000000
 #define TEGRA_SDMMC1_SIZE              SZ_512
 
index 20f640e..71bbf34 100644 (file)
@@ -25,6 +25,7 @@
 
 #define IRQ_LOCALTIMER                  29
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 /* Primary Interrupt Controller */
 #define INT_PRI_BASE                   (INT_GIC_BASE + 32)
 #define INT_TMR1                       (INT_PRI_BASE + 0)
 #define INT_GPIO_NR                    (28 * 8)
 
 #define NR_IRQS                                (INT_GPIO_BASE + INT_GPIO_NR)
+#endif
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h
new file mode 100644 (file)
index 0000000..db1eb3d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-tegra/include/mach/legacy_irq.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+#define _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+
+void tegra_legacy_mask_irq(unsigned int irq);
+void tegra_legacy_unmask_irq(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+void tegra_legacy_force_irq_set(unsigned int irq);
+void tegra_legacy_force_irq_clr(unsigned int irq);
+int tegra_legacy_force_irq_status(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+unsigned long tegra_legacy_vfiq(int nr);
+unsigned long tegra_legacy_class(int nr);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
new file mode 100644 (file)
index 0000000..e5b9d74
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/pinmux-t2.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_PINMUX_T2_H
+#define __MACH_TEGRA_PINMUX_T2_H
+
+enum tegra_pingroup {
+       TEGRA_PINGROUP_ATA = 0,
+       TEGRA_PINGROUP_ATB,
+       TEGRA_PINGROUP_ATC,
+       TEGRA_PINGROUP_ATD,
+       TEGRA_PINGROUP_ATE,
+       TEGRA_PINGROUP_CDEV1,
+       TEGRA_PINGROUP_CDEV2,
+       TEGRA_PINGROUP_CRTP,
+       TEGRA_PINGROUP_CSUS,
+       TEGRA_PINGROUP_DAP1,
+       TEGRA_PINGROUP_DAP2,
+       TEGRA_PINGROUP_DAP3,
+       TEGRA_PINGROUP_DAP4,
+       TEGRA_PINGROUP_DDC,
+       TEGRA_PINGROUP_DTA,
+       TEGRA_PINGROUP_DTB,
+       TEGRA_PINGROUP_DTC,
+       TEGRA_PINGROUP_DTD,
+       TEGRA_PINGROUP_DTE,
+       TEGRA_PINGROUP_DTF,
+       TEGRA_PINGROUP_GMA,
+       TEGRA_PINGROUP_GMB,
+       TEGRA_PINGROUP_GMC,
+       TEGRA_PINGROUP_GMD,
+       TEGRA_PINGROUP_GME,
+       TEGRA_PINGROUP_GPU,
+       TEGRA_PINGROUP_GPU7,
+       TEGRA_PINGROUP_GPV,
+       TEGRA_PINGROUP_HDINT,
+       TEGRA_PINGROUP_I2CP,
+       TEGRA_PINGROUP_IRRX,
+       TEGRA_PINGROUP_IRTX,
+       TEGRA_PINGROUP_KBCA,
+       TEGRA_PINGROUP_KBCB,
+       TEGRA_PINGROUP_KBCC,
+       TEGRA_PINGROUP_KBCD,
+       TEGRA_PINGROUP_KBCE,
+       TEGRA_PINGROUP_KBCF,
+       TEGRA_PINGROUP_LCSN,
+       TEGRA_PINGROUP_LD0,
+       TEGRA_PINGROUP_LD1,
+       TEGRA_PINGROUP_LD10,
+       TEGRA_PINGROUP_LD11,
+       TEGRA_PINGROUP_LD12,
+       TEGRA_PINGROUP_LD13,
+       TEGRA_PINGROUP_LD14,
+       TEGRA_PINGROUP_LD15,
+       TEGRA_PINGROUP_LD16,
+       TEGRA_PINGROUP_LD17,
+       TEGRA_PINGROUP_LD2,
+       TEGRA_PINGROUP_LD3,
+       TEGRA_PINGROUP_LD4,
+       TEGRA_PINGROUP_LD5,
+       TEGRA_PINGROUP_LD6,
+       TEGRA_PINGROUP_LD7,
+       TEGRA_PINGROUP_LD8,
+       TEGRA_PINGROUP_LD9,
+       TEGRA_PINGROUP_LDC,
+       TEGRA_PINGROUP_LDI,
+       TEGRA_PINGROUP_LHP0,
+       TEGRA_PINGROUP_LHP1,
+       TEGRA_PINGROUP_LHP2,
+       TEGRA_PINGROUP_LHS,
+       TEGRA_PINGROUP_LM0,
+       TEGRA_PINGROUP_LM1,
+       TEGRA_PINGROUP_LPP,
+       TEGRA_PINGROUP_LPW0,
+       TEGRA_PINGROUP_LPW1,
+       TEGRA_PINGROUP_LPW2,
+       TEGRA_PINGROUP_LSC0,
+       TEGRA_PINGROUP_LSC1,
+       TEGRA_PINGROUP_LSCK,
+       TEGRA_PINGROUP_LSDA,
+       TEGRA_PINGROUP_LSDI,
+       TEGRA_PINGROUP_LSPI,
+       TEGRA_PINGROUP_LVP0,
+       TEGRA_PINGROUP_LVP1,
+       TEGRA_PINGROUP_LVS,
+       TEGRA_PINGROUP_OWC,
+       TEGRA_PINGROUP_PMC,
+       TEGRA_PINGROUP_PTA,
+       TEGRA_PINGROUP_RM,
+       TEGRA_PINGROUP_SDB,
+       TEGRA_PINGROUP_SDC,
+       TEGRA_PINGROUP_SDD,
+       TEGRA_PINGROUP_SDIO1,
+       TEGRA_PINGROUP_SLXA,
+       TEGRA_PINGROUP_SLXC,
+       TEGRA_PINGROUP_SLXD,
+       TEGRA_PINGROUP_SLXK,
+       TEGRA_PINGROUP_SPDI,
+       TEGRA_PINGROUP_SPDO,
+       TEGRA_PINGROUP_SPIA,
+       TEGRA_PINGROUP_SPIB,
+       TEGRA_PINGROUP_SPIC,
+       TEGRA_PINGROUP_SPID,
+       TEGRA_PINGROUP_SPIE,
+       TEGRA_PINGROUP_SPIF,
+       TEGRA_PINGROUP_SPIG,
+       TEGRA_PINGROUP_SPIH,
+       TEGRA_PINGROUP_UAA,
+       TEGRA_PINGROUP_UAB,
+       TEGRA_PINGROUP_UAC,
+       TEGRA_PINGROUP_UAD,
+       TEGRA_PINGROUP_UCA,
+       TEGRA_PINGROUP_UCB,
+       TEGRA_PINGROUP_UDA,
+       /* these pin groups only have pullup and pull down control */
+       TEGRA_PINGROUP_CK32,
+       TEGRA_PINGROUP_DDRC,
+       TEGRA_PINGROUP_PMCA,
+       TEGRA_PINGROUP_PMCB,
+       TEGRA_PINGROUP_PMCC,
+       TEGRA_PINGROUP_PMCD,
+       TEGRA_PINGROUP_PMCE,
+       TEGRA_PINGROUP_XM2C,
+       TEGRA_PINGROUP_XM2D,
+       TEGRA_MAX_PINGROUP,
+};
+
+enum tegra_drive_pingroup {
+       TEGRA_DRIVE_PINGROUP_AO1 = 0,
+       TEGRA_DRIVE_PINGROUP_AO2,
+       TEGRA_DRIVE_PINGROUP_AT1,
+       TEGRA_DRIVE_PINGROUP_AT2,
+       TEGRA_DRIVE_PINGROUP_CDEV1,
+       TEGRA_DRIVE_PINGROUP_CDEV2,
+       TEGRA_DRIVE_PINGROUP_CSUS,
+       TEGRA_DRIVE_PINGROUP_DAP1,
+       TEGRA_DRIVE_PINGROUP_DAP2,
+       TEGRA_DRIVE_PINGROUP_DAP3,
+       TEGRA_DRIVE_PINGROUP_DAP4,
+       TEGRA_DRIVE_PINGROUP_DBG,
+       TEGRA_DRIVE_PINGROUP_LCD1,
+       TEGRA_DRIVE_PINGROUP_LCD2,
+       TEGRA_DRIVE_PINGROUP_SDMMC2,
+       TEGRA_DRIVE_PINGROUP_SDMMC3,
+       TEGRA_DRIVE_PINGROUP_SPI,
+       TEGRA_DRIVE_PINGROUP_UAA,
+       TEGRA_DRIVE_PINGROUP_UAB,
+       TEGRA_DRIVE_PINGROUP_UART2,
+       TEGRA_DRIVE_PINGROUP_UART3,
+       TEGRA_DRIVE_PINGROUP_VI1,
+       TEGRA_DRIVE_PINGROUP_VI2,
+       TEGRA_DRIVE_PINGROUP_XM2A,
+       TEGRA_DRIVE_PINGROUP_XM2C,
+       TEGRA_DRIVE_PINGROUP_XM2D,
+       TEGRA_DRIVE_PINGROUP_XM2CLK,
+       TEGRA_DRIVE_PINGROUP_MEMCOMP,
+       TEGRA_MAX_DRIVE_PINGROUP,
+};
+
+#endif
+
index 41c8ce5..defd877 100644 (file)
 #ifndef __MACH_TEGRA_PINMUX_H
 #define __MACH_TEGRA_PINMUX_H
 
-enum tegra_pingroup {
-       TEGRA_PINGROUP_ATA = 0,
-       TEGRA_PINGROUP_ATB,
-       TEGRA_PINGROUP_ATC,
-       TEGRA_PINGROUP_ATD,
-       TEGRA_PINGROUP_ATE,
-       TEGRA_PINGROUP_CDEV1,
-       TEGRA_PINGROUP_CDEV2,
-       TEGRA_PINGROUP_CRTP,
-       TEGRA_PINGROUP_CSUS,
-       TEGRA_PINGROUP_DAP1,
-       TEGRA_PINGROUP_DAP2,
-       TEGRA_PINGROUP_DAP3,
-       TEGRA_PINGROUP_DAP4,
-       TEGRA_PINGROUP_DDC,
-       TEGRA_PINGROUP_DTA,
-       TEGRA_PINGROUP_DTB,
-       TEGRA_PINGROUP_DTC,
-       TEGRA_PINGROUP_DTD,
-       TEGRA_PINGROUP_DTE,
-       TEGRA_PINGROUP_DTF,
-       TEGRA_PINGROUP_GMA,
-       TEGRA_PINGROUP_GMB,
-       TEGRA_PINGROUP_GMC,
-       TEGRA_PINGROUP_GMD,
-       TEGRA_PINGROUP_GME,
-       TEGRA_PINGROUP_GPU,
-       TEGRA_PINGROUP_GPU7,
-       TEGRA_PINGROUP_GPV,
-       TEGRA_PINGROUP_HDINT,
-       TEGRA_PINGROUP_I2CP,
-       TEGRA_PINGROUP_IRRX,
-       TEGRA_PINGROUP_IRTX,
-       TEGRA_PINGROUP_KBCA,
-       TEGRA_PINGROUP_KBCB,
-       TEGRA_PINGROUP_KBCC,
-       TEGRA_PINGROUP_KBCD,
-       TEGRA_PINGROUP_KBCE,
-       TEGRA_PINGROUP_KBCF,
-       TEGRA_PINGROUP_LCSN,
-       TEGRA_PINGROUP_LD0,
-       TEGRA_PINGROUP_LD1,
-       TEGRA_PINGROUP_LD10,
-       TEGRA_PINGROUP_LD11,
-       TEGRA_PINGROUP_LD12,
-       TEGRA_PINGROUP_LD13,
-       TEGRA_PINGROUP_LD14,
-       TEGRA_PINGROUP_LD15,
-       TEGRA_PINGROUP_LD16,
-       TEGRA_PINGROUP_LD17,
-       TEGRA_PINGROUP_LD2,
-       TEGRA_PINGROUP_LD3,
-       TEGRA_PINGROUP_LD4,
-       TEGRA_PINGROUP_LD5,
-       TEGRA_PINGROUP_LD6,
-       TEGRA_PINGROUP_LD7,
-       TEGRA_PINGROUP_LD8,
-       TEGRA_PINGROUP_LD9,
-       TEGRA_PINGROUP_LDC,
-       TEGRA_PINGROUP_LDI,
-       TEGRA_PINGROUP_LHP0,
-       TEGRA_PINGROUP_LHP1,
-       TEGRA_PINGROUP_LHP2,
-       TEGRA_PINGROUP_LHS,
-       TEGRA_PINGROUP_LM0,
-       TEGRA_PINGROUP_LM1,
-       TEGRA_PINGROUP_LPP,
-       TEGRA_PINGROUP_LPW0,
-       TEGRA_PINGROUP_LPW1,
-       TEGRA_PINGROUP_LPW2,
-       TEGRA_PINGROUP_LSC0,
-       TEGRA_PINGROUP_LSC1,
-       TEGRA_PINGROUP_LSCK,
-       TEGRA_PINGROUP_LSDA,
-       TEGRA_PINGROUP_LSDI,
-       TEGRA_PINGROUP_LSPI,
-       TEGRA_PINGROUP_LVP0,
-       TEGRA_PINGROUP_LVP1,
-       TEGRA_PINGROUP_LVS,
-       TEGRA_PINGROUP_OWC,
-       TEGRA_PINGROUP_PMC,
-       TEGRA_PINGROUP_PTA,
-       TEGRA_PINGROUP_RM,
-       TEGRA_PINGROUP_SDB,
-       TEGRA_PINGROUP_SDC,
-       TEGRA_PINGROUP_SDD,
-       TEGRA_PINGROUP_SDIO1,
-       TEGRA_PINGROUP_SLXA,
-       TEGRA_PINGROUP_SLXC,
-       TEGRA_PINGROUP_SLXD,
-       TEGRA_PINGROUP_SLXK,
-       TEGRA_PINGROUP_SPDI,
-       TEGRA_PINGROUP_SPDO,
-       TEGRA_PINGROUP_SPIA,
-       TEGRA_PINGROUP_SPIB,
-       TEGRA_PINGROUP_SPIC,
-       TEGRA_PINGROUP_SPID,
-       TEGRA_PINGROUP_SPIE,
-       TEGRA_PINGROUP_SPIF,
-       TEGRA_PINGROUP_SPIG,
-       TEGRA_PINGROUP_SPIH,
-       TEGRA_PINGROUP_UAA,
-       TEGRA_PINGROUP_UAB,
-       TEGRA_PINGROUP_UAC,
-       TEGRA_PINGROUP_UAD,
-       TEGRA_PINGROUP_UCA,
-       TEGRA_PINGROUP_UCB,
-       TEGRA_PINGROUP_UDA,
-       /* these pin groups only have pullup and pull down control */
-       TEGRA_PINGROUP_CK32,
-       TEGRA_PINGROUP_DDRC,
-       TEGRA_PINGROUP_PMCA,
-       TEGRA_PINGROUP_PMCB,
-       TEGRA_PINGROUP_PMCC,
-       TEGRA_PINGROUP_PMCD,
-       TEGRA_PINGROUP_PMCE,
-       TEGRA_PINGROUP_XM2C,
-       TEGRA_PINGROUP_XM2D,
-       TEGRA_MAX_PINGROUP,
-};
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#include "pinmux-t2.h"
+#else
+#error "Undefined Tegra architecture"
+#endif
 
 enum tegra_mux_func {
        TEGRA_MUX_RSVD = 0x8000,
@@ -205,6 +90,7 @@ enum tegra_mux_func {
        TEGRA_MUX_VI,
        TEGRA_MUX_VI_SENSOR_CLK,
        TEGRA_MUX_XIO,
+       TEGRA_MUX_SAFE,
        TEGRA_MAX_MUX,
 };
 
@@ -219,6 +105,18 @@ enum tegra_tristate {
        TEGRA_TRI_TRISTATE = 1,
 };
 
+enum tegra_vddio {
+       TEGRA_VDDIO_BB = 0,
+       TEGRA_VDDIO_LCD,
+       TEGRA_VDDIO_VI,
+       TEGRA_VDDIO_UART,
+       TEGRA_VDDIO_DDR,
+       TEGRA_VDDIO_NAND,
+       TEGRA_VDDIO_SYS,
+       TEGRA_VDDIO_AUDIO,
+       TEGRA_VDDIO_SD,
+};
+
 struct tegra_pingroup_config {
        enum tegra_pingroup     pingroup;
        enum tegra_mux_func     func;
@@ -270,38 +168,6 @@ enum tegra_pull_strength {
        TEGRA_MAX_PULL,
 };
 
-enum tegra_drive_pingroup {
-       TEGRA_DRIVE_PINGROUP_AO1 = 0,
-       TEGRA_DRIVE_PINGROUP_AO2,
-       TEGRA_DRIVE_PINGROUP_AT1,
-       TEGRA_DRIVE_PINGROUP_AT2,
-       TEGRA_DRIVE_PINGROUP_CDEV1,
-       TEGRA_DRIVE_PINGROUP_CDEV2,
-       TEGRA_DRIVE_PINGROUP_CSUS,
-       TEGRA_DRIVE_PINGROUP_DAP1,
-       TEGRA_DRIVE_PINGROUP_DAP2,
-       TEGRA_DRIVE_PINGROUP_DAP3,
-       TEGRA_DRIVE_PINGROUP_DAP4,
-       TEGRA_DRIVE_PINGROUP_DBG,
-       TEGRA_DRIVE_PINGROUP_LCD1,
-       TEGRA_DRIVE_PINGROUP_LCD2,
-       TEGRA_DRIVE_PINGROUP_SDMMC2,
-       TEGRA_DRIVE_PINGROUP_SDMMC3,
-       TEGRA_DRIVE_PINGROUP_SPI,
-       TEGRA_DRIVE_PINGROUP_UAA,
-       TEGRA_DRIVE_PINGROUP_UAB,
-       TEGRA_DRIVE_PINGROUP_UART2,
-       TEGRA_DRIVE_PINGROUP_UART3,
-       TEGRA_DRIVE_PINGROUP_VI1,
-       TEGRA_DRIVE_PINGROUP_VI2,
-       TEGRA_DRIVE_PINGROUP_XM2A,
-       TEGRA_DRIVE_PINGROUP_XM2C,
-       TEGRA_DRIVE_PINGROUP_XM2D,
-       TEGRA_DRIVE_PINGROUP_XM2CLK,
-       TEGRA_DRIVE_PINGROUP_MEMCOMP,
-       TEGRA_MAX_DRIVE_PINGROUP,
-};
-
 enum tegra_drive {
        TEGRA_DRIVE_DIV_8 = 0,
        TEGRA_DRIVE_DIV_4,
@@ -331,18 +197,44 @@ struct tegra_drive_pingroup_config {
        enum tegra_slew slew_falling;
 };
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func);
-int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate);
-int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd);
+struct tegra_drive_pingroup_desc {
+       const char *name;
+       s16 reg;
+};
+
+struct tegra_pingroup_desc {
+       const char *name;
+       int funcs[4];
+       int func_safe;
+       int vddio;
+       s16 tri_reg;    /* offset into the TRISTATE_REG_* register bank */
+       s16 mux_reg;    /* offset into the PIN_MUX_CTL_* register bank */
+       s16 pupd_reg;   /* offset into the PULL_UPDOWN_REG_* register bank */
+       s8 tri_bit;     /* offset into the TRISTATE_REG_* register bit */
+       s8 mux_bit;     /* offset into the PIN_MUX_CTL_* register bit */
+       s8 pupd_bit;    /* offset into the PULL_UPDOWN_REG_* register bit */
+};
+
+extern const struct tegra_pingroup_desc tegra_soc_pingroups[];
+extern const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[];
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-       enum tegra_mux_func func, enum tegra_pullupdown pupd,
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
        enum tegra_tristate tristate);
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
+       enum tegra_pullupdown pupd);
 
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len);
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config,
+       int len);
 
 void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
        int len);
-
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+       int len);
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+       int len);
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_tristate tristate);
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_pullupdown pupd);
 #endif
 
index 9fe2c5c..31848a9 100644 (file)
@@ -49,6 +49,12 @@ static struct map_desc tegra_io_desc[] __initdata = {
                .length = IO_CPU_SIZE,
                .type = MT_DEVICE,
        },
+       {
+               .virtual = IO_IRAM_VIRT,
+               .pfn = __phys_to_pfn(IO_IRAM_PHYS),
+               .length = IO_IRAM_SIZE,
+               .type = MT_DEVICE,
+       },
 };
 
 void __init tegra_map_common_io(void)
index 1fdbe70..50a8dfb 100644 (file)
@@ -4,6 +4,8 @@
  * Author:
  *     Colin Cross <ccross@google.com>
  *
+ * Copyright (C) 2010, NVIDIA Corporation
+ *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
  * may be copied, distributed, and modified under those terms.
 
 #include "board.h"
 
+#define INT_SYS_NR     (INT_GPIO_BASE - INT_PRI_BASE)
+#define INT_SYS_SZ     (INT_SEC_BASE - INT_PRI_BASE)
+#define PPI_NR         ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+
+#define APBDMA_IRQ_STA_CPU  0x14
+#define APBDMA_IRQ_MASK_SET 0x20
+#define APBDMA_IRQ_MASK_CLR 0x24
+
+#define ICTLR_CPU_IER          0x20
+#define ICTLR_CPU_IER_SET      0x24
+#define ICTLR_CPU_IER_CLR      0x28
+#define ICTLR_CPU_IEP_CLASS    0x2c
+#define ICTLR_COP_IER          0x30
+#define ICTLR_COP_IER_SET      0x34
+#define ICTLR_COP_IER_CLR      0x38
+#define ICTLR_COP_IEP_CLASS    0x3c
+
+static void (*gic_mask_irq)(unsigned int irq);
+static void (*gic_unmask_irq)(unsigned int irq);
+
+#define irq_to_ictlr(irq) (((irq)-32) >> 5)
+static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
+#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100)
+
+static void tegra_mask(unsigned int irq)
+{
+       void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+       gic_mask_irq(irq);
+       writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR);
+}
+
+static void tegra_unmask(unsigned int irq)
+{
+       void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+       gic_unmask_irq(irq);
+       writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET);
+}
+
+#ifdef CONFIG_PM
+
+static int tegra_set_wake(unsigned int irq, unsigned int on)
+{
+       return 0;
+}
+#endif
+
+static struct irq_chip tegra_irq = {
+       .name           = "PPI",
+       .mask           = tegra_mask,
+       .unmask         = tegra_unmask,
+#ifdef CONFIG_PM
+       .set_wake       = tegra_set_wake,
+#endif
+};
+
 void __init tegra_init_irq(void)
 {
+       struct irq_chip *gic;
+       unsigned int i;
+
+       for (i = 0; i < PPI_NR; i++) {
+               writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
+               writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
+       }
+
        gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
        gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+
+       gic = get_irq_chip(29);
+       gic_unmask_irq = gic->unmask;
+       gic_mask_irq = gic->mask;
+       tegra_irq.ack = gic->ack;
+#ifdef CONFIG_SMP
+       tegra_irq.set_affinity = gic->set_affinity;
+#endif
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               set_irq_chip(i, &tegra_irq);
+               set_irq_handler(i, handle_level_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+}
+
+#ifdef CONFIG_PM
+static u32 cop_ier[PPI_NR];
+static u32 cpu_ier[PPI_NR];
+static u32 cpu_iep[PPI_NR];
+
+void tegra_irq_suspend(void)
+{
+       unsigned long flags;
+       int i;
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc)
+                       continue;
+               if (desc->status & IRQ_WAKEUP) {
+                       pr_debug("irq %d is wakeup\n", i);
+                       continue;
+               }
+               disable_irq(i);
+       }
+
+       local_irq_save(flags);
+       for (i = 0; i < PPI_NR; i++) {
+               void __iomem *ictlr = ictlr_to_virt(i);
+               cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
+               cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
+               cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+               writel(~0, ictlr + ICTLR_COP_IER_CLR);
+       }
+       local_irq_restore(flags);
+}
+
+void tegra_irq_resume(void)
+{
+       unsigned long flags;
+       int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < PPI_NR; i++) {
+               void __iomem *ictlr = ictlr_to_virt(i);
+               writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+               writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+               writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+               writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+               writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
+               writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+       }
+       local_irq_restore(flags);
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc || (desc->status & IRQ_WAKEUP))
+                       continue;
+               enable_irq(i);
+       }
 }
+#endif
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c
new file mode 100644 (file)
index 0000000..7cc8601
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-tegra/legacy_irq.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/iomap.h>
+#include <mach/legacy_irq.h>
+
+#define ICTLR_CPU_IER          0x20
+#define ICTLR_CPU_IER_SET      0x24
+#define ICTLR_CPU_IER_CLR      0x28
+#define ICTLR_CPU_IEP_CLASS    0x2C
+#define ICTLR_CPU_IEP_VFIQ     0x08
+#define ICTLR_CPU_IEP_FIR      0x14
+#define ICTLR_CPU_IEP_FIR_SET  0x18
+#define ICTLR_CPU_IEP_FIR_CLR  0x1c
+
+static void __iomem *ictlr_reg_base[] = {
+       IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
+};
+
+/* When going into deep sleep, the CPU is powered down, taking the GIC with it
+   In order to wake, the wake interrupts need to be enabled in the legacy
+   interrupt controller. */
+void tegra_legacy_unmask_irq(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IER_SET);
+}
+
+void tegra_legacy_mask_irq(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IER_CLR);
+}
+
+void tegra_legacy_force_irq_set(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_SET);
+}
+
+void tegra_legacy_force_irq_clr(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_CLR);
+}
+
+int tegra_legacy_force_irq_status(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       return !!(readl(base + ICTLR_CPU_IEP_FIR) & (1 << (irq & 31)));
+}
+
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(fiq << (irq & 31), base + ICTLR_CPU_IEP_CLASS);
+}
+
+unsigned long tegra_legacy_vfiq(int nr)
+{
+       void __iomem *base;
+       base = ictlr_reg_base[nr];
+       return readl(base + ICTLR_CPU_IEP_VFIQ);
+}
+
+unsigned long tegra_legacy_class(int nr)
+{
+       void __iomem *base;
+       base = ictlr_reg_base[nr];
+       return readl(base + ICTLR_CPU_IEP_CLASS);
+}
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
new file mode 100644 (file)
index 0000000..53f5fa3
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * arch/arm/mach-tegra/pci.c
+ *
+ * PCIe host controller driver for TEGRA(2) SOCs
+ *
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * Bits taken from arch/arm/mach-dove/pcie.c
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <asm/sizes.h>
+#include <asm/mach/pci.h>
+
+#include <mach/pinmux.h>
+#include <mach/iomap.h>
+#include <mach/clk.h>
+
+/* register definitions */
+#define AFI_OFFSET     0x3800
+#define PADS_OFFSET    0x3000
+#define RP0_OFFSET     0x0000
+#define RP1_OFFSET     0x1000
+
+#define AFI_AXI_BAR0_SZ        0x00
+#define AFI_AXI_BAR1_SZ        0x04
+#define AFI_AXI_BAR2_SZ        0x08
+#define AFI_AXI_BAR3_SZ        0x0c
+#define AFI_AXI_BAR4_SZ        0x10
+#define AFI_AXI_BAR5_SZ        0x14
+
+#define AFI_AXI_BAR0_START     0x18
+#define AFI_AXI_BAR1_START     0x1c
+#define AFI_AXI_BAR2_START     0x20
+#define AFI_AXI_BAR3_START     0x24
+#define AFI_AXI_BAR4_START     0x28
+#define AFI_AXI_BAR5_START     0x2c
+
+#define AFI_FPCI_BAR0  0x30
+#define AFI_FPCI_BAR1  0x34
+#define AFI_FPCI_BAR2  0x38
+#define AFI_FPCI_BAR3  0x3c
+#define AFI_FPCI_BAR4  0x40
+#define AFI_FPCI_BAR5  0x44
+
+#define AFI_CACHE_BAR0_SZ      0x48
+#define AFI_CACHE_BAR0_ST      0x4c
+#define AFI_CACHE_BAR1_SZ      0x50
+#define AFI_CACHE_BAR1_ST      0x54
+
+#define AFI_MSI_BAR_SZ         0x60
+#define AFI_MSI_FPCI_BAR_ST    0x64
+#define AFI_MSI_AXI_BAR_ST     0x68
+
+#define AFI_CONFIGURATION              0xac
+#define  AFI_CONFIGURATION_EN_FPCI     (1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS   0xb0
+
+#define AFI_INTR_MASK          0xb4
+#define  AFI_INTR_MASK_INT_MASK        (1 << 0)
+#define  AFI_INTR_MASK_MSI_MASK        (1 << 8)
+
+#define AFI_INTR_CODE          0xb8
+#define  AFI_INTR_CODE_MASK    0xf
+#define  AFI_INTR_MASTER_ABORT 4
+#define  AFI_INTR_LEGACY       6
+
+#define AFI_INTR_SIGNATURE     0xbc
+#define AFI_SM_INTR_ENABLE     0xc4
+
+#define AFI_AFI_INTR_ENABLE            0xc8
+#define  AFI_INTR_EN_INI_SLVERR                (1 << 0)
+#define  AFI_INTR_EN_INI_DECERR                (1 << 1)
+#define  AFI_INTR_EN_TGT_SLVERR                (1 << 2)
+#define  AFI_INTR_EN_TGT_DECERR                (1 << 3)
+#define  AFI_INTR_EN_TGT_WRERR         (1 << 4)
+#define  AFI_INTR_EN_DFPCI_DECERR      (1 << 5)
+#define  AFI_INTR_EN_AXI_DECERR                (1 << 6)
+#define  AFI_INTR_EN_FPCI_TIMEOUT      (1 << 7)
+
+#define AFI_PCIE_CONFIG                                        0x0f8
+#define  AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE         (1 << 1)
+#define  AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE         (1 << 2)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK      (0xf << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE    (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL      (0x1 << 20)
+
+#define AFI_FUSE                       0x104
+#define  AFI_FUSE_PCIE_T0_GEN2_DIS     (1 << 2)
+
+#define AFI_PEX0_CTRL                  0x110
+#define AFI_PEX1_CTRL                  0x118
+#define  AFI_PEX_CTRL_RST              (1 << 0)
+#define  AFI_PEX_CTRL_REFCLK_EN                (1 << 3)
+
+#define RP_VEND_XP     0x00000F00
+#define  RP_VEND_XP_DL_UP      (1 << 30)
+
+#define RP_LINK_CONTROL_STATUS                 0x00000090
+#define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK  0x3fff0000
+
+#define PADS_CTL_SEL           0x0000009C
+
+#define PADS_CTL               0x000000A0
+#define  PADS_CTL_IDDQ_1L      (1 << 0)
+#define  PADS_CTL_TX_DATA_EN_1L        (1 << 6)
+#define  PADS_CTL_RX_DATA_EN_1L        (1 << 10)
+
+#define PADS_PLL_CTL                           0x000000B8
+#define  PADS_PLL_CTL_RST_B4SM                 (1 << 1)
+#define  PADS_PLL_CTL_LOCKDET                  (1 << 8)
+#define  PADS_PLL_CTL_REFCLK_MASK              (0x3 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CML      (0 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CMOS     (1 << 16)
+#define  PADS_PLL_CTL_REFCLK_EXTERNAL          (2 << 16)
+#define  PADS_PLL_CTL_TXCLKREF_MASK            (0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV10           (0 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV5            (1 << 20)
+
+/* PMC access is required for PCIE xclk (un)clamping */
+#define PMC_SCRATCH42          0x144
+#define PMC_SCRATCH42_PCX_CLAMP        (1 << 0)
+
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+#define pmc_writel(value, reg) \
+       __raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+       __raw_readl((u32)reg_pmc_base + (reg))
+
+/*
+ * Tegra2 defines 1GB in the AXI address map for PCIe.
+ *
+ * That address space is split into different regions, with sizes and
+ * offsets as follows:
+ *
+ * 0x80000000 - 0x80003fff - PCI controller registers
+ * 0x80004000 - 0x80103fff - PCI configuration space
+ * 0x80104000 - 0x80203fff - PCI extended configuration space
+ * 0x80203fff - 0x803fffff - unused
+ * 0x80400000 - 0x8040ffff - downstream IO
+ * 0x80410000 - 0x8fffffff - unused
+ * 0x90000000 - 0x9fffffff - non-prefetchable memory
+ * 0xa0000000 - 0xbfffffff - prefetchable memory
+ */
+#define TEGRA_PCIE_BASE                0x80000000
+
+#define PCIE_REGS_SZ           SZ_16K
+#define PCIE_CFG_OFF           PCIE_REGS_SZ
+#define PCIE_CFG_SZ            SZ_1M
+#define PCIE_EXT_CFG_OFF       (PCIE_CFG_SZ + PCIE_CFG_OFF)
+#define PCIE_EXT_CFG_SZ                SZ_1M
+#define PCIE_IOMAP_SZ          (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
+
+#define MMIO_BASE              (TEGRA_PCIE_BASE + SZ_4M)
+#define MMIO_SIZE              SZ_64K
+#define MEM_BASE_0             (TEGRA_PCIE_BASE + SZ_256M)
+#define MEM_SIZE_0             SZ_128M
+#define MEM_BASE_1             (MEM_BASE_0 + MEM_SIZE_0)
+#define MEM_SIZE_1             SZ_128M
+#define PREFETCH_MEM_BASE_0    (MEM_BASE_1 + MEM_SIZE_1)
+#define PREFETCH_MEM_SIZE_0    SZ_128M
+#define PREFETCH_MEM_BASE_1    (PREFETCH_MEM_BASE_0 + PREFETCH_MEM_SIZE_0)
+#define PREFETCH_MEM_SIZE_1    SZ_128M
+
+#define  PCIE_CONF_BUS(b)      ((b) << 16)
+#define  PCIE_CONF_DEV(d)      ((d) << 11)
+#define  PCIE_CONF_FUNC(f)     ((f) << 8)
+#define  PCIE_CONF_REG(r)      \
+       (((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF))
+
+struct tegra_pcie_port {
+       int                     index;
+       u8                      root_bus_nr;
+       void __iomem            *base;
+
+       bool                    link_up;
+
+       char                    io_space_name[16];
+       char                    mem_space_name[16];
+       char                    prefetch_space_name[20];
+       struct resource         res[3];
+};
+
+struct tegra_pcie_info {
+       struct tegra_pcie_port  port[2];
+       int                     num_ports;
+
+       void __iomem            *regs;
+       struct resource         res_mmio;
+
+       struct clk              *pex_clk;
+       struct clk              *afi_clk;
+       struct clk              *pcie_xclk;
+       struct clk              *pll_e;
+};
+
+static struct tegra_pcie_info tegra_pcie = {
+       .res_mmio = {
+               .name = "PCI IO",
+               .start = MMIO_BASE,
+               .end = MMIO_BASE + MMIO_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+void __iomem *tegra_pcie_io_base;
+EXPORT_SYMBOL(tegra_pcie_io_base);
+
+static inline void afi_writel(u32 value, unsigned long offset)
+{
+       writel(value, offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 afi_readl(unsigned long offset)
+{
+       return readl(offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline void pads_writel(u32 value, unsigned long offset)
+{
+       writel(value, offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 pads_readl(unsigned long offset)
+{
+       return readl(offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static struct tegra_pcie_port *bus_to_port(int bus)
+{
+       int i;
+
+       for (i = tegra_pcie.num_ports - 1; i >= 0; i--) {
+               int rbus = tegra_pcie.port[i].root_bus_nr;
+               if (rbus != -1 && rbus == bus)
+                       break;
+       }
+
+       return i >= 0 ? tegra_pcie.port + i : NULL;
+}
+
+static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
+                               int where, int size, u32 *val)
+{
+       struct tegra_pcie_port *pp = bus_to_port(bus->number);
+       void __iomem *addr;
+
+       if (pp) {
+               if (devfn != 0) {
+                       *val = 0xffffffff;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+
+               addr = pp->base + (where & ~0x3);
+       } else {
+               addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+                                         PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+                                         PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+                                         PCIE_CONF_REG(where));
+       }
+
+       *val = readl(addr);
+
+       if (size == 1)
+               *val = (*val >> (8 * (where & 3))) & 0xff;
+       else if (size == 2)
+               *val = (*val >> (8 * (where & 3))) & 0xffff;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 val)
+{
+       struct tegra_pcie_port *pp = bus_to_port(bus->number);
+       void __iomem *addr;
+
+       u32 mask;
+       u32 tmp;
+
+       if (pp) {
+               if (devfn != 0)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+               addr = pp->base + (where & ~0x3);
+       } else {
+               addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+                                         PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+                                         PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+                                         PCIE_CONF_REG(where));
+       }
+
+       if (size == 4) {
+               writel(val, addr);
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       if (size == 2)
+               mask = ~(0xffff << ((where & 0x3) * 8));
+       else if (size == 1)
+               mask = ~(0xff << ((where & 0x3) * 8));
+       else
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       tmp = readl(addr) & mask;
+       tmp |= val << ((where & 0x3) * 8);
+       writel(tmp, addr);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops tegra_pcie_ops = {
+       .read   = tegra_pcie_read_conf,
+       .write  = tegra_pcie_write_conf,
+};
+
+static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev)
+{
+       u16 reg;
+
+       if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+               pci_read_config_word(dev, PCI_COMMAND, &reg);
+               reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                       PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+               pci_write_config_word(dev, PCI_COMMAND, reg);
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge);
+
+/* Tegra PCIE root complex wrongly reports device class */
+static void __devinit tegra_pcie_fixup_class(struct pci_dev *dev)
+{
+       dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
+
+/* Tegra PCIE requires relaxed ordering */
+static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
+{
+       u16 val16;
+       int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+
+       if (pos <= 0) {
+               dev_err(&dev->dev, "skipping relaxed ordering fixup\n");
+               return;
+       }
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16);
+       val16 |= PCI_EXP_DEVCTL_RELAX_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
+
+static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+       struct tegra_pcie_port *pp;
+
+       if (nr >= tegra_pcie.num_ports)
+               return 0;
+
+       pp = tegra_pcie.port + nr;
+       pp->root_bus_nr = sys->busnr;
+
+       /*
+        * IORESOURCE_IO
+        */
+       snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+                "PCIe %d I/O", pp->index);
+       pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+       pp->res[0].name = pp->io_space_name;
+       if (pp->index == 0) {
+               pp->res[0].start = PCIBIOS_MIN_IO;
+               pp->res[0].end = pp->res[0].start + SZ_32K - 1;
+       } else {
+               pp->res[0].start = PCIBIOS_MIN_IO + SZ_32K;
+               pp->res[0].end = IO_SPACE_LIMIT;
+       }
+       pp->res[0].flags = IORESOURCE_IO;
+       if (request_resource(&ioport_resource, &pp->res[0]))
+               panic("Request PCIe IO resource failed\n");
+       sys->resource[0] = &pp->res[0];
+
+       /*
+        * IORESOURCE_MEM
+        */
+       snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+                "PCIe %d MEM", pp->index);
+       pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+       pp->res[1].name = pp->mem_space_name;
+       if (pp->index == 0) {
+               pp->res[1].start = MEM_BASE_0;
+               pp->res[1].end = pp->res[1].start + MEM_SIZE_0 - 1;
+       } else {
+               pp->res[1].start = MEM_BASE_1;
+               pp->res[1].end = pp->res[1].start + MEM_SIZE_1 - 1;
+       }
+       pp->res[1].flags = IORESOURCE_MEM;
+       if (request_resource(&iomem_resource, &pp->res[1]))
+               panic("Request PCIe Memory resource failed\n");
+       sys->resource[1] = &pp->res[1];
+
+       /*
+        * IORESOURCE_MEM | IORESOURCE_PREFETCH
+        */
+       snprintf(pp->prefetch_space_name, sizeof(pp->prefetch_space_name),
+                "PCIe %d PREFETCH MEM", pp->index);
+       pp->prefetch_space_name[sizeof(pp->prefetch_space_name) - 1] = 0;
+       pp->res[2].name = pp->prefetch_space_name;
+       if (pp->index == 0) {
+               pp->res[2].start = PREFETCH_MEM_BASE_0;
+               pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_0 - 1;
+       } else {
+               pp->res[2].start = PREFETCH_MEM_BASE_1;
+               pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_1 - 1;
+       }
+       pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+       if (request_resource(&iomem_resource, &pp->res[2]))
+               panic("Request PCIe Prefetch Memory resource failed\n");
+       sys->resource[2] = &pp->res[2];
+
+       return 1;
+}
+
+static int tegra_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return INT_PCIE_INTR;
+}
+
+static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
+                                                 struct pci_sys_data *sys)
+{
+       struct tegra_pcie_port *pp;
+
+       if (nr >= tegra_pcie.num_ports)
+               return 0;
+
+       pp = tegra_pcie.port + nr;
+       pp->root_bus_nr = sys->busnr;
+
+       return pci_scan_bus(sys->busnr, &tegra_pcie_ops, sys);
+}
+
+static struct hw_pci tegra_pcie_hw __initdata = {
+       .nr_controllers = 2,
+       .setup          = tegra_pcie_setup,
+       .scan           = tegra_pcie_scan_bus,
+       .swizzle        = pci_std_swizzle,
+       .map_irq        = tegra_pcie_map_irq,
+};
+
+
+static irqreturn_t tegra_pcie_isr(int irq, void *arg)
+{
+       const char *err_msg[] = {
+               "Unknown",
+               "AXI slave error",
+               "AXI decode error",
+               "Target abort",
+               "Master abort",
+               "Invalid write",
+               "Response decoding error",
+               "AXI response decoding error",
+               "Transcation timeout",
+       };
+
+       u32 code, signature;
+
+       code = afi_readl(AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
+       signature = afi_readl(AFI_INTR_SIGNATURE);
+       afi_writel(0, AFI_INTR_CODE);
+
+       if (code == AFI_INTR_LEGACY)
+               return IRQ_NONE;
+
+       if (code >= ARRAY_SIZE(err_msg))
+               code = 0;
+
+       /*
+        * do not pollute kernel log with master abort reports since they
+        * happen a lot during enumeration
+        */
+       if (code == AFI_INTR_MASTER_ABORT)
+               pr_debug("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+       else
+               pr_err("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+
+       return IRQ_HANDLED;
+}
+
+static void tegra_pcie_setup_translations(void)
+{
+       u32 fpci_bar;
+       u32 size;
+       u32 axi_address;
+
+       /* Bar 0: config Bar */
+       fpci_bar = ((u32)0xfdff << 16);
+       size = PCIE_CFG_SZ;
+       axi_address = TEGRA_PCIE_BASE + PCIE_CFG_OFF;
+       afi_writel(axi_address, AFI_AXI_BAR0_START);
+       afi_writel(size >> 12, AFI_AXI_BAR0_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR0);
+
+       /* Bar 1: extended config Bar */
+       fpci_bar = ((u32)0xfe1 << 20);
+       size = PCIE_EXT_CFG_SZ;
+       axi_address = TEGRA_PCIE_BASE + PCIE_EXT_CFG_OFF;
+       afi_writel(axi_address, AFI_AXI_BAR1_START);
+       afi_writel(size >> 12, AFI_AXI_BAR1_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR1);
+
+       /* Bar 2: downstream IO bar */
+       fpci_bar = ((__u32)0xfdfc << 16);
+       size = MMIO_SIZE;
+       axi_address = MMIO_BASE;
+       afi_writel(axi_address, AFI_AXI_BAR2_START);
+       afi_writel(size >> 12, AFI_AXI_BAR2_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR2);
+
+       /* Bar 3: prefetchable memory BAR */
+       fpci_bar = (((PREFETCH_MEM_BASE_0 >> 12) & 0x0fffffff) << 4) | 0x1;
+       size =  PREFETCH_MEM_SIZE_0 +  PREFETCH_MEM_SIZE_1;
+       axi_address = PREFETCH_MEM_BASE_0;
+       afi_writel(axi_address, AFI_AXI_BAR3_START);
+       afi_writel(size >> 12, AFI_AXI_BAR3_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR3);
+
+       /* Bar 4: non prefetchable memory BAR */
+       fpci_bar = (((MEM_BASE_0 >> 12) & 0x0FFFFFFF) << 4) | 0x1;
+       size = MEM_SIZE_0 + MEM_SIZE_1;
+       axi_address = MEM_BASE_0;
+       afi_writel(axi_address, AFI_AXI_BAR4_START);
+       afi_writel(size >> 12, AFI_AXI_BAR4_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR4);
+
+       /* Bar 5: NULL out the remaining BAR as it is not used */
+       fpci_bar = 0;
+       size = 0;
+       axi_address = 0;
+       afi_writel(axi_address, AFI_AXI_BAR5_START);
+       afi_writel(size >> 12, AFI_AXI_BAR5_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR5);
+
+       /* map all upstream transactions as uncached */
+       afi_writel(PHYS_OFFSET, AFI_CACHE_BAR0_ST);
+       afi_writel(0, AFI_CACHE_BAR0_SZ);
+       afi_writel(0, AFI_CACHE_BAR1_ST);
+       afi_writel(0, AFI_CACHE_BAR1_SZ);
+
+       /* No MSI */
+       afi_writel(0, AFI_MSI_FPCI_BAR_ST);
+       afi_writel(0, AFI_MSI_BAR_SZ);
+       afi_writel(0, AFI_MSI_AXI_BAR_ST);
+       afi_writel(0, AFI_MSI_BAR_SZ);
+}
+
+static void tegra_pcie_enable_controller(void)
+{
+       u32 val, reg;
+       int i;
+
+       /* Enable slot clock and pulse the reset signals */
+       for (i = 0, reg = AFI_PEX0_CTRL; i < 2; i++, reg += 0x8) {
+               val = afi_readl(reg) |  AFI_PEX_CTRL_REFCLK_EN;
+               afi_writel(val, reg);
+               val &= ~AFI_PEX_CTRL_RST;
+               afi_writel(val, reg);
+
+               val = afi_readl(reg) | AFI_PEX_CTRL_RST;
+               afi_writel(val, reg);
+       }
+
+       /* Enable dual controller and both ports */
+       val = afi_readl(AFI_PCIE_CONFIG);
+       val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE |
+                AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE |
+                AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK);
+       val |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL;
+       afi_writel(val, AFI_PCIE_CONFIG);
+
+       val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+       afi_writel(val, AFI_FUSE);
+
+       /* Initialze internal PHY, enable up to 16 PCIE lanes */
+       pads_writel(0x0, PADS_CTL_SEL);
+
+       /* override IDDQ to 1 on all 4 lanes */
+       val = pads_readl(PADS_CTL) | PADS_CTL_IDDQ_1L;
+       pads_writel(val, PADS_CTL);
+
+       /*
+        * set up PHY PLL inputs select PLLE output as refclock,
+        * set TX ref sel to div10 (not div5)
+        */
+       val = pads_readl(PADS_PLL_CTL);
+       val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
+       val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10);
+       pads_writel(val, PADS_PLL_CTL);
+
+       /* take PLL out of reset  */
+       val = pads_readl(PADS_PLL_CTL) | PADS_PLL_CTL_RST_B4SM;
+       pads_writel(val, PADS_PLL_CTL);
+
+       /*
+        * Hack, set the clock voltage to the DEFAULT provided by hw folks.
+        * This doesn't exist in the documentation
+        */
+       pads_writel(0xfa5cfa5c, 0xc8);
+
+       /* Wait for the PLL to lock */
+       do {
+               val = pads_readl(PADS_PLL_CTL);
+       } while (!(val & PADS_PLL_CTL_LOCKDET));
+
+       /* turn off IDDQ override */
+       val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L;
+       pads_writel(val, PADS_CTL);
+
+       /* enable TX/RX data */
+       val = pads_readl(PADS_CTL);
+       val |= (PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L);
+       pads_writel(val, PADS_CTL);
+
+       /* Take the PCIe interface module out of reset */
+       tegra_periph_reset_deassert(tegra_pcie.pcie_xclk);
+
+       /* Finally enable PCIe */
+       val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_EN_FPCI;
+       afi_writel(val, AFI_CONFIGURATION);
+
+       val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR |
+              AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR |
+              AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR);
+       afi_writel(val, AFI_AFI_INTR_ENABLE);
+       afi_writel(0xffffffff, AFI_SM_INTR_ENABLE);
+
+       /* FIXME: No MSI for now, only INT */
+       afi_writel(AFI_INTR_MASK_INT_MASK, AFI_INTR_MASK);
+
+       /* Disable all execptions */
+       afi_writel(0, AFI_FPCI_ERROR_MASKS);
+
+       return;
+}
+
+static void tegra_pcie_xclk_clamp(bool clamp)
+{
+       u32 reg;
+
+       reg = pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP;
+
+       if (clamp)
+               reg |= PMC_SCRATCH42_PCX_CLAMP;
+
+       pmc_writel(reg, PMC_SCRATCH42);
+}
+
+static int tegra_pcie_power_on(void)
+{
+       tegra_pcie_xclk_clamp(true);
+       tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+       tegra_pcie_xclk_clamp(false);
+
+       clk_enable(tegra_pcie.afi_clk);
+       clk_enable(tegra_pcie.pex_clk);
+       return clk_enable(tegra_pcie.pll_e);
+}
+
+static void tegra_pcie_power_off(void)
+{
+       tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+       tegra_periph_reset_assert(tegra_pcie.afi_clk);
+       tegra_periph_reset_assert(tegra_pcie.pex_clk);
+
+       tegra_pcie_xclk_clamp(true);
+}
+
+static int tegra_pcie_clocks_get(void)
+{
+       int err;
+
+       tegra_pcie.pex_clk = clk_get(NULL, "pex");
+       if (IS_ERR(tegra_pcie.pex_clk))
+               return PTR_ERR(tegra_pcie.pex_clk);
+
+       tegra_pcie.afi_clk = clk_get(NULL, "afi");
+       if (IS_ERR(tegra_pcie.afi_clk)) {
+               err = PTR_ERR(tegra_pcie.afi_clk);
+               goto err_afi_clk;
+       }
+
+       tegra_pcie.pcie_xclk = clk_get(NULL, "pcie_xclk");
+       if (IS_ERR(tegra_pcie.pcie_xclk)) {
+               err =  PTR_ERR(tegra_pcie.pcie_xclk);
+               goto err_pcie_xclk;
+       }
+
+       tegra_pcie.pll_e = clk_get_sys(NULL, "pll_e");
+       if (IS_ERR(tegra_pcie.pll_e)) {
+               err = PTR_ERR(tegra_pcie.pll_e);
+               goto err_pll_e;
+       }
+
+       return 0;
+
+err_pll_e:
+       clk_put(tegra_pcie.pcie_xclk);
+err_pcie_xclk:
+       clk_put(tegra_pcie.afi_clk);
+err_afi_clk:
+       clk_put(tegra_pcie.pex_clk);
+
+       return err;
+}
+
+static void tegra_pcie_clocks_put(void)
+{
+       clk_put(tegra_pcie.pll_e);
+       clk_put(tegra_pcie.pcie_xclk);
+       clk_put(tegra_pcie.afi_clk);
+       clk_put(tegra_pcie.pex_clk);
+}
+
+static int __init tegra_pcie_get_resources(void)
+{
+       struct resource *res_mmio = &tegra_pcie.res_mmio;
+       int err;
+
+       err = tegra_pcie_clocks_get();
+       if (err) {
+               pr_err("PCIE: failed to get clocks: %d\n", err);
+               return err;
+       }
+
+       err = tegra_pcie_power_on();
+       if (err) {
+               pr_err("PCIE: failed to power up: %d\n", err);
+               goto err_pwr_on;
+       }
+
+       tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ);
+       if (tegra_pcie.regs == NULL) {
+               pr_err("PCIE: Failed to map PCI/AFI registers\n");
+               err = -ENOMEM;
+               goto err_map_reg;
+       }
+
+       err = request_resource(&iomem_resource, res_mmio);
+       if (err) {
+               pr_err("PCIE: Failed to request resources: %d\n", err);
+               goto err_req_io;
+       }
+
+       tegra_pcie_io_base = ioremap_nocache(res_mmio->start,
+                                            resource_size(res_mmio));
+       if (tegra_pcie_io_base == NULL) {
+               pr_err("PCIE: Failed to map IO\n");
+               err = -ENOMEM;
+               goto err_map_io;
+       }
+
+       err = request_irq(INT_PCIE_INTR, tegra_pcie_isr,
+                         IRQF_SHARED, "PCIE", &tegra_pcie);
+       if (err) {
+               pr_err("PCIE: Failed to register IRQ: %d\n", err);
+               goto err_irq;
+       }
+       set_irq_flags(INT_PCIE_INTR, IRQF_VALID);
+
+       return 0;
+
+err_irq:
+       iounmap(tegra_pcie_io_base);
+err_map_io:
+       release_resource(&tegra_pcie.res_mmio);
+err_req_io:
+       iounmap(tegra_pcie.regs);
+err_map_reg:
+       tegra_pcie_power_off();
+err_pwr_on:
+       tegra_pcie_clocks_put();
+
+       return err;
+}
+
+/*
+ * FIXME: If there are no PCIe cards attached, then calling this function
+ * can result in the increase of the bootup time as there are big timeout
+ * loops.
+ */
+#define TEGRA_PCIE_LINKUP_TIMEOUT      200     /* up to 1.2 seconds */
+static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
+                                 u32 reset_reg)
+{
+       u32 reg;
+       int retries = 3;
+       int timeout;
+
+       do {
+               timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+               while (timeout) {
+                       reg = readl(pp->base + RP_VEND_XP);
+
+                       if (reg & RP_VEND_XP_DL_UP)
+                               break;
+
+                       mdelay(1);
+                       timeout--;
+               }
+
+               if (!timeout)  {
+                       pr_err("PCIE: port %d: link down, retrying\n", idx);
+                       goto retry;
+               }
+
+               timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+               while (timeout) {
+                       reg = readl(pp->base + RP_LINK_CONTROL_STATUS);
+
+                       if (reg & 0x20000000)
+                               return true;
+
+                       mdelay(1);
+                       timeout--;
+               }
+
+retry:
+               /* Pulse the PEX reset */
+               reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+               afi_writel(reg, reset_reg);
+               mdelay(1);
+               reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+               afi_writel(reg, reset_reg);
+
+               retries--;
+       } while (retries);
+
+       return false;
+}
+
+static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+{
+       struct tegra_pcie_port *pp;
+
+       pp = tegra_pcie.port + tegra_pcie.num_ports;
+
+       pp->index = -1;
+       pp->base = tegra_pcie.regs + offset;
+       pp->link_up = tegra_pcie_check_link(pp, index, reset_reg);
+
+       if (!pp->link_up) {
+               pp->base = NULL;
+               printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
+               return;
+       }
+
+       tegra_pcie.num_ports++;
+       pp->index = index;
+       pp->root_bus_nr = -1;
+       memset(pp->res, 0, sizeof(pp->res));
+}
+
+int __init tegra_pcie_init(bool init_port0, bool init_port1)
+{
+       int err;
+
+       if (!(init_port0 || init_port1))
+               return -ENODEV;
+
+       err = tegra_pcie_get_resources();
+       if (err)
+               return err;
+
+       tegra_pcie_enable_controller();
+
+       /* setup the AFI address translations */
+       tegra_pcie_setup_translations();
+
+       if (init_port0)
+               tegra_pcie_add_port(0, RP0_OFFSET, AFI_PEX0_CTRL);
+
+       if (init_port1)
+               tegra_pcie_add_port(1, RP1_OFFSET, AFI_PEX1_CTRL);
+
+       pci_common_init(&tegra_pcie_hw);
+
+       return 0;
+}
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
new file mode 100644 (file)
index 0000000..a6ea34e
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * linux/arch/arm/mach-tegra/pinmux-t2-tables.c
+ *
+ * Common pinmux configurations for Tegra 2 SoCs
+ *
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+
+#define DRIVE_PINGROUP(pg_name, r)                             \
+       [TEGRA_DRIVE_PINGROUP_ ## pg_name] = {                  \
+               .name = #pg_name,                               \
+               .reg = r                                        \
+       }
+
+const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
+       DRIVE_PINGROUP(AO1,             0x868),
+       DRIVE_PINGROUP(AO2,             0x86c),
+       DRIVE_PINGROUP(AT1,             0x870),
+       DRIVE_PINGROUP(AT2,             0x874),
+       DRIVE_PINGROUP(CDEV1,           0x878),
+       DRIVE_PINGROUP(CDEV2,           0x87c),
+       DRIVE_PINGROUP(CSUS,            0x880),
+       DRIVE_PINGROUP(DAP1,            0x884),
+       DRIVE_PINGROUP(DAP2,            0x888),
+       DRIVE_PINGROUP(DAP3,            0x88c),
+       DRIVE_PINGROUP(DAP4,            0x890),
+       DRIVE_PINGROUP(DBG,             0x894),
+       DRIVE_PINGROUP(LCD1,            0x898),
+       DRIVE_PINGROUP(LCD2,            0x89c),
+       DRIVE_PINGROUP(SDMMC2,          0x8a0),
+       DRIVE_PINGROUP(SDMMC3,          0x8a4),
+       DRIVE_PINGROUP(SPI,             0x8a8),
+       DRIVE_PINGROUP(UAA,             0x8ac),
+       DRIVE_PINGROUP(UAB,             0x8b0),
+       DRIVE_PINGROUP(UART2,           0x8b4),
+       DRIVE_PINGROUP(UART3,           0x8b8),
+       DRIVE_PINGROUP(VI1,             0x8bc),
+       DRIVE_PINGROUP(VI2,             0x8c0),
+       DRIVE_PINGROUP(XM2A,            0x8c4),
+       DRIVE_PINGROUP(XM2C,            0x8c8),
+       DRIVE_PINGROUP(XM2D,            0x8cc),
+       DRIVE_PINGROUP(XM2CLK,          0x8d0),
+       DRIVE_PINGROUP(MEMCOMP,         0x8d4),
+};
+
+#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe,         \
+                tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)    \
+       [TEGRA_PINGROUP_ ## pg_name] = {                        \
+               .name = #pg_name,                               \
+               .vddio = TEGRA_VDDIO_ ## vdd,                   \
+               .funcs = {                                      \
+                       TEGRA_MUX_ ## f0,                       \
+                       TEGRA_MUX_ ## f1,                       \
+                       TEGRA_MUX_ ## f2,                       \
+                       TEGRA_MUX_ ## f3,                       \
+               },                                              \
+               .func_safe = TEGRA_MUX_ ## f_safe,              \
+               .tri_reg = tri_r,                               \
+               .tri_bit = tri_b,                               \
+               .mux_reg = mux_r,                               \
+               .mux_bit = mux_b,                               \
+               .pupd_reg = pupd_r,                             \
+               .pupd_bit = pupd_b,                             \
+       }
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
+       PINGROUP(ATA,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x14, 0,  0x80, 24, 0xA0, 0),
+       PINGROUP(ATB,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 1,  0x80, 16, 0xA0, 2),
+       PINGROUP(ATC,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 2,  0x80, 22, 0xA0, 4),
+       PINGROUP(ATD,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 3,  0x80, 20, 0xA0, 6),
+       PINGROUP(ATE,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x18, 25, 0x80, 12, 0xA0, 8),
+       PINGROUP(CDEV1, AUDIO, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    OSC,       0x14, 4,  0x88, 2,  0xA8, 0),
+       PINGROUP(CDEV2, AUDIO, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     OSC,       0x14, 5,  0x88, 4,  0xA8, 2),
+       PINGROUP(CRTP,  LCD,   CRT,       RSVD,      RSVD,      RSVD,          RSVD,      0x20, 14, 0x98, 20, 0xA4, 24),
+       PINGROUP(CSUS,  VI,    PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, PLLC_OUT1, 0x14, 6,  0x88, 6,  0xAC, 24),
+       PINGROUP(DAP1,  AUDIO, DAP1,      RSVD,      GMI,       SDIO2,         DAP1,      0x14, 7,  0x88, 20, 0xA0, 10),
+       PINGROUP(DAP2,  AUDIO, DAP2,      TWC,       RSVD,      GMI,           DAP2,      0x14, 8,  0x88, 22, 0xA0, 12),
+       PINGROUP(DAP3,  BB,    DAP3,      RSVD,      RSVD,      RSVD,          DAP3,      0x14, 9,  0x88, 24, 0xA0, 14),
+       PINGROUP(DAP4,  UART,  DAP4,      RSVD,      GMI,       RSVD,          DAP4,      0x14, 10, 0x88, 26, 0xA0, 16),
+       PINGROUP(DDC,   LCD,   I2C2,      RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 31, 0x88, 0,  0xB0, 28),
+       PINGROUP(DTA,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD4,     0x14, 11, 0x84, 20, 0xA0, 18),
+       PINGROUP(DTB,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 12, 0x84, 22, 0xA0, 20),
+       PINGROUP(DTC,   VI,    RSVD,      RSVD,      VI,        RSVD,          RSVD1,     0x14, 13, 0x84, 26, 0xA0, 22),
+       PINGROUP(DTD,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD1,     0x14, 14, 0x84, 28, 0xA0, 24),
+       PINGROUP(DTE,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 15, 0x84, 30, 0xA0, 26),
+       PINGROUP(DTF,   VI,    I2C3,      RSVD,      VI,        RSVD,          RSVD4,     0x20, 12, 0x98, 30, 0xA0, 28),
+       PINGROUP(GMA,   NAND,  UARTE,     SPI3,      GMI,       SDIO4,         SPI3,      0x14, 28, 0x84, 0,  0xB0, 20),
+       PINGROUP(GMB,   NAND,  IDE,       NAND,      GMI,       GMI_INT,       GMI,       0x18, 29, 0x88, 28, 0xB0, 22),
+       PINGROUP(GMC,   NAND,  UARTD,     SPI4,      GMI,       SFLASH,        SPI4,      0x14, 29, 0x84, 2,  0xB0, 24),
+       PINGROUP(GMD,   NAND,  RSVD,      NAND,      GMI,       SFLASH,        GMI,       0x18, 30, 0x88, 30, 0xB0, 26),
+       PINGROUP(GME,   NAND,  RSVD,      DAP5,      GMI,       SDIO4,         GMI,       0x18, 0,  0x8C, 0,  0xA8, 24),
+       PINGROUP(GPU,   UART,  PWM,       UARTA,     GMI,       RSVD,          RSVD4,     0x14, 16, 0x8C, 4,  0xA4, 20),
+       PINGROUP(GPU7,  SYS,   RTCK,      RSVD,      RSVD,      RSVD,          RTCK,      0x20, 11, 0x98, 28, 0xA4, 6),
+       PINGROUP(GPV,   SD,    PCIE,      RSVD,      RSVD,      RSVD,          PCIE,      0x14, 17, 0x8C, 2,  0xA0, 30),
+       PINGROUP(HDINT, LCD,   HDMI,      RSVD,      RSVD,      RSVD,          HDMI,      0x1C, 23, 0x84, 4,  0xAC, 22),
+       PINGROUP(I2CP,  SYS,   I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 18, 0x88, 8,  0xA4, 2),
+       PINGROUP(IRRX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 20, 0x88, 18, 0xA8, 22),
+       PINGROUP(IRTX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 19, 0x88, 16, 0xA8, 20),
+       PINGROUP(KBCA,  SYS,   KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, KBC,       0x14, 22, 0x88, 10, 0xA4, 8),
+       PINGROUP(KBCB,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x14, 21, 0x88, 12, 0xA4, 10),
+       PINGROUP(KBCC,  SYS,   KBC,       NAND,      TRACE,     EMC_TEST1_DLL, KBC,       0x18, 26, 0x88, 14, 0xA4, 12),
+       PINGROUP(KBCD,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x20, 10, 0x98, 26, 0xA4, 14),
+       PINGROUP(KBCE,  SYS,   KBC,       NAND,      OWR,       RSVD,          KBC,       0x14, 26, 0x80, 28, 0xB0, 2),
+       PINGROUP(KBCF,  SYS,   KBC,       NAND,      TRACE,     MIO,           KBC,       0x14, 27, 0x80, 26, 0xB0, 0),
+       PINGROUP(LCSN,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 31, 0x90, 12, 0xAC, 20),
+       PINGROUP(LD0,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 0,  0x94, 0,  0xAC, 12),
+       PINGROUP(LD1,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 1,  0x94, 2,  0xAC, 12),
+       PINGROUP(LD10,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 10, 0x94, 20, 0xAC, 12),
+       PINGROUP(LD11,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 11, 0x94, 22, 0xAC, 12),
+       PINGROUP(LD12,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 12, 0x94, 24, 0xAC, 12),
+       PINGROUP(LD13,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 13, 0x94, 26, 0xAC, 12),
+       PINGROUP(LD14,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 14, 0x94, 28, 0xAC, 12),
+       PINGROUP(LD15,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 15, 0x94, 30, 0xAC, 12),
+       PINGROUP(LD16,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 16, 0x98, 0,  0xAC, 12),
+       PINGROUP(LD17,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 17, 0x98, 2,  0xAC, 12),
+       PINGROUP(LD2,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 2,  0x94, 4,  0xAC, 12),
+       PINGROUP(LD3,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 3,  0x94, 6,  0xAC, 12),
+       PINGROUP(LD4,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 4,  0x94, 8,  0xAC, 12),
+       PINGROUP(LD5,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 5,  0x94, 10, 0xAC, 12),
+       PINGROUP(LD6,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 6,  0x94, 12, 0xAC, 12),
+       PINGROUP(LD7,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 7,  0x94, 14, 0xAC, 12),
+       PINGROUP(LD8,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 8,  0x94, 16, 0xAC, 12),
+       PINGROUP(LD9,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 9,  0x94, 18, 0xAC, 12),
+       PINGROUP(LDC,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 30, 0x90, 14, 0xAC, 20),
+       PINGROUP(LDI,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 6,  0x98, 16, 0xAC, 18),
+       PINGROUP(LHP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 18, 0x98, 10, 0xAC, 16),
+       PINGROUP(LHP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 19, 0x98, 4,  0xAC, 14),
+       PINGROUP(LHP2,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 20, 0x98, 6,  0xAC, 14),
+       PINGROUP(LHS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x20, 7,  0x90, 22, 0xAC, 22),
+       PINGROUP(LM0,   LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 24, 0x90, 26, 0xAC, 22),
+       PINGROUP(LM1,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           RSVD3,     0x1C, 25, 0x90, 28, 0xAC, 22),
+       PINGROUP(LPP,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 8,  0x98, 14, 0xAC, 18),
+       PINGROUP(LPW0,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 3,  0x90, 0,  0xAC, 20),
+       PINGROUP(LPW1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 4,  0x90, 2,  0xAC, 20),
+       PINGROUP(LPW2,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 5,  0x90, 4,  0xAC, 20),
+       PINGROUP(LSC0,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 27, 0x90, 18, 0xAC, 22),
+       PINGROUP(LSC1,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 28, 0x90, 20, 0xAC, 20),
+       PINGROUP(LSCK,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 29, 0x90, 16, 0xAC, 20),
+       PINGROUP(LSDA,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 1,  0x90, 8,  0xAC, 20),
+       PINGROUP(LSDI,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          DISPLAYA,  0x20, 2,  0x90, 6,  0xAC, 20),
+       PINGROUP(LSPI,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       HDMI,          DISPLAYA,  0x20, 0,  0x90, 10, 0xAC, 22),
+       PINGROUP(LVP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 21, 0x90, 30, 0xAC, 22),
+       PINGROUP(LVP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 22, 0x98, 8,  0xAC, 16),
+       PINGROUP(LVS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 26, 0x90, 24, 0xAC, 22),
+       PINGROUP(OWC,   SYS,   OWR,       RSVD,      RSVD,      RSVD,          OWR,       0x14, 31, 0x84, 8,  0xB0, 30),
+       PINGROUP(PMC,   SYS,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          PWR_ON,    0x14, 23, 0x98, 18, -1,   -1),
+       PINGROUP(PTA,   NAND,  I2C2,      HDMI,      GMI,       RSVD,          RSVD4,     0x14, 24, 0x98, 22, 0xA4, 4),
+       PINGROUP(RM,    UART,  I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 25, 0x80, 14, 0xA4, 0),
+       PINGROUP(SDB,   SD,    UARTA,     PWM,       SDIO3,     SPI2,          PWM,       0x20, 15, 0x8C, 10, -1,   -1),
+       PINGROUP(SDC,   SD,    PWM,       TWC,       SDIO3,     SPI3,          TWC,       0x18, 1,  0x8C, 12, 0xAC, 28),
+       PINGROUP(SDD,   SD,    UARTA,     PWM,       SDIO3,     SPI3,          PWM,       0x18, 2,  0x8C, 14, 0xAC, 30),
+       PINGROUP(SDIO1, BB,    SDIO1,     RSVD,      UARTE,     UARTA,         RSVD2,     0x14, 30, 0x80, 30, 0xB0, 18),
+       PINGROUP(SLXA,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 3,  0x84, 6,  0xA4, 22),
+       PINGROUP(SLXC,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 5,  0x84, 10, 0xA4, 26),
+       PINGROUP(SLXD,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 6,  0x84, 12, 0xA4, 28),
+       PINGROUP(SLXK,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 7,  0x84, 14, 0xA4, 30),
+       PINGROUP(SPDI,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 8,  0x8C, 8,  0xA4, 16),
+       PINGROUP(SPDO,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 9,  0x8C, 6,  0xA4, 18),
+       PINGROUP(SPIA,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 10, 0x8C, 30, 0xA8, 4),
+       PINGROUP(SPIB,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 11, 0x8C, 28, 0xA8, 6),
+       PINGROUP(SPIC,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 12, 0x8C, 26, 0xA8, 8),
+       PINGROUP(SPID,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 13, 0x8C, 24, 0xA8, 10),
+       PINGROUP(SPIE,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 14, 0x8C, 22, 0xA8, 12),
+       PINGROUP(SPIF,  AUDIO, SPI3,      SPI1,      SPI2,      RSVD,          RSVD4,     0x18, 15, 0x8C, 20, 0xA8, 14),
+       PINGROUP(SPIG,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 16, 0x8C, 18, 0xA8, 16),
+       PINGROUP(SPIH,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 17, 0x8C, 16, 0xA8, 18),
+       PINGROUP(UAA,   BB,    SPI3,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 18, 0x80, 0,  0xAC, 0),
+       PINGROUP(UAB,   BB,    SPI2,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 19, 0x80, 2,  0xAC, 2),
+       PINGROUP(UAC,   BB,    OWR,       RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 20, 0x80, 4,  0xAC, 4),
+       PINGROUP(UAD,   UART,  IRDA,      SPDIF,     UARTA,     SPI4,          SPDIF,     0x18, 21, 0x80, 6,  0xAC, 6),
+       PINGROUP(UCA,   UART,  UARTC,     RSVD,      GMI,       RSVD,          RSVD4,     0x18, 22, 0x84, 16, 0xAC, 8),
+       PINGROUP(UCB,   UART,  UARTC,     PWM,       GMI,       RSVD,          RSVD4,     0x18, 23, 0x84, 18, 0xAC, 10),
+       PINGROUP(UDA,   BB,    SPI1,      RSVD,      UARTD,     ULPI,          RSVD2,     0x20, 13, 0x80, 8,  0xB0, 16),
+       /* these pin groups only have pullup and pull down control */
+       PINGROUP(CK32,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 14),
+       PINGROUP(DDRC,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xAC, 26),
+       PINGROUP(PMCA,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 4),
+       PINGROUP(PMCB,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 6),
+       PINGROUP(PMCC,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 8),
+       PINGROUP(PMCD,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 10),
+       PINGROUP(PMCE,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 12),
+       PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
+       PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
+};
+
+#ifdef CONFIG_PM
+#define TRISTATE_REG_A         0x14
+#define TRISTATE_REG_NUM       4
+#define PIN_MUX_CTL_REG_A      0x80
+#define PIN_MUX_CTL_REG_NUM    8
+#define PULLUPDOWN_REG_A       0xa0
+#define PULLUPDOWN_REG_NUM     5
+
+static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
+                    PULLUPDOWN_REG_NUM];
+
+static inline unsigned long pg_readl(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+static inline void pg_writel(unsigned long value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+void tegra_pinmux_suspend(void)
+{
+       unsigned int i;
+       u32 *ctx = pinmux_reg;
+
+       for (i = 0; i < TRISTATE_REG_NUM; i++)
+               *ctx++ = pg_readl(TRISTATE_REG_A + i*4);
+
+       for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
+               *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
+
+       for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
+               *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
+}
+
+void tegra_pinmux_resume(void)
+{
+       unsigned int i;
+       u32 *ctx = pinmux_reg;
+
+       for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
+               pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
+
+       for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
+               pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
+
+       for (i = 0; i < TRISTATE_REG_NUM; i++)
+               pg_writel(*ctx++, TRISTATE_REG_A + i*4);
+}
+#endif
index 13ae102..f80d507 100644 (file)
@@ -14,7 +14,8 @@
  *
  */
 
-
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
 
-
-#define TEGRA_TRI_STATE(x)     (0x14 + (4 * (x)))
-#define TEGRA_PP_MUX_CTL(x)    (0x80 + (4 * (x)))
-#define TEGRA_PP_PU_PD(x)      (0xa0 + (4 * (x)))
-
-#define REG_A 0
-#define REG_B 1
-#define REG_C 2
-#define REG_D 3
-#define REG_E 4
-#define REG_F 5
-#define REG_G 6
-
-#define REG_N -1
-
 #define HSM_EN(reg)    (((reg) >> 2) & 0x1)
 #define SCHMT_EN(reg)  (((reg) >> 3) & 0x1)
 #define LPMD(reg)      (((reg) >> 4) & 0x3)
 #define SLWR(reg)      (((reg) >> 28) & 0x3)
 #define SLWF(reg)      (((reg) >> 30) & 0x3)
 
-struct tegra_pingroup_desc {
-       const char *name;
-       int funcs[4];
-       s8 tri_reg;     /* offset into the TRISTATE_REG_* register bank */
-       s8 tri_bit;     /* offset into the TRISTATE_REG_* register bit */
-       s8 mux_reg;     /* offset into the PIN_MUX_CTL_* register bank */
-       s8 mux_bit;     /* offset into the PIN_MUX_CTL_* register bit */
-       s8 pupd_reg;    /* offset into the PULL_UPDOWN_REG_* register bank */
-       s8 pupd_bit;    /* offset into the PULL_UPDOWN_REG_* register bit */
-};
-
-#define PINGROUP(pg_name, f0, f1, f2, f3,                      \
-                tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)    \
-       [TEGRA_PINGROUP_ ## pg_name] = {                        \
-               .name = #pg_name,                               \
-               .funcs = {                                      \
-                       TEGRA_MUX_ ## f0,                       \
-                       TEGRA_MUX_ ## f1,                       \
-                       TEGRA_MUX_ ## f2,                       \
-                       TEGRA_MUX_ ## f3,                       \
-               },                                              \
-               .tri_reg = REG_ ## tri_r,                       \
-               .tri_bit = tri_b,                               \
-               .mux_reg = REG_ ## mux_r,                       \
-               .mux_bit = mux_b,                               \
-               .pupd_reg = REG_ ## pupd_r,                     \
-               .pupd_bit = pupd_b,                             \
-       }
-
-static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = {
-       PINGROUP(ATA,   IDE,       NAND,      GMI,       RSVD,          A, 0,  A, 24, A, 0),
-       PINGROUP(ATB,   IDE,       NAND,      GMI,       SDIO4,         A, 1,  A, 16, A, 2),
-       PINGROUP(ATC,   IDE,       NAND,      GMI,       SDIO4,         A, 2,  A, 22, A, 4),
-       PINGROUP(ATD,   IDE,       NAND,      GMI,       SDIO4,         A, 3,  A, 20, A, 6),
-       PINGROUP(ATE,   IDE,       NAND,      GMI,       RSVD,          B, 25, A, 12, A, 8),
-       PINGROUP(CDEV1, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    A, 4,  C, 2,  C, 0),
-       PINGROUP(CDEV2, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     A, 5,  C, 4,  C, 2),
-       PINGROUP(CRTP,  CRT,       RSVD,      RSVD,      RSVD,          D, 14, G, 20, B, 24),
-       PINGROUP(CSUS,  PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6,  C, 6,  D, 24),
-       PINGROUP(DAP1,  DAP1,      RSVD,      GMI,       SDIO2,         A, 7,  C, 20, A, 10),
-       PINGROUP(DAP2,  DAP2,      TWC,       RSVD,      GMI,           A, 8,  C, 22, A, 12),
-       PINGROUP(DAP3,  DAP3,      RSVD,      RSVD,      RSVD,          A, 9,  C, 24, A, 14),
-       PINGROUP(DAP4,  DAP4,      RSVD,      GMI,       RSVD,          A, 10, C, 26, A, 16),
-       PINGROUP(DDC,   I2C2,      RSVD,      RSVD,      RSVD,          B, 31, C, 0,  E, 28),
-       PINGROUP(DTA,   RSVD,      SDIO2,     VI,        RSVD,          A, 11, B, 20, A, 18),
-       PINGROUP(DTB,   RSVD,      RSVD,      VI,        SPI1,          A, 12, B, 22, A, 20),
-       PINGROUP(DTC,   RSVD,      RSVD,      VI,        RSVD,          A, 13, B, 26, A, 22),
-       PINGROUP(DTD,   RSVD,      SDIO2,     VI,        RSVD,          A, 14, B, 28, A, 24),
-       PINGROUP(DTE,   RSVD,      RSVD,      VI,        SPI1,          A, 15, B, 30, A, 26),
-       PINGROUP(DTF,   I2C3,      RSVD,      VI,        RSVD,          D, 12, G, 30, A, 28),
-       PINGROUP(GMA,   UARTE,     SPI3,      GMI,       SDIO4,         A, 28, B, 0,  E, 20),
-       PINGROUP(GMB,   IDE,       NAND,      GMI,       GMI_INT,       B, 29, C, 28, E, 22),
-       PINGROUP(GMC,   UARTD,     SPI4,      GMI,       SFLASH,        A, 29, B, 2,  E, 24),
-       PINGROUP(GMD,   RSVD,      NAND,      GMI,       SFLASH,        B, 30, C, 30, E, 26),
-       PINGROUP(GME,   RSVD,      DAP5,      GMI,       SDIO4,         B, 0,  D, 0,  C, 24),
-       PINGROUP(GPU,   PWM,       UARTA,     GMI,       RSVD,          A, 16, D, 4,  B, 20),
-       PINGROUP(GPU7,  RTCK,      RSVD,      RSVD,      RSVD,          D, 11, G, 28, B, 6),
-       PINGROUP(GPV,   PCIE,      RSVD,      RSVD,      RSVD,          A, 17, D, 2,  A, 30),
-       PINGROUP(HDINT, HDMI,      RSVD,      RSVD,      RSVD,          C, 23, B, 4,  D, 22),
-       PINGROUP(I2CP,  I2C,       RSVD,      RSVD,      RSVD,          A, 18, C, 8,  B, 2),
-       PINGROUP(IRRX,  UARTA,     UARTB,     GMI,       SPI4,          A, 20, C, 18, C, 22),
-       PINGROUP(IRTX,  UARTA,     UARTB,     GMI,       SPI4,          A, 19, C, 16, C, 20),
-       PINGROUP(KBCA,  KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, A, 22, C, 10, B, 8),
-       PINGROUP(KBCB,  KBC,       NAND,      SDIO2,     MIO,           A, 21, C, 12, B, 10),
-       PINGROUP(KBCC,  KBC,       NAND,      TRACE,     EMC_TEST1_DLL, B, 26, C, 14, B, 12),
-       PINGROUP(KBCD,  KBC,       NAND,      SDIO2,     MIO,           D, 10, G, 26, B, 14),
-       PINGROUP(KBCE,  KBC,       NAND,      OWR,       RSVD,          A, 26, A, 28, E, 2),
-       PINGROUP(KBCF,  KBC,       NAND,      TRACE,     MIO,           A, 27, A, 26, E, 0),
-       PINGROUP(LCSN,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 31, E, 12, D, 20),
-       PINGROUP(LD0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 0,  F, 0,  D, 12),
-       PINGROUP(LD1,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 1,  F, 2,  D, 12),
-       PINGROUP(LD10,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 10, F, 20, D, 12),
-       PINGROUP(LD11,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 11, F, 22, D, 12),
-       PINGROUP(LD12,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 12, F, 24, D, 12),
-       PINGROUP(LD13,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 13, F, 26, D, 12),
-       PINGROUP(LD14,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 14, F, 28, D, 12),
-       PINGROUP(LD15,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 15, F, 30, D, 12),
-       PINGROUP(LD16,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 16, G, 0,  D, 12),
-       PINGROUP(LD17,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 17, G, 2,  D, 12),
-       PINGROUP(LD2,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 2,  F, 4,  D, 12),
-       PINGROUP(LD3,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 3,  F, 6,  D, 12),
-       PINGROUP(LD4,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 4,  F, 8,  D, 12),
-       PINGROUP(LD5,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 5,  F, 10, D, 12),
-       PINGROUP(LD6,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 6,  F, 12, D, 12),
-       PINGROUP(LD7,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 7,  F, 14, D, 12),
-       PINGROUP(LD8,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 8,  F, 16, D, 12),
-       PINGROUP(LD9,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 9,  F, 18, D, 12),
-       PINGROUP(LDC,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 30, E, 14, D, 20),
-       PINGROUP(LDI,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 6,  G, 16, D, 18),
-       PINGROUP(LHP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 18, G, 10, D, 16),
-       PINGROUP(LHP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 19, G, 4,  D, 14),
-       PINGROUP(LHP2,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 20, G, 6,  D, 14),
-       PINGROUP(LHS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          D, 7,  E, 22, D, 22),
-       PINGROUP(LM0,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 24, E, 26, D, 22),
-       PINGROUP(LM1,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           C, 25, E, 28, D, 22),
-       PINGROUP(LPP,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 8,  G, 14, D, 18),
-       PINGROUP(LPW0,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 3,  E, 0,  D, 20),
-       PINGROUP(LPW1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 4,  E, 2,  D, 20),
-       PINGROUP(LPW2,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 5,  E, 4,  D, 20),
-       PINGROUP(LSC0,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 27, E, 18, D, 22),
-       PINGROUP(LSC1,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 28, E, 20, D, 20),
-       PINGROUP(LSCK,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 29, E, 16, D, 20),
-       PINGROUP(LSDA,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 1,  E, 8,  D, 20),
-       PINGROUP(LSDI,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          D, 2,  E, 6,  D, 20),
-       PINGROUP(LSPI,  DISPLAYA,  DISPLAYB,  XIO,       HDMI,          D, 0,  E, 10, D, 22),
-       PINGROUP(LVP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 21, E, 30, D, 22),
-       PINGROUP(LVP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 22, G, 8,  D, 16),
-       PINGROUP(LVS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 26, E, 24, D, 22),
-       PINGROUP(OWC,   OWR,       RSVD,      RSVD,      RSVD,          A, 31, B, 8,  E, 30),
-       PINGROUP(PMC,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          A, 23, G, 18, N, -1),
-       PINGROUP(PTA,   I2C2,      HDMI,      GMI,       RSVD,          A, 24, G, 22, B, 4),
-       PINGROUP(RM,    I2C,       RSVD,      RSVD,      RSVD,          A, 25, A, 14, B, 0),
-       PINGROUP(SDB,   UARTA,     PWM,       SDIO3,     SPI2,          D, 15, D, 10, N, -1),
-       PINGROUP(SDC,   PWM,       TWC,       SDIO3,     SPI3,          B, 1,  D, 12, D, 28),
-       PINGROUP(SDD,   UARTA,     PWM,       SDIO3,     SPI3,          B, 2,  D, 14, D, 30),
-       PINGROUP(SDIO1, SDIO1,     RSVD,      UARTE,     UARTA,         A, 30, A, 30, E, 18),
-       PINGROUP(SLXA,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 3,  B, 6,  B, 22),
-       PINGROUP(SLXC,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 5,  B, 10, B, 26),
-       PINGROUP(SLXD,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 6,  B, 12, B, 28),
-       PINGROUP(SLXK,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 7,  B, 14, B, 30),
-       PINGROUP(SPDI,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 8,  D, 8,  B, 16),
-       PINGROUP(SPDO,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 9,  D, 6,  B, 18),
-       PINGROUP(SPIA,  SPI1,      SPI2,      SPI3,      GMI,           B, 10, D, 30, C, 4),
-       PINGROUP(SPIB,  SPI1,      SPI2,      SPI3,      GMI,           B, 11, D, 28, C, 6),
-       PINGROUP(SPIC,  SPI1,      SPI2,      SPI3,      GMI,           B, 12, D, 26, C, 8),
-       PINGROUP(SPID,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 13, D, 24, C, 10),
-       PINGROUP(SPIE,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 14, D, 22, C, 12),
-       PINGROUP(SPIF,  SPI3,      SPI1,      SPI2,      RSVD,          B, 15, D, 20, C, 14),
-       PINGROUP(SPIG,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 16, D, 18, C, 16),
-       PINGROUP(SPIH,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 17, D, 16, C, 18),
-       PINGROUP(UAA,   SPI3,      MIPI_HS,   UARTA,     ULPI,          B, 18, A, 0,  D, 0),
-       PINGROUP(UAB,   SPI2,      MIPI_HS,   UARTA,     ULPI,          B, 19, A, 2,  D, 2),
-       PINGROUP(UAC,   OWR,       RSVD,      RSVD,      RSVD,          B, 20, A, 4,  D, 4),
-       PINGROUP(UAD,   IRDA,      SPDIF,     UARTA,     SPI4,          B, 21, A, 6,  D, 6),
-       PINGROUP(UCA,   UARTC,     RSVD,      GMI,       RSVD,          B, 22, B, 16, D, 8),
-       PINGROUP(UCB,   UARTC,     PWM,       GMI,       RSVD,          B, 23, B, 18, D, 10),
-       PINGROUP(UDA,   SPI1,      RSVD,      UARTD,     ULPI,          D, 13, A, 8,  E, 16),
-       /* these pin groups only have pullup and pull down control */
-       PINGROUP(CK32,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 14),
-       PINGROUP(DDRC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  D, 26),
-       PINGROUP(PMCA,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 4),
-       PINGROUP(PMCB,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 6),
-       PINGROUP(PMCC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 8),
-       PINGROUP(PMCD,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 10),
-       PINGROUP(PMCE,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 12),
-       PINGROUP(XM2C,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 30),
-       PINGROUP(XM2D,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 28),
-};
+static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups;
+static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups;
 
 static char *tegra_mux_names[TEGRA_MAX_MUX] = {
        [TEGRA_MUX_AHB_CLK] = "AHB_CLK",
@@ -256,48 +96,7 @@ static char *tegra_mux_names[TEGRA_MAX_MUX] = {
        [TEGRA_MUX_VI] = "VI",
        [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
        [TEGRA_MUX_XIO] = "XIO",
-};
-
-struct tegra_drive_pingroup_desc {
-       const char *name;
-       s16 reg;
-};
-
-#define DRIVE_PINGROUP(pg_name, r)                             \
-       [TEGRA_DRIVE_PINGROUP_ ## pg_name] = {                  \
-               .name = #pg_name,                               \
-               .reg = r                                        \
-       }
-
-static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = {
-       DRIVE_PINGROUP(AO1,             0x868),
-       DRIVE_PINGROUP(AO2,             0x86c),
-       DRIVE_PINGROUP(AT1,             0x870),
-       DRIVE_PINGROUP(AT2,             0x874),
-       DRIVE_PINGROUP(CDEV1,           0x878),
-       DRIVE_PINGROUP(CDEV2,           0x87c),
-       DRIVE_PINGROUP(CSUS,            0x880),
-       DRIVE_PINGROUP(DAP1,            0x884),
-       DRIVE_PINGROUP(DAP2,            0x888),
-       DRIVE_PINGROUP(DAP3,            0x88c),
-       DRIVE_PINGROUP(DAP4,            0x890),
-       DRIVE_PINGROUP(DBG,             0x894),
-       DRIVE_PINGROUP(LCD1,            0x898),
-       DRIVE_PINGROUP(LCD2,            0x89c),
-       DRIVE_PINGROUP(SDMMC2,  0x8a0),
-       DRIVE_PINGROUP(SDMMC3,  0x8a4),
-       DRIVE_PINGROUP(SPI,             0x8a8),
-       DRIVE_PINGROUP(UAA,             0x8ac),
-       DRIVE_PINGROUP(UAB,             0x8b0),
-       DRIVE_PINGROUP(UART2,           0x8b4),
-       DRIVE_PINGROUP(UART3,           0x8b8),
-       DRIVE_PINGROUP(VI1,             0x8bc),
-       DRIVE_PINGROUP(VI2,             0x8c0),
-       DRIVE_PINGROUP(XM2A,            0x8c4),
-       DRIVE_PINGROUP(XM2C,            0x8c8),
-       DRIVE_PINGROUP(XM2D,            0x8cc),
-       DRIVE_PINGROUP(XM2CLK,  0x8d0),
-       DRIVE_PINGROUP(MEMCOMP, 0x8d4),
+       [TEGRA_MUX_SAFE] = "<safe>",
 };
 
 static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
@@ -381,22 +180,27 @@ static inline void pg_writel(unsigned long value, unsigned long offset)
        writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
 }
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
+static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
 {
        int mux = -1;
        int i;
        unsigned long reg;
        unsigned long flags;
+       enum tegra_pingroup pg = config->pingroup;
+       enum tegra_mux_func func = config->func;
 
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].mux_reg == REG_N)
+       if (pingroups[pg].mux_reg < 0)
                return -EINVAL;
 
        if (func < 0)
                return -ERANGE;
 
+       if (func == TEGRA_MUX_SAFE)
+               func = pingroups[pg].func_safe;
+
        if (func & TEGRA_MUX_RSVD) {
                mux = func & 0x3;
        } else {
@@ -413,10 +217,10 @@ int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+       reg = pg_readl(pingroups[pg].mux_reg);
        reg &= ~(0x3 << pingroups[pg].mux_bit);
        reg |= mux << pingroups[pg].mux_bit;
-       pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+       pg_writel(reg, pingroups[pg].mux_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -432,16 +236,16 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].tri_reg == REG_N)
+       if (pingroups[pg].tri_reg < 0)
                return -EINVAL;
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+       reg = pg_readl(pingroups[pg].tri_reg);
        reg &= ~(0x1 << pingroups[pg].tri_bit);
        if (tristate)
                reg |= 1 << pingroups[pg].tri_bit;
-       pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+       pg_writel(reg, pingroups[pg].tri_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -457,7 +261,7 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].pupd_reg == REG_N)
+       if (pingroups[pg].pupd_reg < 0)
                return -EINVAL;
 
        if (pupd != TEGRA_PUPD_NORMAL &&
@@ -468,38 +272,39 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+       reg = pg_readl(pingroups[pg].pupd_reg);
        reg &= ~(0x3 << pingroups[pg].pupd_bit);
        reg |= pupd << pingroups[pg].pupd_bit;
-       pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+       pg_writel(reg, pingroups[pg].pupd_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
        return 0;
 }
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-                                enum tegra_mux_func func,
-                                enum tegra_pullupdown pupd,
-                                enum tegra_tristate tristate)
+static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config)
 {
+       enum tegra_pingroup pingroup = config->pingroup;
+       enum tegra_mux_func func     = config->func;
+       enum tegra_pullupdown pupd   = config->pupd;
+       enum tegra_tristate tristate = config->tristate;
        int err;
 
-       if (pingroups[pingroup].mux_reg != REG_N) {
-               err = tegra_pinmux_set_func(pingroup, func);
+       if (pingroups[pingroup].mux_reg >= 0) {
+               err = tegra_pinmux_set_func(config);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
                               pingroup_name(pingroup), func_name(func), err);
        }
 
-       if (pingroups[pingroup].pupd_reg != REG_N) {
+       if (pingroups[pingroup].pupd_reg >= 0) {
                err = tegra_pinmux_set_pullupdown(pingroup, pupd);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
                               pingroup_name(pingroup), pupd_name(pupd), err);
        }
 
-       if (pingroups[pingroup].tri_reg != REG_N) {
+       if (pingroups[pingroup].tri_reg >= 0) {
                err = tegra_pinmux_set_tristate(pingroup, tristate);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
@@ -507,17 +312,12 @@ void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
        }
 }
 
-
-
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len)
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len)
 {
        int i;
 
        for (i = 0; i < len; i++)
-               tegra_pinmux_config_pingroup(config[i].pingroup,
-                                            config[i].func,
-                                            config[i].pupd,
-                                            config[i].tristate);
+               tegra_pinmux_config_pingroup(&config[i]);
 }
 
 static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
@@ -784,6 +584,86 @@ void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
                                                     config[i].slew_falling);
 }
 
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+       int len)
+{
+       int i;
+       struct tegra_pingroup_config c;
+
+       for (i = 0; i < len; i++) {
+               int err;
+               c = config[i];
+               if (c.pingroup < 0 || c.pingroup >= TEGRA_MAX_PINGROUP) {
+                       WARN_ON(1);
+                       continue;
+               }
+               c.func = pingroups[c.pingroup].func_safe;
+               err = tegra_pinmux_set_func(&c);
+               if (err < 0)
+                       pr_err("%s: tegra_pinmux_set_func returned %d setting "
+                              "%s to %s\n", __func__, err,
+                              pingroup_name(c.pingroup), func_name(c.func));
+       }
+}
+
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+       int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               int err;
+               if (config[i].pingroup < 0 ||
+                   config[i].pingroup >= TEGRA_MAX_PINGROUP) {
+                       WARN_ON(1);
+                       continue;
+               }
+               err = tegra_pinmux_set_func(&config[i]);
+               if (err < 0)
+                       pr_err("%s: tegra_pinmux_set_func returned %d setting "
+                              "%s to %s\n", __func__, err,
+                              pingroup_name(config[i].pingroup),
+                              func_name(config[i].func));
+       }
+}
+
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_tristate tristate)
+{
+       int i;
+       int err;
+       enum tegra_pingroup pingroup;
+
+       for (i = 0; i < len; i++) {
+               pingroup = config[i].pingroup;
+               if (pingroups[pingroup].tri_reg >= 0) {
+                       err = tegra_pinmux_set_tristate(pingroup, tristate);
+                       if (err < 0)
+                               pr_err("pinmux: can't set pingroup %s tristate"
+                                       " to %s: %d\n", pingroup_name(pingroup),
+                                       tri_name(tristate), err);
+               }
+       }
+}
+
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_pullupdown pupd)
+{
+       int i;
+       int err;
+       enum tegra_pingroup pingroup;
+
+       for (i = 0; i < len; i++) {
+               pingroup = config[i].pingroup;
+               if (pingroups[pingroup].pupd_reg >= 0) {
+                       err = tegra_pinmux_set_pullupdown(pingroup, pupd);
+                       if (err < 0)
+                               pr_err("pinmux: can't set pingroup %s pullupdown"
+                                       " to %s: %d\n", pingroup_name(pingroup),
+                                       pupd_name(pupd), err);
+               }
+       }
+}
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -812,11 +692,11 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
                len = strlen(pingroups[i].name);
                dbg_pad_field(s, 5 - len);
 
-               if (pingroups[i].mux_reg == REG_N) {
+               if (pingroups[i].mux_reg < 0) {
                        seq_printf(s, "TEGRA_MUX_NONE");
                        len = strlen("NONE");
                } else {
-                       mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >>
+                       mux = (pg_readl(pingroups[i].mux_reg) >>
                               pingroups[i].mux_bit) & 0x3;
                        if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
                                seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
@@ -829,21 +709,21 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
                }
                dbg_pad_field(s, 13-len);
 
-               if (pingroups[i].mux_reg == REG_N) {
+               if (pingroups[i].pupd_reg < 0) {
                        seq_printf(s, "TEGRA_PUPD_NORMAL");
                        len = strlen("NORMAL");
                } else {
-                       pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >>
+                       pupd = (pg_readl(pingroups[i].pupd_reg) >>
                                pingroups[i].pupd_bit) & 0x3;
                        seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
                        len = strlen(pupd_name(pupd));
                }
                dbg_pad_field(s, 9 - len);
 
-               if (pingroups[i].tri_reg == REG_N) {
+               if (pingroups[i].tri_reg < 0) {
                        seq_printf(s, "TEGRA_TRI_NORMAL");
                } else {
-                       tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >>
+                       tri = (pg_readl(pingroups[i].tri_reg) >>
                               pingroups[i].tri_bit) & 0x1;
 
                        seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
index 4261632..ae3b308 100644 (file)
 #include <mach/iomap.h>
 
 #include "clock.h"
+#include "fuse.h"
+#include "tegra2_dvfs.h"
 
 #define RST_DEVICES                    0x004
 #define RST_DEVICES_SET                        0x300
 #define RST_DEVICES_CLR                        0x304
+#define RST_DEVICES_NUM                        3
 
 #define CLK_OUT_ENB                    0x010
 #define CLK_OUT_ENB_SET                        0x320
 #define CLK_OUT_ENB_CLR                        0x324
+#define CLK_OUT_ENB_NUM                        3
+
+#define CLK_MASK_ARM                   0x44
+#define MISC_CLK_ENB                   0x48
 
 #define OSC_CTRL                       0x50
 #define OSC_CTRL_OSC_FREQ_MASK         (3<<30)
@@ -45,6 +52,7 @@
 #define OSC_CTRL_OSC_FREQ_19_2MHZ      (1<<30)
 #define OSC_CTRL_OSC_FREQ_12MHZ                (2<<30)
 #define OSC_CTRL_OSC_FREQ_26MHZ                (3<<30)
+#define OSC_CTRL_MASK                  0x3f2
 
 #define OSC_FREQ_DET                   0x58
 #define OSC_FREQ_DET_TRIG              (1<<31)
 #define OSC_FREQ_DET_BUSY              (1<<31)
 #define OSC_FREQ_DET_CNT_MASK          0xFFFF
 
+#define PERIPH_CLK_SOURCE_I2S1         0x100
+#define PERIPH_CLK_SOURCE_EMC          0x19c
+#define PERIPH_CLK_SOURCE_OSC          0x1fc
+#define PERIPH_CLK_SOURCE_NUM \
+       ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
+
 #define PERIPH_CLK_SOURCE_MASK         (3<<30)
 #define PERIPH_CLK_SOURCE_SHIFT                30
 #define PERIPH_CLK_SOURCE_ENABLE       (1<<28)
-#define PERIPH_CLK_SOURCE_DIV_MASK     0xFF
+#define PERIPH_CLK_SOURCE_DIVU71_MASK  0xFF
+#define PERIPH_CLK_SOURCE_DIVU16_MASK  0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT    0
 
 #define PLL_BASE                       0x0
@@ -79,8 +94,9 @@
 #define PLL_OUT_RESET_DISABLE          (1<<0)
 
 #define PLL_MISC(c)                    (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_LOCK_ENABLE(c)                (((c)->flags & PLLU) ? (1<<22) : (1<<18))
+
 #define PLL_MISC_DCCON_SHIFT           20
-#define PLL_MISC_LOCK_ENABLE           (1<<18)
 #define PLL_MISC_CPCON_SHIFT           8
 #define PLL_MISC_CPCON_MASK            (0xF<<PLL_MISC_CPCON_SHIFT)
 #define PLL_MISC_LFCON_SHIFT           4
 #define PLL_MISC_VCOCON_SHIFT          0
 #define PLL_MISC_VCOCON_MASK           (0xF<<PLL_MISC_VCOCON_SHIFT)
 
+#define PLLU_BASE_POST_DIV             (1<<20)
+
 #define PLLD_MISC_CLKENABLE            (1<<30)
 #define PLLD_MISC_DIV_RST              (1<<23)
 #define PLLD_MISC_DCCON_SHIFT          12
 
+#define PLLE_MISC_READY                        (1 << 15)
+
 #define PERIPH_CLK_TO_ENB_REG(c)       ((c->clk_num / 32) * 4)
 #define PERIPH_CLK_TO_ENB_SET_REG(c)   ((c->clk_num / 32) * 8)
 #define PERIPH_CLK_TO_ENB_BIT(c)       (1 << (c->clk_num % 32))
@@ -143,30 +163,37 @@ unsigned long clk_measure_input_freq(void)
        }
 }
 
-static int clk_div71_get_divider(struct clk *c, unsigned long rate)
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-       unsigned long divider_u71;
+       s64 divider_u71 = parent_rate * 2;
+       divider_u71 += rate - 1;
+       do_div(divider_u71, rate);
 
-       divider_u71 = DIV_ROUND_UP(c->rate * 2, rate);
+       if (divider_u71 - 2 < 0)
+               return 0;
 
-       if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0)
+       if (divider_u71 - 2 > 255)
                return -EINVAL;
 
        return divider_u71 - 2;
 }
 
-static unsigned long tegra2_clk_recalculate_rate(struct clk *c)
+static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-       unsigned long rate;
-       rate = c->parent->rate;
+       s64 divider_u16;
 
-       if (c->mul != 0 && c->div != 0)
-               c->rate = rate * c->mul / c->div;
-       else
-               c->rate = rate;
-       return c->rate;
-}
+       divider_u16 = parent_rate;
+       divider_u16 += rate - 1;
+       do_div(divider_u16, rate);
+
+       if (divider_u16 - 1 < 0)
+               return 0;
 
+       if (divider_u16 - 1 > 255)
+               return -EINVAL;
+
+       return divider_u16 - 1;
+}
 
 /* clk_m functions */
 static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
@@ -244,7 +271,6 @@ static void tegra2_super_clk_init(struct clk *c)
        }
        BUG_ON(sel->input == NULL);
        c->parent = sel->input;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_super_clk_enable(struct clk *c)
@@ -266,6 +292,7 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
        u32 val;
        const struct clk_mux_sel *sel;
        int shift;
+
        val = clk_readl(c->reg + SUPER_CLK_MUX);;
        BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
                ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
@@ -273,11 +300,18 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
                SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
-                       clk_reparent(c, p);
                        val &= ~(SUPER_SOURCE_MASK << shift);
                        val |= sel->value << shift;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
                        clk_writel(val, c->reg);
-                       c->rate = c->parent->rate;
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
                        return 0;
                }
        }
@@ -289,7 +323,61 @@ static struct clk_ops tegra_super_ops = {
        .enable                 = tegra2_super_clk_enable,
        .disable                = tegra2_super_clk_disable,
        .set_parent             = tegra2_super_clk_set_parent,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
+};
+
+/* virtual cpu clock functions */
+/* some clocks can not be stopped (cpu, memory bus) while the SoC is running.
+   To change the frequency of these clocks, the parent pll may need to be
+   reprogrammed, so the clock must be moved off the pll, the pll reprogrammed,
+   and then the clock moved back to the pll.  To hide this sequence, a virtual
+   clock handles it.
+ */
+static void tegra2_cpu_clk_init(struct clk *c)
+{
+}
+
+static int tegra2_cpu_clk_enable(struct clk *c)
+{
+       return 0;
+}
+
+static void tegra2_cpu_clk_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       /* oops - don't disable the CPU clock! */
+       BUG();
+}
+
+static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+       ret = clk_set_parent_locked(c->parent, c->backup);
+       if (ret) {
+               pr_err("Failed to switch cpu to clock %s\n", c->backup->name);
+               return ret;
+       }
+
+       ret = clk_set_rate_locked(c->main, rate);
+       if (ret) {
+               pr_err("Failed to change cpu pll to %lu\n", rate);
+               return ret;
+       }
+
+       ret = clk_set_parent_locked(c->parent, c->main);
+       if (ret) {
+               pr_err("Failed to switch cpu to clock %s\n", c->main->name);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct clk_ops tegra_cpu_ops = {
+       .init     = tegra2_cpu_clk_init,
+       .enable   = tegra2_cpu_clk_enable,
+       .disable  = tegra2_cpu_clk_disable,
+       .set_rate = tegra2_cpu_clk_set_rate,
 };
 
 /* bus clock functions */
@@ -299,7 +387,6 @@ static void tegra2_bus_clk_init(struct clk *c)
        c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
        c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
        c->mul = 1;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_bus_clk_enable(struct clk *c)
@@ -340,27 +427,15 @@ static struct clk_ops tegra_bus_ops = {
        .enable                 = tegra2_bus_clk_enable,
        .disable                = tegra2_bus_clk_disable,
        .set_rate               = tegra2_bus_clk_set_rate,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
 };
 
 /* PLL Functions */
-static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c)
-{
-       u64 rate;
-       rate = c->parent->rate;
-       rate *= c->n;
-       do_div(rate, c->m);
-       if (c->p == 2)
-               rate >>= 1;
-       c->rate = rate;
-       return c->rate;
-}
-
 static int tegra2_pll_clk_wait_for_lock(struct clk *c)
 {
        ktime_t before;
 
        before = ktime_get();
+
        while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
                if (ktime_us_delta(ktime_get(), before) > 5000) {
                        pr_err("Timed out waiting for lock bit on pll %s",
@@ -380,24 +455,19 @@ static void tegra2_pll_clk_init(struct clk *c)
 
        if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
                pr_warning("Clock %s has unknown fixed frequency\n", c->name);
-               c->n = 1;
-               c->m = 0;
-               c->p = 1;
+               c->mul = 1;
+               c->div = 1;
        } else if (val & PLL_BASE_BYPASS) {
-               c->n = 1;
-               c->m = 1;
-               c->p = 1;
+               c->mul = 1;
+               c->div = 1;
        } else {
-               c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-               c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-               c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+               c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+               c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+               if (c->flags & PLLU)
+                       c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+               else
+                       c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
        }
-
-       val = clk_readl(c->reg + PLL_MISC(c));
-       if (c->flags & PLL_HAS_CPCON)
-               c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT;
-
-       tegra2_pll_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_clk_enable(struct clk *c)
@@ -411,7 +481,7 @@ static int tegra2_pll_clk_enable(struct clk *c)
        clk_writel(val, c->reg + PLL_BASE);
 
        val = clk_readl(c->reg + PLL_MISC(c));
-       val |= PLL_MISC_LOCK_ENABLE;
+       val |= PLL_MISC_LOCK_ENABLE(c);
        clk_writel(val, c->reg + PLL_MISC(c));
 
        tegra2_pll_clk_wait_for_lock(c);
@@ -441,33 +511,36 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
        input_rate = c->parent->rate;
        for (sel = c->pll_table; sel->input_rate != 0; sel++) {
                if (sel->input_rate == input_rate && sel->output_rate == rate) {
-                       c->n = sel->n;
-                       c->m = sel->m;
-                       c->p = sel->p;
-                       c->cpcon = sel->cpcon;
+                       c->mul = sel->n;
+                       c->div = sel->m * sel->p;
 
                        val = clk_readl(c->reg + PLL_BASE);
                        if (c->flags & PLL_FIXED)
                                val |= PLL_BASE_OVERRIDE;
                        val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
                                 PLL_BASE_DIVM_MASK);
-                       val |= (c->m << PLL_BASE_DIVM_SHIFT) |
-                               (c->n << PLL_BASE_DIVN_SHIFT);
-                       BUG_ON(c->p > 2);
-                       if (c->p == 2)
-                               val |= 1 << PLL_BASE_DIVP_SHIFT;
+                       val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
+                               (sel->n << PLL_BASE_DIVN_SHIFT);
+                       BUG_ON(sel->p < 1 || sel->p > 2);
+                       if (c->flags & PLLU) {
+                               if (sel->p == 1)
+                                       val |= PLLU_BASE_POST_DIV;
+                       } else {
+                               if (sel->p == 2)
+                                       val |= 1 << PLL_BASE_DIVP_SHIFT;
+                       }
                        clk_writel(val, c->reg + PLL_BASE);
 
                        if (c->flags & PLL_HAS_CPCON) {
-                               val = c->cpcon << PLL_MISC_CPCON_SHIFT;
-                               val |= PLL_MISC_LOCK_ENABLE;
+                               val = clk_readl(c->reg + PLL_MISC(c));
+                               val &= ~PLL_MISC_CPCON_MASK;
+                               val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
                                clk_writel(val, c->reg + PLL_MISC(c));
                        }
 
                        if (c->state == ON)
                                tegra2_pll_clk_enable(c);
 
-                       c->rate = rate;
                        return 0;
                }
        }
@@ -479,7 +552,46 @@ static struct clk_ops tegra_pll_ops = {
        .enable                 = tegra2_pll_clk_enable,
        .disable                = tegra2_pll_clk_disable,
        .set_rate               = tegra2_pll_clk_set_rate,
-       .recalculate_rate       = tegra2_pll_clk_recalculate_rate,
+};
+
+static void tegra2_pllx_clk_init(struct clk *c)
+{
+       tegra2_pll_clk_init(c);
+
+       if (tegra_sku_id() == 7)
+               c->max_rate = 750000000;
+}
+
+static struct clk_ops tegra_pllx_ops = {
+       .init     = tegra2_pllx_clk_init,
+       .enable   = tegra2_pll_clk_enable,
+       .disable  = tegra2_pll_clk_disable,
+       .set_rate = tegra2_pll_clk_set_rate,
+};
+
+static int tegra2_plle_clk_enable(struct clk *c)
+{
+       u32 val;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       mdelay(1);
+
+       val = clk_readl(c->reg + PLL_BASE);
+       if (!(val & PLLE_MISC_READY))
+               return -EBUSY;
+
+       val = clk_readl(c->reg + PLL_BASE);
+       val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
+       clk_writel(val, c->reg + PLL_BASE);
+
+       return 0;
+}
+
+static struct clk_ops tegra_plle_ops = {
+       .init       = tegra2_pll_clk_init,
+       .enable     = tegra2_plle_clk_enable,
+       .set_rate   = tegra2_pll_clk_set_rate,
 };
 
 /* Clock divider ops */
@@ -503,8 +615,6 @@ static void tegra2_pll_div_clk_init(struct clk *c)
                c->div = 1;
                c->mul = 1;
        }
-
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_div_clk_enable(struct clk *c)
@@ -565,7 +675,7 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
        int divider_u71;
        pr_debug("%s: %s %lu\n", __func__, c->name, rate);
        if (c->flags & DIV_U71) {
-               divider_u71 = clk_div71_get_divider(c->parent, rate);
+               divider_u71 = clk_div71_get_divider(c->parent->rate, rate);
                if (divider_u71 >= 0) {
                        val = clk_readl(c->reg);
                        new_val = val >> c->reg_shift;
@@ -580,25 +690,37 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
                        clk_writel(val, c->reg);
                        c->div = divider_u71 + 2;
                        c->mul = 2;
-                       tegra2_clk_recalculate_rate(c);
                        return 0;
                }
        } else if (c->flags & DIV_2) {
-               if (c->parent->rate == rate * 2) {
-                       c->rate = rate;
+               if (c->parent->rate == rate * 2)
                        return 0;
-               }
        }
        return -EINVAL;
 }
 
+static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
+{
+       int divider;
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+               return c->parent->rate * 2 / (divider + 2);
+       } else if (c->flags & DIV_2) {
+               return c->parent->rate / 2;
+       }
+       return -EINVAL;
+}
 
 static struct clk_ops tegra_pll_div_ops = {
        .init                   = tegra2_pll_div_clk_init,
        .enable                 = tegra2_pll_div_clk_enable,
        .disable                = tegra2_pll_div_clk_disable,
        .set_rate               = tegra2_pll_div_clk_set_rate,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
+       .round_rate             = tegra2_pll_div_clk_round_rate,
 };
 
 /* Periph clk ops */
@@ -621,9 +743,13 @@ static void tegra2_periph_clk_init(struct clk *c)
        }
 
        if (c->flags & DIV_U71) {
-               u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK;
+               u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
                c->div = divu71 + 2;
                c->mul = 2;
+       } else if (c->flags & DIV_U16) {
+               u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+               c->div = divu16 + 1;
+               c->mul = 1;
        } else {
                c->div = 1;
                c->mul = 1;
@@ -637,7 +763,6 @@ static void tegra2_periph_clk_init(struct clk *c)
                if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
                                PERIPH_CLK_TO_ENB_BIT(c))
                        c->state = OFF;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_periph_clk_enable(struct clk *c)
@@ -692,12 +817,19 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
        pr_debug("%s: %s %s\n", __func__, c->name, p->name);
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
-                       clk_reparent(c, p);
                        val = clk_readl(c->reg);
                        val &= ~PERIPH_CLK_SOURCE_MASK;
                        val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
                        clk_writel(val, c->reg);
-                       c->rate = c->parent->rate;
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
                        return 0;
                }
        }
@@ -708,20 +840,55 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 {
        u32 val;
-       int divider_u71;
+       int divider;
        pr_debug("%s: %lu\n", __func__, rate);
        if (c->flags & DIV_U71) {
-               divider_u71 = clk_div71_get_divider(c->parent, rate);
-               if (divider_u71 >= 0) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider >= 0) {
                        val = clk_readl(c->reg);
-                       val &= ~PERIPH_CLK_SOURCE_DIV_MASK;
-                       val |= divider_u71;
+                       val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
+                       val |= divider;
                        clk_writel(val, c->reg);
-                       c->div = divider_u71 + 2;
+                       c->div = divider + 2;
                        c->mul = 2;
-                       tegra2_clk_recalculate_rate(c);
                        return 0;
                }
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(c->parent->rate, rate);
+               if (divider >= 0) {
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+                       val |= divider;
+                       clk_writel(val, c->reg);
+                       c->div = divider + 1;
+                       c->mul = 1;
+                       return 0;
+               }
+       } else if (c->parent->rate <= rate) {
+               c->div = 1;
+               c->mul = 1;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static long tegra2_periph_clk_round_rate(struct clk *c,
+       unsigned long rate)
+{
+       int divider;
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+
+               return c->parent->rate * 2 / (divider + 2);
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+               return c->parent->rate / (divider + 1);
        }
        return -EINVAL;
 }
@@ -732,7 +899,7 @@ static struct clk_ops tegra_periph_clk_ops = {
        .disable                = &tegra2_periph_clk_disable,
        .set_parent             = &tegra2_periph_clk_set_parent,
        .set_rate               = &tegra2_periph_clk_set_rate,
-       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+       .round_rate             = &tegra2_periph_clk_round_rate,
 };
 
 /* Clock doubler ops */
@@ -744,21 +911,108 @@ static void tegra2_clk_double_init(struct clk *c)
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
-       tegra2_clk_recalculate_rate(c);
 };
 
+static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
+{
+       if (rate != 2 * c->parent->rate)
+               return -EINVAL;
+       c->mul = 2;
+       c->div = 1;
+       return 0;
+}
+
 static struct clk_ops tegra_clk_double_ops = {
        .init                   = &tegra2_clk_double_init,
        .enable                 = &tegra2_periph_clk_enable,
        .disable                = &tegra2_periph_clk_disable,
-       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+       .set_rate               = &tegra2_clk_double_set_rate,
+};
+
+static void tegra2_audio_sync_clk_init(struct clk *c)
+{
+       int source;
+       const struct clk_mux_sel *sel;
+       u32 val = clk_readl(c->reg);
+       c->state = (val & (1<<4)) ? OFF : ON;
+       source = val & 0xf;
+       for (sel = c->inputs; sel->input != NULL; sel++)
+               if (sel->value == source)
+                       break;
+       BUG_ON(sel->input == NULL);
+       c->parent = sel->input;
+}
+
+static int tegra2_audio_sync_clk_enable(struct clk *c)
+{
+       clk_writel(0, c->reg);
+       return 0;
+}
+
+static void tegra2_audio_sync_clk_disable(struct clk *c)
+{
+       clk_writel(1, c->reg);
+}
+
+static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       val = clk_readl(c->reg);
+                       val &= ~0xf;
+                       val |= sel->value;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
+                       clk_writel(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       unsigned long parent_rate;
+       if (!c->parent) {
+               pr_err("%s: clock has no parent\n", __func__);
+               return -EINVAL;
+       }
+       parent_rate = c->parent->rate;
+       if (rate != parent_rate) {
+               pr_err("%s: %s/%ld differs from parent %s/%ld\n",
+                       __func__,
+                       c->name, rate,
+                       c->parent->name, parent_rate);
+               return -EINVAL;
+       }
+       c->rate = parent_rate;
+       return 0;
+}
+
+static struct clk_ops tegra_audio_sync_clk_ops = {
+       .init       = tegra2_audio_sync_clk_init,
+       .enable     = tegra2_audio_sync_clk_enable,
+       .disable    = tegra2_audio_sync_clk_disable,
+       .set_rate   = tegra2_audio_sync_clk_set_rate,
+       .set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
 /* Clock definitions */
 static struct clk tegra_clk_32k = {
        .name = "clk_32k",
-       .rate = 32678,
+       .rate = 32768,
        .ops  = NULL,
+       .max_rate = 32768,
 };
 
 static struct clk_pll_table tegra_pll_s_table[] = {
@@ -782,6 +1036,7 @@ static struct clk tegra_pll_s = {
        .vco_min   = 12000000,
        .vco_max   = 26000000,
        .pll_table = tegra_pll_s_table,
+       .max_rate  = 26000000,
 };
 
 static struct clk_mux_sel tegra_clk_m_sel[] = {
@@ -797,6 +1052,7 @@ static struct clk tegra_clk_m = {
        .reg       = 0x1fc,
        .reg_mask  = (1<<28),
        .reg_shift = 28,
+       .max_rate  = 26000000,
 };
 
 static struct clk_pll_table tegra_pll_c_table[] = {
@@ -816,6 +1072,7 @@ static struct clk tegra_pll_c = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_c_table,
+       .max_rate  = 600000000,
 };
 
 static struct clk tegra_pll_c_out1 = {
@@ -825,9 +1082,18 @@ static struct clk tegra_pll_c_out1 = {
        .parent    = &tegra_pll_c,
        .reg       = 0x84,
        .reg_shift = 0,
+       .max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_m_table[] = {
+       { 12000000, 666000000, 666, 12, 1, 8},
+       { 13000000, 666000000, 666, 13, 1, 8},
+       { 19200000, 666000000, 555, 16, 1, 8},
+       { 26000000, 666000000, 666, 26, 1, 8},
+       { 12000000, 600000000, 600, 12, 1, 8},
+       { 13000000, 600000000, 600, 13, 1, 8},
+       { 19200000, 600000000, 375, 12, 1, 6},
+       { 26000000, 600000000, 600, 26, 1, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -844,6 +1110,7 @@ static struct clk tegra_pll_m = {
        .vco_min   = 20000000,
        .vco_max   = 1200000000,
        .pll_table = tegra_pll_m_table,
+       .max_rate  = 800000000,
 };
 
 static struct clk tegra_pll_m_out1 = {
@@ -853,6 +1120,7 @@ static struct clk tegra_pll_m_out1 = {
        .parent    = &tegra_pll_m,
        .reg       = 0x94,
        .reg_shift = 0,
+       .max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_p_table[] = {
@@ -880,6 +1148,7 @@ static struct clk tegra_pll_p = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_p_table,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out1 = {
@@ -889,6 +1158,7 @@ static struct clk tegra_pll_p_out1 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa4,
        .reg_shift = 0,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out2 = {
@@ -898,6 +1168,7 @@ static struct clk tegra_pll_p_out2 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa4,
        .reg_shift = 16,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out3 = {
@@ -907,6 +1178,7 @@ static struct clk tegra_pll_p_out3 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa8,
        .reg_shift = 0,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out4 = {
@@ -916,6 +1188,7 @@ static struct clk tegra_pll_p_out4 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa8,
        .reg_shift = 16,
+       .max_rate  = 432000000,
 };
 
 static struct clk_pll_table tegra_pll_a_table[] = {
@@ -923,6 +1196,7 @@ static struct clk_pll_table tegra_pll_a_table[] = {
        { 28800000, 73728000, 64, 25, 1, 1},
        { 28800000, 11289600, 49, 25, 1, 1},
        { 28800000, 12288000, 64, 25, 1, 1},
+       { 28800000, 24000000,  5,  6, 1, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -939,6 +1213,7 @@ static struct clk tegra_pll_a = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_a_table,
+       .max_rate  = 56448000,
 };
 
 static struct clk tegra_pll_a_out0 = {
@@ -948,6 +1223,7 @@ static struct clk tegra_pll_a_out0 = {
        .parent    = &tegra_pll_a,
        .reg       = 0xb4,
        .reg_shift = 0,
+       .max_rate  = 56448000,
 };
 
 static struct clk_pll_table tegra_pll_d_table[] = {
@@ -971,6 +1247,7 @@ static struct clk tegra_pll_d = {
        .vco_min   = 40000000,
        .vco_max   = 1000000000,
        .pll_table = tegra_pll_d_table,
+       .max_rate  = 1000000000,
 };
 
 static struct clk tegra_pll_d_out0 = {
@@ -978,19 +1255,20 @@ static struct clk tegra_pll_d_out0 = {
        .ops       = &tegra_pll_div_ops,
        .flags     = DIV_2 | PLLD,
        .parent    = &tegra_pll_d,
+       .max_rate  = 500000000,
 };
 
 static struct clk_pll_table tegra_pll_u_table[] = {
-       { 12000000, 480000000, 960, 12, 1, 0},
-       { 13000000, 480000000, 960, 13, 1, 0},
-       { 19200000, 480000000, 200, 4,  1, 0},
-       { 26000000, 480000000, 960, 26, 1, 0},
+       { 12000000, 480000000, 960, 12, 2, 0},
+       { 13000000, 480000000, 960, 13, 2, 0},
+       { 19200000, 480000000, 200, 4,  2, 0},
+       { 26000000, 480000000, 960, 26, 2, 0},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_u = {
        .name      = "pll_u",
-       .flags     = 0,
+       .flags     = PLLU,
        .ops       = &tegra_pll_ops,
        .reg       = 0xc0,
        .input_min = 2000000,
@@ -1001,24 +1279,59 @@ static struct clk tegra_pll_u = {
        .vco_min   = 480000000,
        .vco_max   = 960000000,
        .pll_table = tegra_pll_u_table,
+       .max_rate  = 480000000,
 };
 
 static struct clk_pll_table tegra_pll_x_table[] = {
+       /* 1 GHz */
        { 12000000, 1000000000, 1000, 12, 1, 12},
        { 13000000, 1000000000, 1000, 13, 1, 12},
        { 19200000, 1000000000, 625,  12, 1, 8},
        { 26000000, 1000000000, 1000, 26, 1, 12},
-       { 12000000, 750000000,  750,  12, 1, 12},
-       { 13000000, 750000000,  750,  13, 1, 12},
-       { 19200000, 750000000,  625,  16, 1, 8},
-       { 26000000, 750000000,  750,  26, 1, 12},
+
+       /* 912 MHz */
+       { 12000000, 912000000,  912,  12, 1, 12},
+       { 13000000, 912000000,  912,  13, 1, 12},
+       { 19200000, 912000000,  760,  16, 1, 8},
+       { 26000000, 912000000,  912,  26, 1, 12},
+
+       /* 816 MHz */
+       { 12000000, 816000000,  816,  12, 1, 12},
+       { 13000000, 816000000,  816,  13, 1, 12},
+       { 19200000, 816000000,  680,  16, 1, 8},
+       { 26000000, 816000000,  816,  26, 1, 12},
+
+       /* 760 MHz */
+       { 12000000, 760000000,  760,  12, 1, 12},
+       { 13000000, 760000000,  760,  13, 1, 12},
+       { 19200000, 760000000,  950,  24, 1, 8},
+       { 26000000, 760000000,  760,  26, 1, 12},
+
+       /* 608 MHz */
+       { 12000000, 608000000,  760,  12, 1, 12},
+       { 13000000, 608000000,  760,  13, 1, 12},
+       { 19200000, 608000000,  380,  12, 1, 8},
+       { 26000000, 608000000,  760,  26, 1, 12},
+
+       /* 456 MHz */
+       { 12000000, 456000000,  456,  12, 1, 12},
+       { 13000000, 456000000,  456,  13, 1, 12},
+       { 19200000, 456000000,  380,  16, 1, 8},
+       { 26000000, 456000000,  456,  26, 1, 12},
+
+       /* 312 MHz */
+       { 12000000, 312000000,  312,  12, 1, 12},
+       { 13000000, 312000000,  312,  13, 1, 12},
+       { 19200000, 312000000,  260,  16, 1, 8},
+       { 26000000, 312000000,  312,  26, 1, 12},
+
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_x = {
        .name      = "pll_x",
        .flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
-       .ops       = &tegra_pll_ops,
+       .ops       = &tegra_pllx_ops,
        .reg       = 0xe0,
        .input_min = 2000000,
        .input_max = 31000000,
@@ -1028,6 +1341,24 @@ static struct clk tegra_pll_x = {
        .vco_min   = 20000000,
        .vco_max   = 1200000000,
        .pll_table = tegra_pll_x_table,
+       .max_rate  = 1000000000,
+};
+
+static struct clk_pll_table tegra_pll_e_table[] = {
+       { 12000000, 100000000,  200,  24, 1, 0 },
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_e = {
+       .name      = "pll_e",
+       .flags     = PLL_ALT_MISC_REG,
+       .ops       = &tegra_plle_ops,
+       .input_min = 12000000,
+       .input_max = 12000000,
+       .max_rate  = 100000000,
+       .parent    = &tegra_clk_m,
+       .reg       = 0xe8,
+       .pll_table = tegra_pll_e_table,
 };
 
 static struct clk tegra_clk_d = {
@@ -1038,19 +1369,77 @@ static struct clk tegra_clk_d = {
        .reg       = 0x34,
        .reg_shift = 12,
        .parent    = &tegra_clk_m,
+       .max_rate  = 52000000,
+};
+
+/* initialized before peripheral clocks */
+static struct clk_mux_sel mux_audio_sync_clk[8+1];
+static const struct audio_sources {
+       const char *name;
+       int value;
+} mux_audio_sync_clk_sources[] = {
+       { .name = "spdif_in", .value = 0 },
+       { .name = "i2s1", .value = 1 },
+       { .name = "i2s2", .value = 2 },
+       { .name = "pll_a_out0", .value = 4 },
+#if 0 /* FIXME: not implemented */
+       { .name = "ac97", .value = 3 },
+       { .name = "ext_audio_clk2", .value = 5 },
+       { .name = "ext_audio_clk1", .value = 6 },
+       { .name = "ext_vimclk", .value = 7 },
+#endif
+       { 0, 0 }
+};
+
+static struct clk tegra_clk_audio = {
+       .name      = "audio",
+       .inputs    = mux_audio_sync_clk,
+       .reg       = 0x38,
+       .max_rate  = 24000000,
+       .ops       = &tegra_audio_sync_clk_ops
 };
 
-/* FIXME: need tegra_audio
 static struct clk tegra_clk_audio_2x = {
-       .name      = "clk_d",
+       .name      = "audio_2x",
        .flags     = PERIPH_NO_RESET,
+       .max_rate  = 48000000,
        .ops       = &tegra_clk_double_ops,
        .clk_num   = 89,
        .reg       = 0x34,
        .reg_shift = 8,
-       .parent    = &tegra_audio,
+       .parent    = &tegra_clk_audio,
+};
+
+struct clk_lookup tegra_audio_clk_lookups[] = {
+       { .con_id = "audio", .clk = &tegra_clk_audio },
+       { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
+};
+
+/* This is called after peripheral clocks are initialized, as the
+ * audio_sync clock depends on some of the peripheral clocks.
+ */
+
+static void init_audio_sync_clock_mux(void)
+{
+       int i;
+       struct clk_mux_sel *sel = mux_audio_sync_clk;
+       const struct audio_sources *src = mux_audio_sync_clk_sources;
+       struct clk_lookup *lookup;
+
+       for (i = 0; src->name; i++, sel++, src++) {
+               sel->input = tegra_get_clock_by_name(src->name);
+               if (!sel->input)
+                       pr_err("%s: could not find clk %s\n", __func__,
+                               src->name);
+               sel->value = src->value;
+       }
+
+       lookup = tegra_audio_clk_lookups;
+       for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
+               clk_init(lookup->clk);
+               clkdev_add(lookup);
+       }
 }
-*/
 
 static struct clk_mux_sel mux_cclk[] = {
        { .input = &tegra_clk_m,        .value = 0},
@@ -1077,27 +1466,40 @@ static struct clk_mux_sel mux_sclk[] = {
        { 0, 0},
 };
 
-static struct clk tegra_clk_cpu = {
-       .name   = "cpu",
+static struct clk tegra_clk_cclk = {
+       .name   = "cclk",
        .inputs = mux_cclk,
        .reg    = 0x20,
        .ops    = &tegra_super_ops,
+       .max_rate = 1000000000,
 };
 
-static struct clk tegra_clk_sys = {
-       .name   = "sys",
+static struct clk tegra_clk_sclk = {
+       .name   = "sclk",
        .inputs = mux_sclk,
        .reg    = 0x28,
        .ops    = &tegra_super_ops,
+       .max_rate = 600000000,
+};
+
+static struct clk tegra_clk_virtual_cpu = {
+       .name      = "cpu",
+       .parent    = &tegra_clk_cclk,
+       .main      = &tegra_pll_x,
+       .backup    = &tegra_clk_m,
+       .ops       = &tegra_cpu_ops,
+       .max_rate  = 1000000000,
+       .dvfs      = &tegra_dvfs_virtual_cpu_dvfs,
 };
 
 static struct clk tegra_clk_hclk = {
        .name           = "hclk",
        .flags          = DIV_BUS,
-       .parent         = &tegra_clk_sys,
+       .parent         = &tegra_clk_sclk,
        .reg            = 0x30,
        .reg_shift      = 4,
        .ops            = &tegra_bus_ops,
+       .max_rate       = 240000000,
 };
 
 static struct clk tegra_clk_pclk = {
@@ -1107,6 +1509,7 @@ static struct clk tegra_clk_pclk = {
        .reg            = 0x30,
        .reg_shift      = 0,
        .ops            = &tegra_bus_ops,
+       .max_rate       = 108000000,
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
@@ -1133,10 +1536,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = {
-       {.input = &tegra_pll_a, .value = 0},
-       /* FIXME: no mux defined for tegra_audio
-       {.input = &tegra_audio, .value = 1},*/
+static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
+       {.input = &tegra_pll_a_out0, .value = 0},
+       {.input = &tegra_clk_audio_2x, .value = 1},
        {.input = &tegra_pll_p, .value = 2},
        {.input = &tegra_clk_m, .value = 3},
        { 0, 0},
@@ -1153,8 +1555,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
        {.input = &tegra_pll_p,     .value = 0},
        {.input = &tegra_pll_c,     .value = 1},
-       /* FIXME: no mux defined for tegra_audio
-       {.input = &tegra_audio,     .value = 2},*/
+       {.input = &tegra_clk_audio,     .value = 2},
        {.input = &tegra_clk_m,     .value = 3},
        {.input = &tegra_clk_32k,   .value = 4},
        { 0, 0},
@@ -1187,7 +1588,7 @@ static struct clk_mux_sel mux_clk_32k[] = {
        { 0, 0},
 };
 
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
        {                                               \
                .name      = _name,                     \
                .lookup    = {                          \
@@ -1199,72 +1600,79 @@ static struct clk_mux_sel mux_clk_32k[] = {
                .reg       = _reg,                      \
                .inputs    = _inputs,                   \
                .flags     = _flags,                    \
+               .max_rate  = _max,                      \
        }
 
 struct clk tegra_periph_clks[] = {
-       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      mux_clk_32k,                    PERIPH_NO_RESET),
-       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      mux_clk_m,                      0),
-       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
-       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
+       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET),
+       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        /* FIXME: spdif has 2 clocks but 1 enable */
-       PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
-       PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  mux_pllp_pllc_pllm,             MUX | DIV_U71),
-       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
-       PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  100000000, mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71),
+       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71),
+       PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  40000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  100000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  164000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        /* FIXME: vfir shares an enable with uartb */
-       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  72000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x160,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  250000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* max rate ??? */
        /* FIXME: what is la? */
-       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("owr",       "owr",                  NULL,   71,     0x1cc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("dvc",       "tegra-i2c.3",          NULL,   47,     0x128,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c1_i2c",  "tegra-i2c.0",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71 | PERIPH_MANUAL_RESET),
-       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  92000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  60000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("dvc",       "tegra-i2c.3",          NULL,   47,     0x128,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c1_i2c",  "tegra-i2c.0",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
+       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        /* FIXME: vi and vi_sensor share an enable */
-       PERIPH_CLK("vi",        "vi",                   NULL,   20,     0x148,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("vi_sensor", "vi_sensor",            NULL,   20,     0x1a8,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("vi",        "vi",                   NULL,   20,     0x148,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("vi_sensor", "vi_sensor",            NULL,   20,     0x1a8,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
+       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  250000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  166000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        /* FIXME: cve and tvo share an enable   */
-       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("disp1",     "tegrafb.0",            NULL,   27,     0x138,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("disp2",     "tegrafb.1",            NULL,   26,     0x13c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("usb2",      "usb.1",                NULL,   58,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("usb3",      "usb.2",                NULL,   59,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  mux_pllm_pllc_pllp_clkm,        MUX | DIV_U71 | PERIPH_EMC_ENB),
-       PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      mux_plld,                       0),
+       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  148500000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("disp1",     "tegrafb.0",            NULL,   27,     0x138,  190000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("disp2",     "tegrafb.1",            NULL,   26,     0x13c,  190000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  800000000, mux_pllm_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_EMC_ENB),
+       PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      500000000, mux_plld,                    0), /* scales with voltage */
+       PERIPH_CLK("csi",       "csi",                  NULL,   52,     0,      72000000,  mux_pllp_out3,               0),
+       PERIPH_CLK("isp",       "isp",                  NULL,   23,     0,      150000000, mux_clk_m,                   0), /* same frequency as VI */
+       PERIPH_CLK("csus",      "csus",                 NULL,   92,     0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
+       PERIPH_CLK("pex",       NULL,                   "pex",  70,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
+       PERIPH_CLK("afi",       NULL,                   "afi",  72,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
+       PERIPH_CLK("pcie_xclk", NULL,             "pcie_xclk",  74,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)               \
@@ -1286,6 +1694,9 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("uartc",  "tegra_uart.2", NULL),
        CLK_DUPLICATE("uartd",  "tegra_uart.3", NULL),
        CLK_DUPLICATE("uarte",  "tegra_uart.4", NULL),
+       CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"),
+       CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"),
+       CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
 };
 
 #define CLK(dev, con, ck)      \
@@ -1315,11 +1726,13 @@ struct clk_lookup tegra_clk_lookups[] = {
        CLK(NULL,       "pll_d_out0",   &tegra_pll_d_out0),
        CLK(NULL,       "pll_u",        &tegra_pll_u),
        CLK(NULL,       "pll_x",        &tegra_pll_x),
-       CLK(NULL,       "cpu",          &tegra_clk_cpu),
-       CLK(NULL,       "sys",          &tegra_clk_sys),
+       CLK(NULL,       "pll_e",        &tegra_pll_e),
+       CLK(NULL,       "cclk",         &tegra_clk_cclk),
+       CLK(NULL,       "sclk",         &tegra_clk_sclk),
        CLK(NULL,       "hclk",         &tegra_clk_hclk),
        CLK(NULL,       "pclk",         &tegra_clk_pclk),
        CLK(NULL,       "clk_d",        &tegra_clk_d),
+       CLK(NULL,       "cpu",          &tegra_clk_virtual_cpu),
 };
 
 void __init tegra2_init_clocks(void)
@@ -1356,4 +1769,75 @@ void __init tegra2_init_clocks(void)
                                cd->name);
                }
        }
+
+       init_audio_sync_clock_mux();
+}
+
+#ifdef CONFIG_PM
+static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
+                          PERIPH_CLK_SOURCE_NUM + 3];
+
+void tegra_clk_suspend(void)
+{
+       unsigned long off, i;
+       u32 *ctx = clk_rst_suspend;
+
+       *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+
+       for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+                       off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC)
+                       continue;
+               *ctx++ = clk_readl(off);
+       }
+
+       off = RST_DEVICES;
+       for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+               *ctx++ = clk_readl(off);
+
+       off = CLK_OUT_ENB;
+       for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+               *ctx++ = clk_readl(off);
+
+       *ctx++ = clk_readl(MISC_CLK_ENB);
+       *ctx++ = clk_readl(CLK_MASK_ARM);
+}
+
+void tegra_clk_resume(void)
+{
+       unsigned long off, i;
+       const u32 *ctx = clk_rst_suspend;
+       u32 val;
+
+       val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
+       val |= *ctx++;
+       clk_writel(val, OSC_CTRL);
+
+       /* enable all clocks before configuring clock sources */
+       clk_writel(0xbffffff9ul, CLK_OUT_ENB);
+       clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
+       clk_writel(0x77f01bfful, CLK_OUT_ENB + 8);
+       wmb();
+
+       for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+                       off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC)
+                       continue;
+               clk_writel(*ctx++, off);
+       }
+       wmb();
+
+       off = RST_DEVICES;
+       for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+               clk_writel(*ctx++, off);
+       wmb();
+
+       off = CLK_OUT_ENB;
+       for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+               clk_writel(*ctx++, off);
+       wmb();
+
+       clk_writel(*ctx++, MISC_CLK_ENB);
+       clk_writel(*ctx++, CLK_MASK_ARM);
 }
+#endif
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c
new file mode 100644 (file)
index 0000000..5529c23
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include "clock.h"
+#include "tegra2_dvfs.h"
+
+static struct dvfs_table virtual_cpu_process_0[] = {
+       {314000000,  750},
+       {456000000,  825},
+       {608000000,  900},
+       {760000000,  975},
+       {817000000,  1000},
+       {912000000,  1050},
+       {1000000000, 1100},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_1[] = {
+       {314000000,  750},
+       {456000000,  825},
+       {618000000,  900},
+       {770000000,  975},
+       {827000000,  1000},
+       {922000000,  1050},
+       {1000000000, 1100},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_2[] = {
+       {494000000,  750},
+       {675000000,  825},
+       {817000000,  875},
+       {922000000,  925},
+       {1000000000, 975},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_3[] = {
+       {730000000,  750},
+       {760000000,  775},
+       {845000000,  800},
+       {1000000000, 875},
+       {0, 0},
+};
+
+struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
+       .reg_id = "vdd_cpu",
+       .process_id_table = {
+               {
+                       .process_id = 0,
+                       .table = virtual_cpu_process_0,
+               },
+               {
+                       .process_id = 1,
+                       .table = virtual_cpu_process_1,
+               },
+               {
+                       .process_id = 2,
+                       .table = virtual_cpu_process_2,
+               },
+               {
+                       .process_id = 3,
+                       .table = virtual_cpu_process_3,
+               },
+       },
+       .process_id_table_length = 4,
+       .cpu = 1,
+};
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h
new file mode 100644 (file)
index 0000000..f8c1adb
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+extern struct dvfs tegra_dvfs_virtual_cpu_dvfs;
index fcb587f..cac83a6 100644 (file)
 #include <linux/amba/pl022.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ske.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -49,6 +51,24 @@ static pin_cfg_t mop500_pins[] = {
        GPIO11_I2C2_SCL,
        GPIO229_I2C3_SDA,
        GPIO230_I2C3_SCL,
+
+       /* SKE keypad */
+       GPIO153_KP_I7,
+       GPIO154_KP_I6,
+       GPIO155_KP_I5,
+       GPIO156_KP_I4,
+       GPIO157_KP_O7,
+       GPIO158_KP_O6,
+       GPIO159_KP_O5,
+       GPIO160_KP_O4,
+       GPIO161_KP_I3,
+       GPIO162_KP_I2,
+       GPIO163_KP_I1,
+       GPIO164_KP_I0,
+       GPIO165_KP_O3,
+       GPIO166_KP_O2,
+       GPIO167_KP_O1,
+       GPIO168_KP_O0,
 };
 
 static void ab4500_spi_cs_control(u32 command)
@@ -148,12 +168,120 @@ static struct amba_device *amba_devs[] __initdata = {
        &u8500_ssp0_device,
 };
 
+static const unsigned int ux500_keymap[] = {
+       KEY(2, 5, KEY_END),
+       KEY(4, 1, KEY_POWER),
+       KEY(3, 5, KEY_VOLUMEDOWN),
+       KEY(1, 3, KEY_3),
+       KEY(5, 2, KEY_RIGHT),
+       KEY(5, 0, KEY_9),
+
+       KEY(0, 5, KEY_MENU),
+       KEY(7, 6, KEY_ENTER),
+       KEY(4, 5, KEY_0),
+       KEY(6, 7, KEY_2),
+       KEY(3, 4, KEY_UP),
+       KEY(3, 3, KEY_DOWN),
+
+       KEY(6, 4, KEY_SEND),
+       KEY(6, 2, KEY_BACK),
+       KEY(4, 2, KEY_VOLUMEUP),
+       KEY(5, 5, KEY_1),
+       KEY(4, 3, KEY_LEFT),
+       KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data ux500_keymap_data = {
+       .keymap         = ux500_keymap,
+       .keymap_size    = ARRAY_SIZE(ux500_keymap),
+};
+
+/*
+ * Nomadik SKE keypad
+ */
+#define ROW_PIN_I0      164
+#define ROW_PIN_I1      163
+#define ROW_PIN_I2      162
+#define ROW_PIN_I3      161
+#define ROW_PIN_I4      156
+#define ROW_PIN_I5      155
+#define ROW_PIN_I6      154
+#define ROW_PIN_I7      153
+#define COL_PIN_O0      168
+#define COL_PIN_O1      167
+#define COL_PIN_O2      166
+#define COL_PIN_O3      165
+#define COL_PIN_O4      160
+#define COL_PIN_O5      159
+#define COL_PIN_O6      158
+#define COL_PIN_O7      157
+
+#define SKE_KPD_MAX_ROWS        8
+#define SKE_KPD_MAX_COLS        8
+
+static int ske_kp_rows[] = {
+       ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
+       ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+};
+
+/*
+ * ske_set_gpio_row: request and set gpio rows
+ */
+static int ske_set_gpio_row(int gpio)
+{
+       int ret;
+
+       ret = gpio_request(gpio, "ske-kp");
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio request failed\n");
+               return ret;
+       }
+
+       ret = gpio_direction_output(gpio, 1);
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio direction failed\n");
+               gpio_free(gpio);
+       }
+
+       return ret;
+}
+
+/*
+ * ske_kp_init - enable the gpio configuration
+ */
+static int ske_kp_init(void)
+{
+       int ret, i;
+
+       for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
+               ret = ske_set_gpio_row(ske_kp_rows[i]);
+               if (ret < 0) {
+                       pr_err("ske_kp_init: failed init\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static struct ske_keypad_platform_data ske_keypad_board = {
+       .init           = ske_kp_init,
+       .keymap_data    = &ux500_keymap_data,
+       .no_autorepeat  = true,
+       .krow           = SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
+       .kcol           = SKE_KPD_MAX_COLS,
+       .debounce_ms    = 40,                   /* in millsecs */
+};
+
+
+
 /* add any platform devices here - TODO */
 static struct platform_device *platform_devs[] __initdata = {
        &u8500_i2c0_device,
        &ux500_i2c1_device,
        &ux500_i2c2_device,
        &ux500_i2c3_device,
+       &ux500_ske_keypad_device,
 };
 
 static void __init u8500_init_machine(void)
@@ -168,6 +296,7 @@ static void __init u8500_init_machine(void)
        ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
        ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
        ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
+       ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
 
        u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
 
index d8ab7f1..1675047 100644 (file)
@@ -477,6 +477,7 @@ static struct clk_lookup u8500_common_clks[] = {
        CLK(sdi5,       "sdi5",         NULL),
        CLK(uart2,      "uart2",        NULL),
        CLK(ske,        "ske",          NULL),
+       CLK(ske,        "nmk-ske-keypad",       NULL),
        CLK(sdi2,       "sdi2",         NULL),
        CLK(i2c0,       "nmk-i2c.0",    NULL),
        CLK(fsmc,       "fsmc",         NULL),
index 40032fe..cbbe69a 100644 (file)
@@ -292,3 +292,23 @@ void dma40_u8500ed_fixup(void)
        dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
        dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1;
 }
+
+struct resource keypad_resources[] = {
+       [0] = {
+               .start = U8500_SKE_BASE,
+               .end = U8500_SKE_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_DB8500_KB,
+               .end = IRQ_DB8500_KB,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device ux500_ske_keypad_device = {
+       .name = "nmk-ske-keypad",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(keypad_resources),
+       .resource = keypad_resources,
+};
index 33a120c..b91a4d1 100644 (file)
@@ -26,6 +26,7 @@ extern struct platform_device ux500_i2c3_device;
 extern struct platform_device u8500_i2c0_device;
 extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
+extern struct platform_device ux500_ske_keypad_device;
 
 extern struct amba_device u8500_sdi0_device;
 extern struct amba_device u8500_sdi1_device;
index 66f8761..f923764 100644 (file)
 #define GPIO152_KP_O9          PIN_CFG(152, ALT_C)
 
 #define GPIO153_GPIO           PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7          PIN_CFG(153, ALT_A)
+#define GPIO153_KP_I7          PIN_CFG_PULL(153, ALT_A, DOWN)
 #define GPIO153_LCD_D24                PIN_CFG(153, ALT_B)
 #define GPIO153_U2_RXD         PIN_CFG(153, ALT_C)
 
 #define GPIO154_GPIO           PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6          PIN_CFG(154, ALT_A)
+#define GPIO154_KP_I6          PIN_CFG_PULL(154, ALT_A, DOWN)
 #define GPIO154_LCD_D25                PIN_CFG(154, ALT_B)
 #define GPIO154_U2_TXD         PIN_CFG(154, ALT_C)
 
 #define GPIO155_GPIO           PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5          PIN_CFG(155, ALT_A)
+#define GPIO155_KP_I5          PIN_CFG_PULL(155, ALT_A, DOWN)
 #define GPIO155_LCD_D26                PIN_CFG(155, ALT_B)
 #define GPIO155_STMAPE_CLK     PIN_CFG(155, ALT_C)
 
 #define GPIO156_GPIO           PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4          PIN_CFG(156, ALT_A)
+#define GPIO156_KP_I4          PIN_CFG_PULL(156, ALT_A, DOWN)
 #define GPIO156_LCD_D27                PIN_CFG(156, ALT_B)
 #define GPIO156_STMAPE_DAT3    PIN_CFG(156, ALT_C)
 
 #define GPIO157_GPIO           PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7          PIN_CFG(157, ALT_A)
+#define GPIO157_KP_O7          PIN_CFG_PULL(157, ALT_A, UP)
 #define GPIO157_LCD_D28                PIN_CFG(157, ALT_B)
 #define GPIO157_STMAPE_DAT2    PIN_CFG(157, ALT_C)
 
 #define GPIO158_GPIO           PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6          PIN_CFG(158, ALT_A)
+#define GPIO158_KP_O6          PIN_CFG_PULL(158, ALT_A, UP)
 #define GPIO158_LCD_D29                PIN_CFG(158, ALT_B)
 #define GPIO158_STMAPE_DAT1    PIN_CFG(158, ALT_C)
 
 #define GPIO159_GPIO           PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5          PIN_CFG(159, ALT_A)
+#define GPIO159_KP_O5          PIN_CFG_PULL(159, ALT_A, UP)
 #define GPIO159_LCD_D30                PIN_CFG(159, ALT_B)
 #define GPIO159_STMAPE_DAT0    PIN_CFG(159, ALT_C)
 
 #define GPIO160_GPIO           PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4          PIN_CFG(160, ALT_A)
+#define GPIO160_KP_O4          PIN_CFG_PULL(160, ALT_A, UP)
 #define GPIO160_LCD_D31                PIN_CFG(160, ALT_B)
 #define GPIO160_NONE           PIN_CFG(160, ALT_C)
 
 #define GPIO161_GPIO           PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3          PIN_CFG(161, ALT_A)
+#define GPIO161_KP_I3          PIN_CFG_PULL(161, ALT_A, DOWN)
 #define GPIO161_LCD_D32                PIN_CFG(161, ALT_B)
 #define GPIO161_UARTMOD_RXD    PIN_CFG(161, ALT_C)
 
 #define GPIO162_GPIO           PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2          PIN_CFG(162, ALT_A)
+#define GPIO162_KP_I2          PIN_CFG_PULL(162, ALT_A, DOWN)
 #define GPIO162_LCD_D33                PIN_CFG(162, ALT_B)
 #define GPIO162_UARTMOD_TXD    PIN_CFG(162, ALT_C)
 
 #define GPIO163_GPIO           PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1          PIN_CFG(163, ALT_A)
+#define GPIO163_KP_I1          PIN_CFG_PULL(163, ALT_A, DOWN)
 #define GPIO163_LCD_D34                PIN_CFG(163, ALT_B)
 #define GPIO163_STMMOD_CLK     PIN_CFG(163, ALT_C)
 
 #define GPIO164_GPIO           PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0          PIN_CFG(164, ALT_A)
+#define GPIO164_KP_I0          PIN_CFG_PULL(164, ALT_A, UP)
 #define GPIO164_LCD_D35                PIN_CFG(164, ALT_B)
 #define GPIO164_STMMOD_DAT3    PIN_CFG(164, ALT_C)
 
 #define GPIO165_GPIO           PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3          PIN_CFG(165, ALT_A)
+#define GPIO165_KP_O3          PIN_CFG_PULL(165, ALT_A, UP)
 #define GPIO165_LCD_D36                PIN_CFG(165, ALT_B)
 #define GPIO165_STMMOD_DAT2    PIN_CFG(165, ALT_C)
 
 #define GPIO166_GPIO           PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2          PIN_CFG(166, ALT_A)
+#define GPIO166_KP_O2          PIN_CFG_PULL(166, ALT_A, UP)
 #define GPIO166_LCD_D37                PIN_CFG(166, ALT_B)
 #define GPIO166_STMMOD_DAT1    PIN_CFG(166, ALT_C)
 
 #define GPIO167_GPIO           PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1          PIN_CFG(167, ALT_A)
+#define GPIO167_KP_O1          PIN_CFG_PULL(167, ALT_A, UP)
 #define GPIO167_LCD_D38                PIN_CFG(167, ALT_B)
 #define GPIO167_STMMOD_DAT0    PIN_CFG(167, ALT_C)
 
 #define GPIO168_GPIO           PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0          PIN_CFG(168, ALT_A)
+#define GPIO168_KP_O0          PIN_CFG_PULL(168, ALT_A, UP)
 #define GPIO168_LCD_D39                PIN_CFG(168, ALT_B)
 #define GPIO168_NONE           PIN_CFG(168, ALT_C)
 
diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h
new file mode 100644 (file)
index 0000000..31382fb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
+ *
+ * ux500 Scroll key and Keypad Encoder (SKE) header
+ */
+
+#ifndef __SKE_H
+#define __SKE_H
+
+#include <linux/input/matrix_keypad.h>
+
+/* register definitions for SKE peripheral */
+#define SKE_CR         0x00
+#define SKE_VAL0       0x04
+#define SKE_VAL1       0x08
+#define SKE_DBCR       0x0C
+#define SKE_IMSC       0x10
+#define SKE_RIS                0x14
+#define SKE_MIS                0x18
+#define SKE_ICR                0x1C
+
+/*
+ * Keypad module
+ */
+
+/**
+ * struct keypad_platform_data - structure for platform specific data
+ * @init:      pointer to keypad init function
+ * @exit:      pointer to keypad deinitialisation function
+ * @keymap_data: matrix scan code table for keycodes
+ * @krow:      maximum number of rows
+ * @kcol:      maximum number of columns
+ * @debounce_ms: platform specific debounce time
+ * @no_autorepeat: flag for auto repetition
+ * @wakeup_enable: allow waking up the system
+ */
+struct ske_keypad_platform_data {
+       int (*init)(void);
+       int (*exit)(void);
+       const struct matrix_keymap_data *keymap_data;
+       u8 krow;
+       u8 kcol;
+       u8 debounce_ms;
+       bool no_autorepeat;
+       bool wakeup_enable;
+};
+#endif /*__SKE_KPD_H*/
index a92cb49..92c5bb7 100644 (file)
@@ -19,7 +19,7 @@ config ARCH_OMAP2PLUS
        bool "TI OMAP2/3/4"
        select COMMON_CLKDEV
        help
-         "Systems based on omap24xx, omap34xx or omap44xx"
+         "Systems based on OMAP2, OMAP3 or OMAP4"
 
 endchoice
 
index 9405831..a4a1285 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
-        usb.o fb.o io.o
+        usb.o fb.o io.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -31,4 +31,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
\ No newline at end of file
+obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
index 7190cbd..fc62fb5 100644 (file)
@@ -60,7 +60,7 @@ void clk_disable(struct clk *clk)
 
        spin_lock_irqsave(&clockfw_lock, flags);
        if (clk->usecount == 0) {
-               printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
+               pr_err("Trying disable clock %s with 0 usecount\n",
                       clk->name);
                WARN_ON(1);
                goto out;
@@ -397,6 +397,7 @@ static int __init clk_disable_unused(void)
        struct clk *ck;
        unsigned long flags;
 
+       pr_info("clock: disabling unused clocks to save power\n");
        list_for_each_entry(ck, &clocks, node) {
                if (ck->ops == &clkops_null)
                        continue;
@@ -418,7 +419,7 @@ late_initcall(clk_disable_unused);
 int __init clk_init(struct clk_functions * custom_clocks)
 {
        if (!custom_clocks) {
-               printk(KERN_ERR "No custom clock functions registered\n");
+               pr_err("No custom clock functions registered\n");
                BUG();
        }
 
index 3008e71..221a675 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_reg.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
 
-#include <mach/hardware.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-
 #include <plat/common.h>
 #include <plat/board.h>
-#include <plat/control.h>
-#include <plat/mux.h>
-#include <plat/fpga.h>
-#include <plat/serial.h>
 #include <plat/vram.h>
 
-#include <plat/clock.h>
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-# include "../mach-omap2/sdrc.h"
-#endif
 
 #define NO_LENGTH_CHECK 0xffffffff
 
@@ -88,270 +65,3 @@ void __init omap_reserve(void)
        omapfb_reserve_sdram_memblock();
        omap_vram_reserve_sdram_memblock();
 }
-
-/*
- * 32KHz clocksource ... always available, on pretty most chips except
- * OMAP 730 and 1510.  Other timers could be used as clocksources, with
- * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
- * but systems won't necessarily want to spend resources that way.
- */
-
-#define OMAP16XX_TIMER_32K_SYNCHRONIZED                0xfffbc410
-
-#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
-
-#include <linux/clocksource.h>
-
-/*
- * offset_32k holds the init time counter value. It is then subtracted
- * from every counter read to achieve a counter that counts time from the
- * kernel boot (needed for sched_clock()).
- */
-static u32 offset_32k __read_mostly;
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t omap16xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
-}
-#else
-#define omap16xx_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2420
-static cycle_t omap2420_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2420_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2430
-static cycle_t omap2430_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2430_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static cycle_t omap34xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap34xx_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static cycle_t omap44xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap44xx_32k_read      NULL
-#endif
-
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t omap_32k_read_dummy(struct clocksource *cs)
-{
-       return 0;
-}
-
-static struct clocksource clocksource_32k = {
-       .name           = "32k_counter",
-       .rating         = 250,
-       .read           = omap_32k_read_dummy,
-       .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 10,
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
-       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
-                                 clocksource_32k.mult, clocksource_32k.shift);
-}
-
-/**
- * read_persistent_clock -  Return time from a persistent clock.
- *
- * Reads the time from a source which isn't disabled during PM, the
- * 32k sync timer.  Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec.
- */
-static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
-void read_persistent_clock(struct timespec *ts)
-{
-       unsigned long long nsecs;
-       cycles_t delta;
-       struct timespec *tsp = &persistent_ts;
-
-       last_cycles = cycles;
-       cycles = clocksource_32k.read(&clocksource_32k);
-       delta = cycles - last_cycles;
-
-       nsecs = clocksource_cyc2ns(delta,
-                                  clocksource_32k.mult, clocksource_32k.shift);
-
-       timespec_add_ns(tsp, nsecs);
-       *ts = *tsp;
-}
-
-static int __init omap_init_clocksource_32k(void)
-{
-       static char err[] __initdata = KERN_ERR
-                       "%s: can't register clocksource!\n";
-
-       if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-               struct clk *sync_32k_ick;
-
-               if (cpu_is_omap16xx())
-                       clocksource_32k.read = omap16xx_32k_read;
-               else if (cpu_is_omap2420())
-                       clocksource_32k.read = omap2420_32k_read;
-               else if (cpu_is_omap2430())
-                       clocksource_32k.read = omap2430_32k_read;
-               else if (cpu_is_omap34xx())
-                       clocksource_32k.read = omap34xx_32k_read;
-               else if (cpu_is_omap44xx())
-                       clocksource_32k.read = omap44xx_32k_read;
-               else
-                       return -ENODEV;
-
-               sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-               if (sync_32k_ick)
-                       clk_enable(sync_32k_ick);
-
-               clocksource_32k.mult = clocksource_hz2mult(32768,
-                                           clocksource_32k.shift);
-
-               offset_32k = clocksource_32k.read(&clocksource_32k);
-
-               if (clocksource_register(&clocksource_32k))
-                       printk(err, clocksource_32k.name);
-       }
-       return 0;
-}
-arch_initcall(omap_init_clocksource_32k);
-
-#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
-
-/* Global address base setup code */
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
-static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
-{
-       omap2_set_globals_tap(omap2_globals);
-       omap2_set_globals_sdrc(omap2_globals);
-       omap2_set_globals_control(omap2_globals);
-       omap2_set_globals_prcm(omap2_globals);
-       omap2_set_globals_uart(omap2_globals);
-}
-
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2420)
-
-static struct omap_globals omap242x_globals = {
-       .class  = OMAP242X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x48014000),
-       .sdrc   = OMAP2420_SDRC_BASE,
-       .sms    = OMAP2420_SMS_BASE,
-       .ctrl   = OMAP2420_CTRL_BASE,
-       .prm    = OMAP2420_PRM_BASE,
-       .cm     = OMAP2420_CM_BASE,
-       .uart1_phys     = OMAP2_UART1_BASE,
-       .uart2_phys     = OMAP2_UART2_BASE,
-       .uart3_phys     = OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_242x(void)
-{
-       __omap2_set_globals(&omap242x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2430)
-
-static struct omap_globals omap243x_globals = {
-       .class  = OMAP243X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x4900a000),
-       .sdrc   = OMAP243X_SDRC_BASE,
-       .sms    = OMAP243X_SMS_BASE,
-       .ctrl   = OMAP243X_CTRL_BASE,
-       .prm    = OMAP2430_PRM_BASE,
-       .cm     = OMAP2430_CM_BASE,
-       .uart1_phys     = OMAP2_UART1_BASE,
-       .uart2_phys     = OMAP2_UART2_BASE,
-       .uart3_phys     = OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_243x(void)
-{
-       __omap2_set_globals(&omap243x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct omap_globals omap3_globals = {
-       .class  = OMAP343X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x4830A000),
-       .sdrc   = OMAP343X_SDRC_BASE,
-       .sms    = OMAP343X_SMS_BASE,
-       .ctrl   = OMAP343X_CTRL_BASE,
-       .prm    = OMAP3430_PRM_BASE,
-       .cm     = OMAP3430_CM_BASE,
-       .uart1_phys     = OMAP3_UART1_BASE,
-       .uart2_phys     = OMAP3_UART2_BASE,
-       .uart3_phys     = OMAP3_UART3_BASE,
-       .uart4_phys     = OMAP3_UART4_BASE,     /* Only on 3630 */
-};
-
-void __init omap2_set_globals_3xxx(void)
-{
-       __omap2_set_globals(&omap3_globals);
-}
-
-void __init omap3_map_io(void)
-{
-       omap2_set_globals_3xxx();
-       omap34xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static struct omap_globals omap4_globals = {
-       .class  = OMAP443X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-       .ctrl   = OMAP443X_CTRL_BASE,
-       .prm    = OMAP4430_PRM_BASE,
-       .cm     = OMAP4430_CM_BASE,
-       .cm2    = OMAP4430_CM2_BASE,
-       .uart1_phys     = OMAP4_UART1_BASE,
-       .uart2_phys     = OMAP4_UART2_BASE,
-       .uart3_phys     = OMAP4_UART3_BASE,
-       .uart4_phys     = OMAP4_UART4_BASE,
-};
-
-void __init omap2_set_globals_443x(void)
-{
-       omap2_set_globals_tap(&omap4_globals);
-       omap2_set_globals_control(&omap4_globals);
-       omap2_set_globals_prcm(&omap4_globals);
-       omap2_set_globals_uart(&omap4_globals);
-}
-#endif
-
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
new file mode 100644 (file)
index 0000000..155fe43
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * OMAP 32ksynctimer/counter_32k-related code
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * NOTE: This timer is not the same timer as the old OMAP1 MPU timer.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+
+#include <plat/clock.h>
+
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510.  Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#define OMAP16XX_TIMER_32K_SYNCHRONIZED                0xfffbc410
+
+#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
+
+#include <linux/clocksource.h>
+
+/*
+ * offset_32k holds the init time counter value. It is then subtracted
+ * from every counter read to achieve a counter that counts time from the
+ * kernel boot (needed for sched_clock()).
+ */
+static u32 offset_32k __read_mostly;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t omap16xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
+}
+#else
+#define omap16xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+static cycle_t omap2420_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2420_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static cycle_t omap2430_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2430_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static cycle_t omap34xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap34xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t omap44xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap44xx_32k_read      NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+{
+       return 0;
+}
+
+static struct clocksource clocksource_32k = {
+       .name           = "32k_counter",
+       .rating         = 250,
+       .read           = omap_32k_read_dummy,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 10,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
+                                 clocksource_32k.mult, clocksource_32k.shift);
+}
+
+/**
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ */
+static struct timespec persistent_ts;
+static cycles_t cycles, last_cycles;
+void read_persistent_clock(struct timespec *ts)
+{
+       unsigned long long nsecs;
+       cycles_t delta;
+       struct timespec *tsp = &persistent_ts;
+
+       last_cycles = cycles;
+       cycles = clocksource_32k.read(&clocksource_32k);
+       delta = cycles - last_cycles;
+
+       nsecs = clocksource_cyc2ns(delta,
+                                  clocksource_32k.mult, clocksource_32k.shift);
+
+       timespec_add_ns(tsp, nsecs);
+       *ts = *tsp;
+}
+
+static int __init omap_init_clocksource_32k(void)
+{
+       static char err[] __initdata = KERN_ERR
+                       "%s: can't register clocksource!\n";
+
+       if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
+               struct clk *sync_32k_ick;
+
+               if (cpu_is_omap16xx())
+                       clocksource_32k.read = omap16xx_32k_read;
+               else if (cpu_is_omap2420())
+                       clocksource_32k.read = omap2420_32k_read;
+               else if (cpu_is_omap2430())
+                       clocksource_32k.read = omap2430_32k_read;
+               else if (cpu_is_omap34xx())
+                       clocksource_32k.read = omap34xx_32k_read;
+               else if (cpu_is_omap44xx())
+                       clocksource_32k.read = omap44xx_32k_read;
+               else
+                       return -ENODEV;
+
+               sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
+               if (sync_32k_ick)
+                       clk_enable(sync_32k_ick);
+
+               clocksource_32k.mult = clocksource_hz2mult(32768,
+                                           clocksource_32k.shift);
+
+               offset_32k = clocksource_32k.read(&clocksource_32k);
+
+               if (clocksource_register(&clocksource_32k))
+                       printk(err, clocksource_32k.name);
+       }
+       return 0;
+}
+arch_initcall(omap_init_clocksource_32k);
+
+#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
+
index 6d3d333..11c54ec 100644 (file)
@@ -40,7 +40,7 @@ static struct clk *mpu_clk;
 
 /* TODO: Add support for SDRAM timing changes */
 
-int omap_verify_speed(struct cpufreq_policy *policy)
+static int omap_verify_speed(struct cpufreq_policy *policy)
 {
        if (freq_table)
                return cpufreq_frequency_table_verify(policy, freq_table);
@@ -58,7 +58,7 @@ int omap_verify_speed(struct cpufreq_policy *policy)
        return 0;
 }
 
-unsigned int omap_getspeed(unsigned int cpu)
+static unsigned int omap_getspeed(unsigned int cpu)
 {
        unsigned long rate;
 
index d1920be..1e2383e 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/control.h>
 #include <plat/board.h>
 #include <plat/mmc.h>
 #include <mach/gpio.h>
@@ -232,46 +231,6 @@ static void omap_init_uwire(void)
 static inline void omap_init_uwire(void) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
-#if    defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-
-static struct resource wdt_resources[] = {
-       {
-               .flags          = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device omap_wdt_device = {
-       .name      = "omap_wdt",
-       .id          = -1,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-       .resource       = wdt_resources,
-};
-
-static void omap_init_wdt(void)
-{
-       if (cpu_is_omap16xx())
-               wdt_resources[0].start = 0xfffeb000;
-       else if (cpu_is_omap2420())
-               wdt_resources[0].start = 0x48022000; /* WDT2 */
-       else if (cpu_is_omap2430())
-               wdt_resources[0].start = 0x49016000; /* WDT2 */
-       else if (cpu_is_omap343x())
-               wdt_resources[0].start = 0x48314000; /* WDT2 */
-       else if (cpu_is_omap44xx())
-               wdt_resources[0].start = 0x4a314000;
-       else
-               return;
-
-       wdt_resources[0].end = wdt_resources[0].start + 0x4f;
-
-       (void) platform_device_register(&omap_wdt_device);
-}
-#else
-static inline void omap_init_wdt(void) {}
-#endif
-
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -300,7 +259,6 @@ static int __init omap_init_devices(void)
        omap_init_rng();
        omap_init_mcpdm();
        omap_init_uwire();
-       omap_init_wdt();
        return 0;
 }
 arch_initcall(omap_init_devices);
index ec7eddf..f5c5b8d 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <mach/hardware.h>
@@ -996,11 +997,17 @@ void omap_start_dma(int lch)
        l = dma_read(CCR(lch));
 
        /*
-        * Errata: On ES2.0 BUFFERING disable must be set.
-        * This will always fail on ES1.0
+        * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
+        * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
+        * bursting is enabled. This might result in data gets stalled in
+        * FIFO at the end of the block.
+        * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+        * guarantee no data will stay in the DMA FIFO in case inter frame
+        * buffering occurs.
         */
-       if (cpu_is_omap24xx())
-               l |= OMAP_DMA_CCR_EN;
+       if (cpu_is_omap2420() ||
+           (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
+               l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 
        l |= OMAP_DMA_CCR_EN;
        dma_write(l, CCR(lch));
@@ -1018,8 +1025,39 @@ void omap_stop_dma(int lch)
                dma_write(0, CICR(lch));
 
        l = dma_read(CCR(lch));
-       l &= ~OMAP_DMA_CCR_EN;
-       dma_write(l, CCR(lch));
+       /* OMAP3 Errata i541: sDMA FIFO draining does not finish */
+       if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+               int i = 0;
+               u32 sys_cf;
+
+               /* Configure No-Standby */
+               l = dma_read(OCP_SYSCONFIG);
+               sys_cf = l;
+               l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+               l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+               dma_write(l , OCP_SYSCONFIG);
+
+               l = dma_read(CCR(lch));
+               l &= ~OMAP_DMA_CCR_EN;
+               dma_write(l, CCR(lch));
+
+               /* Wait for sDMA FIFO drain */
+               l = dma_read(CCR(lch));
+               while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
+                                       OMAP_DMA_CCR_WR_ACTIVE))) {
+                       udelay(5);
+                       i++;
+                       l = dma_read(CCR(lch));
+               }
+               if (i >= 100)
+                       printk(KERN_ERR "DMA drain did not complete on "
+                                       "lch %d\n", lch);
+               /* Restore OCP_SYSCONFIG */
+               dma_write(sys_cf, OCP_SYSCONFIG);
+       } else {
+               l &= ~OMAP_DMA_CCR_EN;
+               dma_write(l, CCR(lch));
+       }
 
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
index 44bafda..1d706cf 100644 (file)
@@ -581,7 +581,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
         * When the functional clock disappears, too quick writes seem
         * to cause an abort. XXX Is this still necessary?
         */
-       __delay(150000);
+       __delay(300000);
 
        return ret;
 }
index 7193481..bb78c15 100644 (file)
@@ -36,6 +36,8 @@
 #include <plat/board.h>
 #include <plat/sram.h>
 
+#include "fb.h"
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static struct omapfb_platform_data omapfb_config;
diff --git a/arch/arm/plat-omap/fb.h b/arch/arm/plat-omap/fb.h
new file mode 100644 (file)
index 0000000..d765d0b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __PLAT_OMAP_FB_H__
+#define __PLAT_OMAP_FB_H__
+
+extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+                                        unsigned long sram_vstart,
+                                        unsigned long sram_size,
+                                        unsigned long pstart_avail,
+                                        unsigned long size_avail);
+
+#endif /* __PLAT_OMAP_FB_H__ */
index 7951eef..c05c653 100644 (file)
@@ -2084,9 +2084,10 @@ void omap2_gpio_prepare_for_idle(int power_state)
 
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
-               u32 l1, l2;
+               u32 l1 = 0, l2 = 0;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_disable(bank->dbck);
 
                if (power_state > PWRDM_POWER_OFF)
@@ -2151,9 +2152,10 @@ void omap2_gpio_resume_after_idle(void)
                min = 1;
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
-               u32 l, gen, gen0, gen1;
+               u32 l = 0, gen, gen0, gen1;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_enable(bank->dbck);
 
                if (!workaround_enabled)
index 9776b41..a9d69a0 100644 (file)
@@ -47,6 +47,7 @@ struct omap_globals {
        unsigned long   sdrc;           /* SDRAM Controller */
        unsigned long   sms;            /* SDRAM Memory Scheduler */
        unsigned long   ctrl;           /* System Control Module */
+       unsigned long   ctrl_pad;       /* PAD Control Module */
        unsigned long   prm;            /* Power and Reset Management */
        unsigned long   cm;             /* Clock Management */
        unsigned long   cm2;
@@ -66,7 +67,6 @@ void omap2_set_globals_tap(struct omap_globals *);
 void omap2_set_globals_sdrc(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
-void omap2_set_globals_uart(struct omap_globals *);
 
 void omap3_map_io(void);
 
@@ -91,7 +91,8 @@ void omap3_map_io(void);
 })
 
 extern struct device *omap2_get_mpuss_device(void);
-extern struct device *omap2_get_dsp_device(void);
+extern struct device *omap2_get_iva_device(void);
 extern struct device *omap2_get_l3_device(void);
+extern struct device *omap4_get_dsp_device(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
index 2e2ae53..3fd8b40 100644 (file)
@@ -68,10 +68,9 @@ unsigned int omap_rev(void);
 #define OMAP_REVBITS_00                0x00
 #define OMAP_REVBITS_01                0x01
 #define OMAP_REVBITS_02                0x02
-#define OMAP_REVBITS_10                0x10
-#define OMAP_REVBITS_20                0x20
-#define OMAP_REVBITS_30                0x30
-#define OMAP_REVBITS_40                0x40
+#define OMAP_REVBITS_03                0x03
+#define OMAP_REVBITS_04                0x04
+#define OMAP_REVBITS_05                0x05
 
 /*
  * Get the CPU revision for OMAP devices
@@ -363,23 +362,24 @@ IS_OMAP_TYPE(3517, 0x3517)
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
-#define OMAP2420_REV_ES1_0     0x24200024
-#define OMAP2420_REV_ES2_0     0x24201024
+#define OMAP2420_REV_ES1_0     OMAP242X_CLASS
+#define OMAP2420_REV_ES2_0     (OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
 
 #define OMAP243X_CLASS         0x24300024
-#define OMAP2430_REV_ES1_0     0x24300024
+#define OMAP2430_REV_ES1_0     OMAP243X_CLASS
 
 #define OMAP343X_CLASS         0x34300034
-#define OMAP3430_REV_ES1_0     0x34300034
-#define OMAP3430_REV_ES2_0     0x34301034
-#define OMAP3430_REV_ES2_1     0x34302034
-#define OMAP3430_REV_ES3_0     0x34303034
-#define OMAP3430_REV_ES3_1     0x34304034
-#define OMAP3430_REV_ES3_1_2   0x34305034
-
-#define OMAP3630_REV_ES1_0     0x36300034
-#define OMAP3630_REV_ES1_1     0x36300134
-#define OMAP3630_REV_ES1_2     0x36300234
+#define OMAP3430_REV_ES1_0     OMAP343X_CLASS
+#define OMAP3430_REV_ES2_0     (OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP3430_REV_ES2_1     (OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3430_REV_ES3_0     (OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
+#define OMAP3430_REV_ES3_1     (OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
+#define OMAP3430_REV_ES3_1_2   (OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+
+#define OMAP363X_CLASS         0x36300034
+#define OMAP3630_REV_ES1_0     OMAP363X_CLASS
+#define OMAP3630_REV_ES1_1     (OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP3630_REV_ES1_2     (OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
 
 #define OMAP35XX_CLASS         0x35000034
 #define OMAP3503_REV(v)                (OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
@@ -390,7 +390,8 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP3517_REV(v)                (OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
 
 #define OMAP443X_CLASS         0x44300044
-#define OMAP4430_REV_ES1_0     0x44300044
+#define OMAP4430_REV_ES1_0     OMAP443X_CLASS
+#define OMAP4430_REV_ES2_0     0x44301044
 
 /*
  * omap_chip bits
@@ -417,10 +418,12 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define CHIP_IS_OMAP4430ES1            (1 << 8)
 #define CHIP_IS_OMAP3630ES1_1           (1 << 9)
 #define CHIP_IS_OMAP3630ES1_2           (1 << 10)
+#define CHIP_IS_OMAP4430ES2            (1 << 11)
 
 #define CHIP_IS_OMAP24XX               (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
-#define CHIP_IS_OMAP4430               (CHIP_IS_OMAP4430ES1)
+#define CHIP_IS_OMAP4430               (CHIP_IS_OMAP4430ES1 | \
+                                                CHIP_IS_OMAP4430ES2)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
index af3a039..0cce4ca 100644 (file)
 #define OMAP34XX_DMA_USIM_TX           79      /* S_DMA_78 */
 #define OMAP34XX_DMA_USIM_RX           80      /* S_DMA_79 */
 
+#define OMAP36XX_DMA_UART4_TX          81      /* S_DMA_80 */
+#define OMAP36XX_DMA_UART4_RX          82      /* S_DMA_81 */
 /*----------------------------------------------------------------------------*/
 
 #define OMAP1_DMA_TOUT_IRQ             (1 << 0)
 #define OMAP2_DMA_MISALIGNED_ERR_IRQ   (1 << 11)
 
 #define OMAP_DMA_CCR_EN                        (1 << 7)
+#define OMAP_DMA_CCR_RD_ACTIVE         (1 << 9)
+#define OMAP_DMA_CCR_WR_ACTIVE         (1 << 10)
+#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC  (1 << 24)
+#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25)
 
 #define OMAP_DMA_DATA_TYPE_S8          0x00
 #define OMAP_DMA_DATA_TYPE_S16         0x01
index 20f1054..dfa3aff 100644 (file)
@@ -45,6 +45,8 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE        0x02
 
 struct omap_dm_timer;
+extern struct omap_dm_timer *gptimer_wakeup;
+extern struct sys_timer omap_timer;
 struct clk;
 
 int omap_dm_timer_init(void);
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
new file mode 100644 (file)
index 0000000..872de0b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.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 __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
+
+struct omap_smsc911x_platform_data {
+       int     cs;
+       int     gpio_irq;
+       int     gpio_reset;
+       u32     flags;
+};
+
+#if defined(CONFIG_SMSC911X) || \
+       defined(CONFIG_SMSC911X_MODULE)
+
+extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+
+#else
+
+static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+{
+}
+
+#endif
+#endif
index 87f6bf2..36a0bef 100644 (file)
@@ -18,6 +18,8 @@
  * 02110-1301 USA
  *
  */
+#ifndef __ASM__ARCH_OMAP_I2C_H
+#define __ASM__ARCH_OMAP_I2C_H
 
 #include <linux/i2c.h>
 
@@ -36,3 +38,5 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
 
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
+
+#endif /* __ASM__ARCH_OMAP_I2C_H */
index c01d9f0..65e20a6 100644 (file)
 #define INT_34XX_MMC3_IRQ      94
 #define INT_34XX_GPT12_IRQ     95
 
+#define INT_36XX_UART4_IRQ     80
+
 #define INT_35XX_HECC0_IRQ             24
 #define INT_35XX_HECC1_IRQ             28
 #define INT_35XX_EMAC_C0_RXTHRESH_IRQ  67
index b4ff6a1..b87d83c 100644 (file)
 #include <mach/hardware.h>
 #include <plat/clock.h>
 
+/* macro for building platform_device for McBSP ports */
+#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr)            \
+static struct platform_device omap_mcbsp##port_nr = {  \
+       .name   = "omap-mcbsp-dai",                     \
+       .id     = OMAP_MCBSP##port_nr,                  \
+}
+
 #define OMAP7XX_MCBSP1_BASE    0xfffb1000
 #define OMAP7XX_MCBSP2_BASE    0xfffb1800
 
 #define RFSREN                 0x0002
 #define RSYNCERREN             0x0001
 
+/* CLKR signal muxing options */
+#define CLKR_SRC_CLKR          0
+#define CLKR_SRC_CLKX          1
+
+/* FSR signal muxing options */
+#define FSR_SRC_FSR            0
+#define FSR_SRC_FSX            1
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC    0
+#define MCBSP_CLKS_PAD_SRC     1
+
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
        u16 spcr2;
@@ -398,6 +417,7 @@ struct omap_mcbsp_spi_cfg {
 struct omap_mcbsp_ops {
        void (*request)(unsigned int);
        void (*free)(unsigned int);
+       int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
@@ -464,6 +484,9 @@ struct omap_mcbsp {
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count, omap_mcbsp_cache_size;
 
+#define omap_mcbsp_check_valid_id(id)  (id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)            mcbsp_ptr[id];
+
 int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
                                        int size);
@@ -502,6 +525,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
 int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
 
 
+/* McBSP functional clock source changing function */
+extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
 /* SPI specific API */
 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
 
@@ -510,6 +535,10 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf);
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
 int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 
+/* McBSP signal muxing API */
+void omap2_mcbsp1_mux_clkr_src(u8 mux);
+void omap2_mcbsp1_mux_fsr_src(u8 mux);
+
 #ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
index 9b89ec6..f57f36a 100644 (file)
@@ -71,12 +71,17 @@ struct omap_mmc_platform_data {
 
        u64 dma_mask;
 
+       /* Register offset deviation */
+       u16 reg_offset;
+
        struct omap_mmc_slot_data {
 
-               /* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC;
-                * 8 wire signaling is also optional, and is used with HSMMC
+               /*
+                * 4/8 wires and any additional host capabilities
+                * need to OR'd all capabilities (ref. linux/mmc/host.h)
                 */
-               u8 wires;
+               u8  wires;      /* Used for the MMC driver on omap1 and 2420 */
+               u32 caps;       /* Used for the MMC driver on 2430 and later */
 
                /*
                 * nomux means "standard" muxing is wrong on this board, and
@@ -104,6 +109,7 @@ struct omap_mmc_platform_data {
 
                /* we can put the features above into this variable */
 #define HSMMC_HAS_PBIAS                (1 << 0)
+#define HSMMC_HAS_UPDATED_RESET        (1 << 1)
                unsigned features;
 
                int switch_pin;                 /* gpio (card detect) */
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
new file mode 100644 (file)
index 0000000..c8dae02
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *     Govindraj R     <govindraj.raja@ti.com>
+ *     Thara Gopinath  <thara@ti.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.
+ */
+
+#ifndef __OMAP_SERIAL_H__
+#define __OMAP_SERIAL_H__
+
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <plat/mux.h>
+
+#define DRIVER_NAME    "omap-hsuart"
+
+/*
+ * Use tty device name as ttyO, [O -> OMAP]
+ * in bootargs we specify as console=ttyO0 if uart1
+ * is used as console uart.
+ */
+#define OMAP_SERIAL_NAME       "ttyO"
+
+#define OMAP_MDR1_DISABLE      0x07
+#define OMAP_MDR1_MODE13X      0x03
+#define OMAP_MDR1_MODE16X      0x00
+#define OMAP_MODE13X_SPEED     230400
+
+/*
+ * LCR = 0XBF: Switch to Configuration Mode B.
+ * In configuration mode b allow access
+ * to EFR,DLL,DLH.
+ * Reference OMAP TRM Chapter 17
+ * Section: 1.4.3 Mode Selection
+ */
+#define OMAP_UART_LCR_CONF_MDB 0XBF
+
+/* WER = 0x7F
+ * Enable module level wakeup in WER reg
+ */
+#define OMAP_UART_WER_MOD_WKUP 0X7F
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX                0x04
+
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX                0x04
+
+#define OMAP_UART_SYSC_RESET   0X07
+#define OMAP_UART_TCR_TRIG     0X0F
+#define OMAP_UART_SW_CLR       0XF0
+#define OMAP_UART_FIFO_CLR     0X06
+
+#define OMAP_UART_DMA_CH_FREE  -1
+
+#define RX_TIMEOUT             (3 * HZ)
+#define OMAP_MAX_HSUART_PORTS  4
+
+#define MSR_SAVE_FLAGS         UART_MSR_ANY_DELTA
+
+struct omap_uart_port_info {
+       bool                    dma_enabled;    /* To specify DMA Mode */
+       unsigned int            uartclk;        /* UART clock rate */
+       void __iomem            *membase;       /* ioremap cookie or NULL */
+       resource_size_t         mapbase;        /* resource base */
+       unsigned long           irqflags;       /* request_irq flags */
+       upf_t                   flags;          /* UPF_* flags */
+};
+
+struct uart_omap_dma {
+       u8                      uart_dma_tx;
+       u8                      uart_dma_rx;
+       int                     rx_dma_channel;
+       int                     tx_dma_channel;
+       dma_addr_t              rx_buf_dma_phys;
+       dma_addr_t              tx_buf_dma_phys;
+       unsigned int            uart_base;
+       /*
+        * Buffer for rx dma.It is not required for tx because the buffer
+        * comes from port structure.
+        */
+       unsigned char           *rx_buf;
+       unsigned int            prev_rx_dma_pos;
+       int                     tx_buf_size;
+       int                     tx_dma_used;
+       int                     rx_dma_used;
+       spinlock_t              tx_lock;
+       spinlock_t              rx_lock;
+       /* timer to poll activity on rx dma */
+       struct timer_list       rx_timer;
+       int                     rx_buf_size;
+       int                     rx_timeout;
+};
+
+struct uart_omap_port {
+       struct uart_port        port;
+       struct uart_omap_dma    uart_dma;
+       struct platform_device  *pdev;
+
+       unsigned char           ier;
+       unsigned char           lcr;
+       unsigned char           mcr;
+       unsigned char           fcr;
+       unsigned char           efr;
+
+       int                     use_dma;
+       /*
+        * Some bits in registers are cleared on a read, so they must
+        * be saved whenever the register is read but the bits will not
+        * be immediately processed.
+        */
+       unsigned int            lsr_break_flag;
+       unsigned char           msr_saved_flags;
+       char                    name[20];
+       unsigned long           port_activity;
+};
+
+#endif /* __OMAP_SERIAL_H__ */
index 7055672..92df9e2 100644 (file)
@@ -40,7 +40,7 @@
 #define OMAP24XX_IC_BASE       (L4_24XX_BASE + 0xfe000)
 #define OMAP24XX_IVA_INTC_BASE 0x40000000
 
-#define OMAP2420_CTRL_BASE     L4_24XX_BASE
+#define OMAP242X_CTRL_BASE     L4_24XX_BASE
 #define OMAP2420_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
 #define OMAP2420_PRCM_BASE     (L4_24XX_BASE + 0x8000)
 #define OMAP2420_CM_BASE       (L4_24XX_BASE + 0x8000)
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
new file mode 100644 (file)
index 0000000..2b1d9bc
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+
+#include <linux/input/matrix_keypad.h>
+
+struct omap4_keypad_platform_data {
+       const struct matrix_keymap_data *keymap_data;
+
+       u8 rows;
+       u8 cols;
+};
+
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
+#endif
index 25cd9ac..28e2d1a 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <plat/omap_hwmod.h>
 
+extern struct device omap_device_parent;
+
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
 #define OMAP_DEVICE_STATE_ENABLED      1
@@ -62,7 +64,6 @@
  *
  */
 struct omap_device {
-       u32                             magic;
        struct platform_device          pdev;
        struct omap_hwmod               **hwmods;
        struct omap_device_pm_latency   *pm_lats;
@@ -82,7 +83,6 @@ int omap_device_shutdown(struct platform_device *pdev);
 
 /* Core code interface */
 
-bool omap_device_is_valid(struct omap_device *od);
 int omap_device_count_resources(struct omap_device *od);
 int omap_device_fill_resources(struct omap_device *od, struct resource *res);
 
index a4e508d..7eaa8ed 100644 (file)
  *
  * These headers and macros are used to define OMAP on-chip module
  * data and their integration with other OMAP modules and Linux.
- *
- * References:
- * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
- * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
- * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
- * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
- * - Open Core Protocol Specification 2.2
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
  *
  * To do:
  * - add interconnect error log structures
  * - add pinmuxing
  * - init_conn_id_bit (CONNID_BIT_VECTOR)
  * - implement default hwmod SMS/SDRC flags?
+ * - remove unused fields
  *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
@@ -35,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 #include <plat/cpu.h>
 
 struct omap_device;
@@ -96,7 +94,7 @@ struct omap_hwmod_irq_info {
 /**
  * struct omap_hwmod_dma_info - DMA channels used by the hwmod
  * @name: name of the DMA channel (module local name)
- * @dma_ch: DMA channel ID
+ * @dma_req: DMA request ID
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -104,7 +102,20 @@ struct omap_hwmod_irq_info {
  */
 struct omap_hwmod_dma_info {
        const char      *name;
-       u16             dma_ch;
+       u16             dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+       const char      *name;
+       u8              rst_shift;
 };
 
 /**
@@ -237,8 +248,9 @@ struct omap_hwmod_ocp_if {
 #define SYSC_HAS_CLOCKACTIVITY (1 << 4)
 #define SYSC_HAS_SIDLEMODE     (1 << 5)
 #define SYSC_HAS_MIDLEMODE     (1 << 6)
-#define SYSS_MISSING           (1 << 7)
+#define SYSS_HAS_RESET_STATUS  (1 << 7)
 #define SYSC_NO_CACHE          (1 << 8)  /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS  (1 << 9)
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH     0x0
@@ -327,10 +339,12 @@ struct omap_hwmod_omap2_prcm {
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
        void __iomem    *clkctrl_reg;
+       void __iomem    *rstctrl_reg;
        u8              submodule_wkdep_bit;
 };
 
@@ -352,6 +366,11 @@ struct omap_hwmod_omap4_prcm {
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
  * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
  *     only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ *     This is needed for devices like DSS that require optional clocks enabled
+ *     in order to complete the reset. Optional clocks will be disabled
+ *     again after the reset.
+ * HWMOD_16BIT_REG: Module has 16bit registers
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -360,6 +379,8 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_OCP_AUTOIDLE                  (1 << 4)
 #define HWMOD_SET_DEFAULT_CLOCKACT             (1 << 5)
 #define HWMOD_NO_IDLEST                                (1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
+#define HWMOD_16BIT_REG                                (1 << 8)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -410,7 +431,7 @@ struct omap_hwmod_class {
  * @class: struct omap_hwmod_class * to the class of this hwmod
  * @od: struct omap_device currently associated with this hwmod (internal use)
  * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
  * @prcm: PRCM data pertaining to this hwmod
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
@@ -424,7 +445,7 @@ struct omap_hwmod_class {
  * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
  * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
  * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_chs_cnt: number of @sdma_chs
+ * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
  * @master_cnt: number of @master entries
  * @slaves_cnt: number of @slave entries
@@ -433,6 +454,7 @@ struct omap_hwmod_class {
  * @_state: internal-use hwmod state
  * @flags: hwmod flags (documented below)
  * @omap_chip: OMAP chips this hwmod is present on
+ * @_mutex: mutex serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
  * @main_clk refers to this module's "main clock," which for our
@@ -448,7 +470,8 @@ struct omap_hwmod {
        struct omap_hwmod_class         *class;
        struct omap_device              *od;
        struct omap_hwmod_irq_info      *mpu_irqs;
-       struct omap_hwmod_dma_info      *sdma_chs;
+       struct omap_hwmod_dma_info      *sdma_reqs;
+       struct omap_hwmod_rst_info      *rst_lines;
        union {
                struct omap_hwmod_omap2_prcm omap2;
                struct omap_hwmod_omap4_prcm omap4;
@@ -461,6 +484,7 @@ struct omap_hwmod {
        void                            *dev_attr;
        u32                             _sysc_cache;
        void __iomem                    *_mpu_rt_va;
+       struct mutex                    _mutex;
        struct list_head                node;
        u16                             flags;
        u8                              _mpu_port_index;
@@ -468,7 +492,8 @@ struct omap_hwmod {
        u8                              msuspendmux_shift;
        u8                              response_lat;
        u8                              mpu_irqs_cnt;
-       u8                              sdma_chs_cnt;
+       u8                              sdma_reqs_cnt;
+       u8                              rst_lines_cnt;
        u8                              opt_clks_cnt;
        u8                              masters_cnt;
        u8                              slaves_cnt;
@@ -492,6 +517,10 @@ int omap_hwmod_idle(struct omap_hwmod *oh);
 int _omap_hwmod_idle(struct omap_hwmod *oh);
 int omap_hwmod_shutdown(struct omap_hwmod *oh);
 
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
@@ -500,8 +529,8 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs);
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs);
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
@@ -534,5 +563,6 @@ int omap_hwmod_for_each_by_class(const char *classname,
 extern int omap2420_hwmod_init(void);
 extern int omap2430_hwmod_init(void);
 extern int omap3xxx_hwmod_init(void);
+extern int omap44xx_hwmod_init(void);
 
 #endif
index fb6ec74..9ca420d 100644 (file)
@@ -32,6 +32,7 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON              (1 << PWRDM_POWER_ON)
+#define PWRSTS_OFF             (1 << PWRDM_POWER_OFF)
 #define PWRSTS_OFF_ON          ((1 << PWRDM_POWER_OFF) | \
                                 (1 << PWRDM_POWER_ON))
 
@@ -161,5 +162,6 @@ int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
+int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 
 #endif
index 9fbd914..ab77442 100644 (file)
@@ -38,6 +38,8 @@ u32 prm_read_mod_reg(s16 module, u16 idx);
 void prm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
 u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
 u32 cm_read_mod_reg(s16 module, u16 idx);
 void cm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
index 7b76f50..efd87c8 100644 (file)
@@ -147,6 +147,7 @@ struct memory_timings {
 };
 
 extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
+struct omap_sdrc_params *rx51_get_sdram_timings(void);
 
 u32 omap2xxx_sdrc_dll_is_unlocked(void);
 u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
index 16a1b45..5905100 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
-extern int __init omap_sram_init(void);
 extern void * omap_sram_push(void * start, unsigned long size);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
index ddf723b..9036e37 100644 (file)
@@ -139,10 +139,14 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                DEBUG_LL_OMAP2(1, omap3evm);
                DEBUG_LL_OMAP3(1, omap_3430sdp);
                DEBUG_LL_OMAP3(1, omap_3630sdp);
+               DEBUG_LL_OMAP3(1, omap3530_lv_som);
+               DEBUG_LL_OMAP3(1, omap3_torpedo);
 
                /* omap3 based boards using UART3 */
                DEBUG_LL_OMAP3(3, cm_t35);
+               DEBUG_LL_OMAP3(3, cm_t3517);
                DEBUG_LL_OMAP3(3, igep0020);
+               DEBUG_LL_OMAP3(3, igep0030);
                DEBUG_LL_OMAP3(3, nokia_rx51);
                DEBUG_LL_OMAP3(3, omap3517evm);
                DEBUG_LL_OMAP3(3, omap3_beagle);
@@ -153,6 +157,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 
                /* omap4 based boards using UART3 */
                DEBUG_LL_OMAP4(3, omap_4430sdp);
+               DEBUG_LL_OMAP4(3, omap4_panda);
 
                /* zoom2/3 external uart */
                DEBUG_LL_ZOOM(omap_zoom2);
index 9feddac..59c7fe7 100644 (file)
@@ -105,7 +105,7 @@ static inline void omap1_usb_init(struct omap_usb_config *pdata)
 #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE)
 void omap2_usbfs_init(struct omap_usb_config *pdata);
 #else
-static inline omap2_usbfs_init(struct omap_usb_config *pdata)
+static inline void omap2_usbfs_init(struct omap_usb_config *pdata)
 {
 }
 #endif
index 0c8612f..eac4b97 100644 (file)
@@ -33,7 +33,7 @@
 struct omap_mcbsp **mcbsp_ptr;
 int omap_mcbsp_count, omap_mcbsp_cache_size;
 
-void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
        if (cpu_class_is_omap1()) {
                ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
@@ -47,7 +47,7 @@ void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
        }
 }
 
-int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
+static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 {
        if (cpu_class_is_omap1()) {
                return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
@@ -62,12 +62,12 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 }
 
 #ifdef CONFIG_ARCH_OMAP3
-void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
        __raw_writel(val, mcbsp->st_data->io_base_st + reg);
 }
 
-int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
+static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
        return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
@@ -80,9 +80,6 @@ int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 #define MCBSP_READ_CACHE(mcbsp, reg) \
                omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
 
-#define omap_mcbsp_check_valid_id(id)  (id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)            mcbsp_ptr[id];
-
 #define MCBSP_ST_READ(mcbsp, reg) \
                        omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
 #define MCBSP_ST_WRITE(mcbsp, reg, val) \
@@ -878,7 +875,7 @@ EXPORT_SYMBOL(omap_mcbsp_free);
 void omap_mcbsp_start(unsigned int id, int tx, int rx)
 {
        struct omap_mcbsp *mcbsp;
-       int idle;
+       int enable_srg = 0;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -893,10 +890,13 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
        mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
        mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
 
-       idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
-                       MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+       /* Only enable SRG, if McBSP is master */
+       w = MCBSP_READ_CACHE(mcbsp, PCR0);
+       if (w & (FSXM | FSRM | CLKXM | CLKRM))
+               enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+                               MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
 
-       if (idle) {
+       if (enable_srg) {
                /* Start the sample generator */
                w = MCBSP_READ_CACHE(mcbsp, SPCR2);
                MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
@@ -919,7 +919,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
         */
        udelay(500);
 
-       if (idle) {
+       if (enable_srg) {
                /* Start frame sync */
                w = MCBSP_READ_CACHE(mcbsp, SPCR2);
                MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
@@ -1645,7 +1645,7 @@ static const struct attribute_group sidetone_attr_group = {
        .attrs = (struct attribute **)sidetone_attrs,
 };
 
-int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 {
        struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
        struct omap_mcbsp_st_data *st_data;
index d2b1609..abe933c 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
 #define USE_WAKEUP_LAT                 0
 #define IGNORE_WAKEUP_LAT              1
 
-/*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
-#define OMAP_DEVICE_MAGIC               0xf00dcafe
-
 /* Private functions */
 
 /**
@@ -243,6 +238,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
        return container_of(pdev, struct omap_device, pdev);
 }
 
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+                                     struct omap_hwmod *oh)
+{
+       int i;
+
+       for (i = 0; i < oh->opt_clks_cnt; i++) {
+               struct omap_hwmod_opt_clk *oc;
+               int r;
+
+               oc = &oh->opt_clks[i];
+
+               if (!oc->_clk)
+                       continue;
+
+               r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+                                 (char *)oc->clk, &od->pdev.dev);
+               if (r)
+                       pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+                              dev_name(&od->pdev.dev), oc->role);
+       }
+}
+
 
 /* Public functions for use by core code */
 
@@ -257,12 +290,11 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
  */
 int omap_device_count_resources(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               c += omap_hwmod_count_resources(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               c += omap_hwmod_count_resources(od->hwmods[i]);
 
        pr_debug("omap_device: %s: counted %d total resources across %d "
                 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
@@ -289,12 +321,11 @@ int omap_device_count_resources(struct omap_device *od)
  */
 int omap_device_fill_resources(struct omap_device *od, struct resource *res)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i, r;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) {
-               r = omap_hwmod_fill_resources(oh, res);
+       for (i = 0; i < od->hwmods_cnt; i++) {
+               r = omap_hwmod_fill_resources(od->hwmods[i], res);
                res += r;
                c += r;
        }
@@ -414,15 +445,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
        od->pm_lats = pm_lats;
        od->pm_lats_cnt = pm_lats_cnt;
 
-       od->magic = OMAP_DEVICE_MAGIC;
-
        if (is_early_device)
                ret = omap_early_device_register(od);
        else
                ret = omap_device_register(od);
 
-       for (i = 0; i < oh_cnt; i++)
+       for (i = 0; i < oh_cnt; i++) {
                hwmods[i]->od = od;
+               _add_optional_clock_alias(od, hwmods[i]);
+       }
 
        if (ret)
                goto odbs_exit4;
@@ -473,6 +504,7 @@ int omap_device_register(struct omap_device *od)
 {
        pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
+       od->pdev.dev.parent = &omap_device_parent;
        return platform_device_register(&od->pdev);
 }
 
@@ -566,7 +598,6 @@ int omap_device_shutdown(struct platform_device *pdev)
 {
        int ret, i;
        struct omap_device *od;
-       struct omap_hwmod *oh;
 
        od = _find_by_pdev(pdev);
 
@@ -579,8 +610,8 @@ int omap_device_shutdown(struct platform_device *pdev)
 
        ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_shutdown(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_shutdown(od->hwmods[i]);
 
        od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
 
@@ -627,18 +658,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
 }
 
 /**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
-bool omap_device_is_valid(struct omap_device *od)
-{
-       return (od && od->magic == OMAP_DEVICE_MAGIC);
-}
-
-/**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *
  *
@@ -692,11 +711,10 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
  */
 int omap_device_enable_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -710,11 +728,10 @@ int omap_device_enable_hwmods(struct omap_device *od)
  */
 int omap_device_idle_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_idle(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_idle(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -729,11 +746,10 @@ int omap_device_idle_hwmods(struct omap_device *od)
  */
 int omap_device_disable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_disable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_disable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -748,12 +764,22 @@ int omap_device_disable_clocks(struct omap_device *od)
  */
 int omap_device_enable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
 }
+
+struct device omap_device_parent = {
+       .init_name      = "omap",
+       .parent         = &platform_bus,
+};
+
+static int __init omap_device_init(void)
+{
+       return device_register(&omap_device_parent);
+}
+core_initcall(omap_device_init);
index 10b3b4c..e2c8eeb 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -30,8 +31,8 @@
 #include <plat/cpu.h>
 #include <plat/vram.h>
 
-#include <plat/control.h>
-
+#include "sram.h"
+#include "fb.h"
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 # include "../mach-omap2/prm.h"
 # include "../mach-omap2/cm.h"
@@ -53,7 +54,7 @@
 #define OMAP4_SRAM_PUB_PA      (OMAP4_SRAM_PA + 0x4000)
 #define OMAP4_SRAM_PUB_VA      (OMAP4_SRAM_VA + 0x4000)
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ     0x00
 #else
 #define SRAM_BOOTLOADER_SZ     0x80
@@ -68,7 +69,6 @@
 #define OMAP34XX_VA_WRITEPERM0         OMAP2_L3_IO_ADDRESS(0x68012858)
 #define OMAP34XX_VA_ADDR_MATCH2                OMAP2_L3_IO_ADDRESS(0x68012880)
 #define OMAP34XX_VA_SMS_RG_ATT0                OMAP2_L3_IO_ADDRESS(0x6C000048)
-#define OMAP34XX_VA_CONTROL_STAT       OMAP2_L4_IO_ADDRESS(0x480022F0)
 
 #define GP_DEVICE              0x300
 
@@ -79,12 +79,6 @@ static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
-extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
-                                        unsigned long sram_vstart,
-                                        unsigned long sram_size,
-                                        unsigned long pstart_avail,
-                                        unsigned long size_avail);
-
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
  * SRAM varies.  The default accessible size for all device types is 2k. A GP
@@ -93,16 +87,7 @@ extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
  */
 static int is_sram_locked(void)
 {
-       int type = 0;
-
-       if (cpu_is_omap44xx())
-               /* Not yet supported */
-               return 0;
-
-       if (cpu_is_omap242x())
-               type = omap_rev() & OMAP2_DEVICETYPE_MASK;
-
-       if (type == GP_DEVICE) {
+       if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
                /* RAMFW: R/W access to all initiators for all qualifier sets */
                if (cpu_is_omap242x()) {
                        __raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
@@ -127,7 +112,7 @@ static int is_sram_locked(void)
  * to secure SRAM will hang the system. Also the SRAM is not
  * yet mapped at this point.
  */
-void __init omap_detect_sram(void)
+static void __init omap_detect_sram(void)
 {
        unsigned long reserved;
 
@@ -213,7 +198,7 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
-void __init omap_map_sram(void)
+static void __init omap_map_sram(void)
 {
        unsigned long base;
 
@@ -330,7 +315,7 @@ u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2420
-int __init omap242x_sram_init(void)
+static int __init omap242x_sram_init(void)
 {
        _omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
                                        omap242x_sram_ddr_init_sz);
@@ -351,7 +336,7 @@ static inline int omap242x_sram_init(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2430
-int __init omap243x_sram_init(void)
+static int __init omap243x_sram_init(void)
 {
        _omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
                                        omap243x_sram_ddr_init_sz);
@@ -407,7 +392,7 @@ void omap3_sram_restore_context(void)
 }
 #endif /* CONFIG_PM */
 
-int __init omap34xx_sram_init(void)
+static int __init omap34xx_sram_init(void)
 {
        _omap3_sram_configure_core_dpll =
                omap_sram_push(omap3_sram_configure_core_dpll,
@@ -423,7 +408,7 @@ static inline int omap34xx_sram_init(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-int __init omap44xx_sram_init(void)
+static int __init omap44xx_sram_init(void)
 {
        printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
 
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
new file mode 100644 (file)
index 0000000..29b43ef
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __PLAT_OMAP_SRAM_H__
+#define __PLAT_OMAP_SRAM_H__
+
+extern int __init omap_sram_init(void);
+
+#endif /* __PLAT_OMAP_SRAM_H__ */
index 452e184..2f91057 100644 (file)
@@ -247,7 +247,7 @@ static struct resource s3c_iis_resource[] = {
 static u64 s3c_device_iis_dmamask = 0xffffffffUL;
 
 struct platform_device s3c_device_iis = {
-       .name             = "s3c2410-iis",
+       .name             = "s3c24xx-iis",
        .id               = -1,
        .num_resources    = ARRAY_SIZE(s3c_iis_resource),
        .resource         = s3c_iis_resource,
@@ -259,6 +259,21 @@ struct platform_device s3c_device_iis = {
 
 EXPORT_SYMBOL(s3c_device_iis);
 
+/* ASoC PCM DMA */
+
+static u64 s3c_device_audio_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_pcm = {
+       .name             = "s3c24xx-pcm-audio",
+       .id               = -1,
+       .dev              = {
+               .dma_mask = &s3c_device_audio_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c_device_pcm);
+
 /* RTC */
 
 static struct resource s3c_rtc_resource[] = {
@@ -481,19 +496,30 @@ static struct resource s3c_ac97_resource[] = {
        },
 };
 
-static u64 s3c_device_ac97_dmamask = 0xffffffffUL;
-
 struct platform_device s3c_device_ac97 = {
        .name             = "s3c-ac97",
        .id               = -1,
        .num_resources    = ARRAY_SIZE(s3c_ac97_resource),
        .resource         = s3c_ac97_resource,
        .dev              = {
-               .dma_mask = &s3c_device_ac97_dmamask,
+               .dma_mask = &s3c_device_audio_dmamask,
                .coherent_dma_mask = 0xffffffffUL
        }
 };
 
 EXPORT_SYMBOL(s3c_device_ac97);
 
+/* ASoC I2S */
+
+struct platform_device s3c2412_device_iis = {
+       .name             = "s3c2412-iis",
+       .id               = -1,
+       .dev              = {
+               .dma_mask = &s3c_device_audio_dmamask,
+               .coherent_dma_mask = 0xffffffffUL
+       }
+};
+
+EXPORT_SYMBOL(s3c2412_device_iis);
+
 #endif // CONFIG_CPU_S32440
index 7d448e1..c8b9427 100644 (file)
@@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4;
 extern struct platform_device s3c64xx_device_spi0;
 extern struct platform_device s3c64xx_device_spi1;
 
+extern struct platform_device s3c_device_pcm;
+
 extern struct platform_device s3c64xx_device_pcm0;
 extern struct platform_device s3c64xx_device_pcm1;
 
index d1825cb..acb8379 100644 (file)
@@ -102,17 +102,6 @@ config DEBUG_DOUBLEFAULT_RESET
 
 endchoice
 
-config DEBUG_ICACHE_CHECK
-       bool "Check Instruction cache coherency"
-       depends on DEBUG_KERNEL
-       depends on DEBUG_HWERR
-       help
-         Say Y here if you are getting weird unexplained errors. This will
-         ensure that icache is what SDRAM says it should be by doing a
-         byte wise comparison between SDRAM and instruction cache. This
-         also relocates the irq_panic() function to L1 memory, (which is
-         un-cached).
-
 config DEBUG_HUNT_FOR_ZERO
        bool "Catch NULL pointer reads/writes"
        default y
index 46fac1b..c0b988e 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -114,7 +115,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 8024080..864af5b 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -152,7 +153,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 08c55f6..7b6a337 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_EMBEDDED=y
 # CONFIG_ELF_CORE is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -101,5 +102,4 @@ CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
index 4a91255..4faa6b4 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_2=y
@@ -38,6 +39,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -181,6 +183,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 8ccf3ce..9d893eb 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_1=y
@@ -37,6 +38,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -173,6 +175,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 92ded5e..97a2767 100644 (file)
@@ -174,7 +174,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC7=m
index c40e0f1..f847743 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BFIN533_EZKIT=y
 CONFIG_TIMER0=11
@@ -107,6 +108,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index aa8c1d7..0e7262c 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_TIMER0=11
 CONFIG_HIGH_RES_TIMERS=y
@@ -121,6 +122,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index f245c0b..4d14a00 100644 (file)
@@ -20,9 +20,9 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
-CONFIG_IRQ_ERROR=11
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
@@ -133,6 +133,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 74a330c..fbee9d7 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF538=y
 CONFIG_IRQ_TIMER0=12
@@ -31,6 +32,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -129,6 +131,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 29373cb..05dd11d 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -62,7 +63,7 @@ CONFIG_IRCOMM=m
 CONFIG_IRTTY_SIR=m
 CONFIG_BFIN_SIR=m
 CONFIG_BFIN_SIR3=y
-CONFIG_LIB80211=m
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
@@ -92,6 +93,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
index 1f12034..bcb14d1 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_EMBEDDED=y
 # CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
@@ -44,6 +45,7 @@ CONFIG_IP_PNP=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +73,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -147,5 +150,4 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 8913d99..843aaa5 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0xAAC2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
index 0242917..dae7adf 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -63,6 +64,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -104,5 +106,4 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
index 0512fef..f341424 100644 (file)
@@ -50,6 +50,7 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -70,9 +71,9 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
-CONFIG_BFIN_MAC_RMII=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -124,7 +125,6 @@ CONFIG_DEBUG_FS=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 05e09be..8c7e08f 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_BINFMT_SHARED_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -47,6 +48,7 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -72,7 +74,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index d2eb532..bd3cb76 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -65,6 +66,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 9d52c44..82224f3 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_INET=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -59,6 +60,7 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -90,7 +92,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index 9de13cf..433598c 100644 (file)
@@ -49,6 +49,7 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +72,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_EVBUG=m
@@ -167,7 +169,6 @@ CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
index 238353a..ded7d84 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -67,6 +68,7 @@ CONFIG_MII=y
 CONFIG_SMSC911X=m
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index 0cb524e..700fb70 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_IRLAN=m
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -50,6 +51,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -84,4 +86,3 @@ CONFIG_NFS_V3=y
 CONFIG_NLS=m
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
index 2a3411e..b40156d 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_MANGLE=y
+# CONFIG_WIRELESS is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
@@ -60,6 +61,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -89,5 +91,4 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
index fea3033..be866d9 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
 CONFIG_IRQ_TIMER0=12
@@ -107,7 +108,6 @@ CONFIG_SMB_FS=m
 # CONFIG_DEBUG_HUNT_FOR_ZERO is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 # CONFIG_ACCESS_CHECK is not set
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 9811b31..b64bdf7 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_IRLAN=m
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -51,6 +52,7 @@ CONFIG_EEPROM_AT25=m
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -85,4 +87,3 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
index 412bf79..1bccd9a 100644 (file)
@@ -128,7 +128,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 04bf52c..00ce899 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -57,6 +58,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 0b5136e..5392583 100644 (file)
@@ -60,6 +60,8 @@ struct bfin_spi_regs {
        __BFP(shadow);
 };
 
+#undef __BFP
+
 #define MAX_CTRL_CS          8  /* cs in spi controller */
 
 /* device.platform_data for SSP controller devices */
index 0039008..3be05fa 100644 (file)
@@ -48,4 +48,6 @@ struct bfin_eppi_regs {
        u32 clip;
 };
 
+#undef __BFP
+
 #endif
diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h
new file mode 100644 (file)
index 0000000..e767d64
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * bfin_twi.h - interface to Blackfin TWIs
+ *
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_TWI_H__
+#define __ASM_BFIN_TWI_H__
+
+#include <linux/types.h>
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin twi registers layout
+ */
+struct bfin_twi_regs {
+       __BFP(clkdiv);
+       __BFP(control);
+       __BFP(slave_ctl);
+       __BFP(slave_stat);
+       __BFP(slave_addr);
+       __BFP(master_ctl);
+       __BFP(master_stat);
+       __BFP(master_addr);
+       __BFP(int_stat);
+       __BFP(int_mask);
+       __BFP(fifo_ctl);
+       __BFP(fifo_stat);
+       u32 __pad[20];
+       __BFP(xmt_data8);
+       __BFP(xmt_data16);
+       __BFP(rcv_data8);
+       __BFP(rcv_data16);
+};
+
+#undef __BFP
+
+#endif
index a1f6817..59af63c 100644 (file)
 #define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
 #define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
 
-#if ANOMALY_05000481
+#if !ANOMALY_05000481
 #define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
 #define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
 #define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
index f95e609..b894c8a 100644 (file)
@@ -87,13 +87,55 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = {
+       P_MII0_ETxD0,
+       P_MII0_ETxD1,
+       P_MII0_ETxEN,
+       P_MII0_ERxD0,
+       P_MII0_ERxD1,
+       P_MII0_TxCLK,
+       P_MII0_PHYINT,
+       P_MII0_CRS,
+       P_MII0_MDC,
+       P_MII0_MDIO,
+       0
+};
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+       {
+               .addr = 2,
+               .irq = IRQ_MAC_PHYINT,
+       },
+       {
+               .addr = 3,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 3,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
index bead810..e6ce1d7 100644 (file)
@@ -81,13 +81,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 38037c7..2c31af7 100644 (file)
@@ -273,13 +273,35 @@ static struct platform_device dm9000_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 6cc64a1..9a736a8 100644 (file)
@@ -193,13 +193,35 @@ static struct platform_device rtc_device = {
 
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index df82723..9222bc0 100644 (file)
@@ -366,13 +366,35 @@ static struct platform_device dm9000_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index ae4130e..9ec5757 100644 (file)
@@ -257,13 +257,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index e2e7be4..836698c 100644 (file)
@@ -597,13 +597,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 752c833..2a85670 100644 (file)
@@ -562,13 +562,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 05d4599..4980051 100644 (file)
@@ -68,13 +68,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 6b03808..b958078 100644 (file)
@@ -99,13 +99,35 @@ static struct platform_device smc91x_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index cd2c797..3aa344c 100644 (file)
@@ -327,13 +327,35 @@ static struct platform_device bfin_can_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = PHY_POLL, /* IRQ_MAC_PHYINT */
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index a4d62b5..31498ad 100644 (file)
@@ -564,13 +564,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 814cb48..ff299f2 100644 (file)
@@ -11,4 +11,3 @@ obj-$(CONFIG_CPU_FREQ)    += cpufreq.o
 obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
 obj-$(CONFIG_SMP)         += smp.o
 obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
-obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
deleted file mode 100644 (file)
index c649624..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * panic kernel with dump information
- *
- * Copyright 2005-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <asm/blackfin.h>
-
-#define L1_ICACHE_START 0xffa10000
-#define L1_ICACHE_END   0xffa13fff
-
-/*
- * irq_panic - calls panic with string setup
- */
-__attribute__ ((l1_text))
-asmlinkage void irq_panic(int reason, struct pt_regs *regs)
-{
-       unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
-       unsigned short i, j, die;
-       unsigned int bad[10][6];
-
-       /* check entire cache for coherency
-        * Since printk is in cacheable memory,
-        * don't call it until you have checked everything
-       */
-
-       die = 0;
-       i = 0;
-
-       /* check icache */
-
-       for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) {
-
-               /* Grab various address bits for the itest_cmd fields                      */
-               cmd = (((ca & 0x3000) << 4) |   /* ca[13:12] for SBNK[1:0]             */
-                      ((ca & 0x0c00) << 16) |  /* ca[11:10] for WAYSEL[1:0]           */
-                      ((ca & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0]  */
-                      0);      /* Access Tag, Read access             */
-
-               SSYNC();
-               bfin_write_ITEST_COMMAND(cmd);
-               SSYNC();
-               tag = bfin_read_ITEST_DATA0();
-               SSYNC();
-
-               /* if tag is marked as valid, check it */
-               if (tag & 1) {
-                       /* The icache is arranged in 4 groups of 64-bits */
-                       for (j = 0; j < 32; j += 8) {
-                               cmd = ((((ca + j) & 0x3000) << 4) |     /* ca[13:12] for SBNK[1:0]             */
-                                      (((ca + j) & 0x0c00) << 16) |    /* ca[11:10] for WAYSEL[1:0]           */
-                                      (((ca + j) & 0x3f8)) |   /* ca[09:03] for SET[4:0] and DW[1:0]  */
-                                      4);      /* Access Data, Read access             */
-
-                               SSYNC();
-                               bfin_write_ITEST_COMMAND(cmd);
-                               SSYNC();
-
-                               cache_hi = bfin_read_ITEST_DATA1();
-                               cache_lo = bfin_read_ITEST_DATA0();
-
-                               pa = ((unsigned int *)((tag & 0xffffcc00) |
-                                                      ((ca + j) & ~(0xffffcc00))));
-
-                               /*
-                                * Debugging this, enable
-                                *
-                                * printk("addr: %08x %08x%08x | %08x%08x\n",
-                                *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))),
-                                *   cache_hi, cache_lo, *(pa+1), *pa);
-                                */
-
-                               if (cache_hi != *(pa + 1) || cache_lo != *pa) {
-                                       /* Since icache is not working, stay out of it, by not printing */
-                                       die = 1;
-                                       bad[i][0] = (ca + j);
-                                       bad[i][1] = cache_hi;
-                                       bad[i][2] = cache_lo;
-                                       bad[i][3] = ((tag & 0xffffcc00) |
-                                               ((ca + j) & ~(0xffffcc00)));
-                                       bad[i][4] = *(pa + 1);
-                                       bad[i][5] = *(pa);
-                                       i++;
-                               }
-                       }
-               }
-       }
-       if (die) {
-               printk(KERN_EMERG "icache coherency error\n");
-               for (j = 0; j <= i; j++) {
-                       printk(KERN_EMERG
-                           "cache address   : %08x  cache value : %08x%08x\n",
-                            bad[j][0], bad[j][1], bad[j][2]);
-                       printk(KERN_EMERG
-                           "physical address: %08x  SDRAM value : %08x%08x\n",
-                            bad[j][3], bad[j][4], bad[j][5]);
-               }
-               panic("icache coherency error");
-       } else
-               printk(KERN_EMERG "icache checked, and OK\n");
-}
index 89f1956..7085bd5 100644 (file)
@@ -29,7 +29,7 @@
 
 static inline void __flush_cache_all(void)
 {
-#ifdef CONFIG_M5407
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
        /*
         *      Use cpushl to push and invalidate all cache lines.
         *      Gas doesn't seem to know how to generate the ColdFire
index 83a9fa4..3b0a34d 100644 (file)
@@ -32,7 +32,9 @@
  */
 #define        MCF_MBAR        0x10000000
 #define        MCF_MBAR2       0x80000000
-#if defined(CONFIG_M520x)
+#if defined(CONFIG_M548x)
+#define        MCF_IPSBAR      MCF_MBAR
+#elif defined(CONFIG_M520x)
 #define        MCF_IPSBAR      0xFC000000
 #else
 #define        MCF_IPSBAR      0x40000000
index 283214d..1b57adb 100644 (file)
@@ -36,7 +36,8 @@
  */
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
     defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
-    defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+    defined(CONFIG_M532x) || defined(CONFIG_M548x)
 
 /* These parts have GPIO organized by 8 bit ports */
 
@@ -136,6 +137,8 @@ static inline u32 __mcf_gpio_ppdr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
@@ -173,6 +176,8 @@ static inline u32 __mcf_gpio_podr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
diff --git a/arch/m68k/include/asm/m548xgpt.h b/arch/m68k/include/asm/m548xgpt.h
new file mode 100644 (file)
index 0000000..c8ef158
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * File:       m548xgpt.h
+ * Purpose:    Register and bit definitions for the MCF548X
+ *
+ * Notes:
+ *
+ */
+
+#ifndef m548xgpt_h
+#define m548xgpt_h
+
+/*********************************************************************
+*
+* General Purpose Timers (GPT)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPT_GMS0       0x000800
+#define MCF_GPT_GCIR0      0x000804
+#define MCF_GPT_GPWM0      0x000808
+#define MCF_GPT_GSR0       0x00080C
+#define MCF_GPT_GMS1       0x000810
+#define MCF_GPT_GCIR1      0x000814
+#define MCF_GPT_GPWM1      0x000818
+#define MCF_GPT_GSR1       0x00081C
+#define MCF_GPT_GMS2       0x000820
+#define MCF_GPT_GCIR2      0x000824
+#define MCF_GPT_GPWM2      0x000828
+#define MCF_GPT_GSR2       0x00082C
+#define MCF_GPT_GMS3       0x000830
+#define MCF_GPT_GCIR3      0x000834
+#define MCF_GPT_GPWM3      0x000838
+#define MCF_GPT_GSR3       0x00083C
+#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
+#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
+#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
+#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
+
+/* Bit definitions and macros for MCF_GPT_GMS */
+#define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
+#define MCF_GPT_GMS_GPIO(x)        (((x)&0x00000003)<<4)
+#define MCF_GPT_GMS_IEN            (0x00000100)
+#define MCF_GPT_GMS_OD             (0x00000200)
+#define MCF_GPT_GMS_SC             (0x00000400)
+#define MCF_GPT_GMS_CE             (0x00001000)
+#define MCF_GPT_GMS_WDEN           (0x00008000)
+#define MCF_GPT_GMS_ICT(x)         (((x)&0x00000003)<<16)
+#define MCF_GPT_GMS_OCT(x)         (((x)&0x00000003)<<20)
+#define MCF_GPT_GMS_OCPW(x)        (((x)&0x000000FF)<<24)
+#define MCF_GPT_GMS_OCT_FRCLOW     (0x00000000)
+#define MCF_GPT_GMS_OCT_PULSEHI    (0x00100000)
+#define MCF_GPT_GMS_OCT_PULSELO    (0x00200000)
+#define MCF_GPT_GMS_OCT_TOGGLE     (0x00300000)
+#define MCF_GPT_GMS_ICT_ANY        (0x00000000)
+#define MCF_GPT_GMS_ICT_RISE       (0x00010000)
+#define MCF_GPT_GMS_ICT_FALL       (0x00020000)
+#define MCF_GPT_GMS_ICT_PULSE      (0x00030000)
+#define MCF_GPT_GMS_GPIO_INPUT     (0x00000000)
+#define MCF_GPT_GMS_GPIO_OUTLO     (0x00000020)
+#define MCF_GPT_GMS_GPIO_OUTHI     (0x00000030)
+#define MCF_GPT_GMS_TMS_DISABLE    (0x00000000)
+#define MCF_GPT_GMS_TMS_INCAPT     (0x00000001)
+#define MCF_GPT_GMS_TMS_OUTCAPT    (0x00000002)
+#define MCF_GPT_GMS_TMS_PWM        (0x00000003)
+#define MCF_GPT_GMS_TMS_GPIO       (0x00000004)
+
+/* Bit definitions and macros for MCF_GPT_GCIR */
+#define MCF_GPT_GCIR_CNT(x)        (((x)&0x0000FFFF)<<0)
+#define MCF_GPT_GCIR_PRE(x)        (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GPWM */
+#define MCF_GPT_GPWM_LOAD          (0x00000001)
+#define MCF_GPT_GPWM_PWMOP         (0x00000100)
+#define MCF_GPT_GPWM_WIDTH(x)      (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GSR */
+#define MCF_GPT_GSR_CAPT           (0x00000001)
+#define MCF_GPT_GSR_COMP           (0x00000002)
+#define MCF_GPT_GSR_PWMP           (0x00000004)
+#define MCF_GPT_GSR_TEXP           (0x00000008)
+#define MCF_GPT_GSR_PIN            (0x00000100)
+#define MCF_GPT_GSR_OVF(x)         (((x)&0x00000007)<<12)
+#define MCF_GPT_GSR_CAPTURE(x)     (((x)&0x0000FFFF)<<16)
+
+/********************************************************************/
+
+#endif /* m548xgpt_h */
diff --git a/arch/m68k/include/asm/m548xsim.h b/arch/m68k/include/asm/m548xsim.h
new file mode 100644 (file)
index 0000000..149135e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *     m548xsim.h -- ColdFire 547x/548x System Integration Unit support.
+ */
+
+#ifndef        m548xsim_h
+#define m548xsim_h
+
+#define MCFINT_VECBASE      64
+
+/*
+ *      Interrupt Controller Registers
+ */
+#define MCFICM_INTC0           0x0700          /* Base for Interrupt Ctrl 0 */
+#define MCFINTC_IPRH           0x00            /* Interrupt pending 32-63 */
+#define MCFINTC_IPRL           0x04            /* Interrupt pending 1-31 */
+#define MCFINTC_IMRH           0x08            /* Interrupt mask 32-63 */
+#define MCFINTC_IMRL           0x0c            /* Interrupt mask 1-31 */
+#define MCFINTC_INTFRCH                0x10            /* Interrupt force 32-63 */
+#define MCFINTC_INTFRCL                0x14            /* Interrupt force 1-31 */
+#define MCFINTC_IRLR           0x18            /* */
+#define MCFINTC_IACKL          0x19            /* */
+#define MCFINTC_ICR0           0x40            /* Base ICR register */
+
+/*
+ *     Define system peripheral IRQ usage.
+ */
+#define MCF_IRQ_TIMER          (64 + 54)       /* Slice Timer 0 */
+#define MCF_IRQ_PROFILER       (64 + 53)       /* Slice Timer 1 */
+
+/*
+ *     Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX                0       /* I am too lazy to count */
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
+
+/*
+ *     Some PSC related definitions
+ */
+#define MCF_PAR_PSC(x)         (0x000A4F-((x)&0x3))
+#define MCF_PAR_SDA            (0x0008)
+#define MCF_PAR_SCL            (0x0004)
+#define MCF_PAR_PSC_TXD                (0x04)
+#define MCF_PAR_PSC_RXD                (0x08)
+#define MCF_PAR_PSC_RTS(x)     (((x)&0x03)<<4)
+#define MCF_PAR_PSC_CTS(x)     (((x)&0x03)<<6)
+#define MCF_PAR_PSC_CTS_GPIO   (0x00)
+#define MCF_PAR_PSC_CTS_BCLK   (0x80)
+#define MCF_PAR_PSC_CTS_CTS    (0xC0)
+#define MCF_PAR_PSC_RTS_GPIO    (0x00)
+#define MCF_PAR_PSC_RTS_FSYNC  (0x20)
+#define MCF_PAR_PSC_RTS_RTS    (0x30)
+#define MCF_PAR_PSC_CANRX      (0x40)
+
+#endif /* m548xsim_h */
index c042634..f49dfc0 100644 (file)
 .endm
 #endif /* CONFIG_M532x */
 
-#if defined(CONFIG_M5407)
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
 /*
  *     Version 4 cores have a true harvard style separate instruction
  *     and data cache. Invalidate and enable cache, also enable write
index 9c70a67..6901fd6 100644 (file)
@@ -41,6 +41,8 @@
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
 #include <asm/mcfintc.h>
+#elif defined(CONFIG_M548x)
+#include <asm/m548xsim.h>
 #endif
 
 /****************************************************************************/
diff --git a/arch/m68k/include/asm/mcfslt.h b/arch/m68k/include/asm/mcfslt.h
new file mode 100644 (file)
index 0000000..d0d0ecb
--- /dev/null
@@ -0,0 +1,44 @@
+/****************************************************************************/
+
+/*
+ *     mcfslt.h -- ColdFire internal Slice (SLT) timer support defines.
+ *
+ *     (C) Copyright 2004, Greg Ungerer (gerg@snapgear.com)
+ *     (C) Copyright 2009, Philippe De Muyter (phdm@macqel.be)
+ */
+
+/****************************************************************************/
+#ifndef mcfslt_h
+#define mcfslt_h
+/****************************************************************************/
+
+/*
+ *     Get address specific defines for the 547x.
+ */
+#define MCFSLT_TIMER0          0x900   /* Base address of TIMER0 */
+#define MCFSLT_TIMER1          0x910   /* Base address of TIMER1 */
+
+
+/*
+ *     Define the SLT timer register set addresses.
+ */
+#define MCFSLT_STCNT           0x00    /* Terminal count */
+#define MCFSLT_SCR             0x04    /* Control */
+#define MCFSLT_SCNT            0x08    /* Current count */
+#define MCFSLT_SSR             0x0C    /* Status */
+
+/*
+ *     Bit definitions for the SCR control register.
+ */
+#define MCFSLT_SCR_RUN         0x04000000      /* Run mode (continuous) */
+#define MCFSLT_SCR_IEN         0x02000000      /* Interrupt enable */
+#define MCFSLT_SCR_TEN         0x01000000      /* Timer enable */
+
+/*
+ *     Bit definitions for the SSR status register.
+ */
+#define MCFSLT_SSR_BE          0x02000000      /* Bus error condition */
+#define MCFSLT_SSR_TE          0x01000000      /* Timeout condition */
+
+/****************************************************************************/
+#endif /* mcfslt_h */
index 01a8716..db72e2b 100644 (file)
 #define MCFUART_BASE1          0xfc060000      /* Base address of UART1 */
 #define MCFUART_BASE2          0xfc064000      /* Base address of UART2 */
 #define MCFUART_BASE3          0xfc068000      /* Base address of UART3 */
+#elif defined(CONFIG_M548x)
+#define MCFUART_BASE1          0x8600          /* on M548x */
+#define MCFUART_BASE2          0x8700          /* on M548x */
+#define MCFUART_BASE3          0x8800          /* on M548x */
+#define MCFUART_BASE4          0x8900          /* on M548x */
 #endif
 
 
@@ -212,7 +217,9 @@ struct mcf_platform_uart {
 #define        MCFUART_URF_RXS         0xc0            /* Receiver status */
 #endif
 
-#if defined(CONFIG_M5272)
+#if defined(CONFIG_M548x)
+#define MCFUART_TXFIFOSIZE     512
+#elif defined(CONFIG_M5272)
 #define MCFUART_TXFIFOSIZE     25
 #else
 #define MCFUART_TXFIFOSIZE     1
index 73e5e58..78e59b8 100644 (file)
 int main(void)
 {
        /* offsets into the task struct */
-       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
        DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 #ifdef CONFIG_MMU
        DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
 #endif
@@ -64,14 +60,6 @@ int main(void)
        /* bitfields are a bit difficult */
        DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
 
-       /* offsets into the irq_handler struct */
-       DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
-       DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
-       DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
-
-       /* offsets into the kernel_stat struct */
-       DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
-
        /* offsets into the irq_cpustat_t struct */
        DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
 
index 2609c39..9287150 100644 (file)
@@ -59,6 +59,10 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       bool
+       default y
+
 config GENERIC_CALIBRATE_DELAY
        bool
        default y
@@ -171,6 +175,11 @@ config M5407
        help
          Motorola ColdFire 5407 processor support.
 
+config M548x
+       bool "MCF548x"
+       help
+         Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
 endchoice
 
 config M527x
@@ -181,7 +190,7 @@ config M527x
 
 config COLDFIRE
        bool
-       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
+       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M548x)
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
        default y
index 1404257..026ef16 100644 (file)
@@ -25,6 +25,7 @@ platform-$(CONFIG_M528x)      := 528x
 platform-$(CONFIG_M5307)       := 5307
 platform-$(CONFIG_M532x)       := 532x
 platform-$(CONFIG_M5407)       := 5407
+platform-$(CONFIG_M548x)       := 548x
 PLATFORM := $(platform-y)
 
 board-$(CONFIG_PILOT)          := pilot
@@ -73,6 +74,7 @@ cpuclass-$(CONFIG_M528x)      := coldfire
 cpuclass-$(CONFIG_M5307)       := coldfire
 cpuclass-$(CONFIG_M532x)       := coldfire
 cpuclass-$(CONFIG_M5407)       := coldfire
+cpuclass-$(CONFIG_M548x)       := coldfire
 cpuclass-$(CONFIG_M68328)      := 68328
 cpuclass-$(CONFIG_M68EZ328)    := 68328
 cpuclass-$(CONFIG_M68VZ328)    := 68328
@@ -100,6 +102,7 @@ cflags-$(CONFIG_M528x)              := $(call cc-option,-m528x,-m5307)
 cflags-$(CONFIG_M5307)         := $(call cc-option,-m5307,-m5200)
 cflags-$(CONFIG_M532x)         := $(call cc-option,-mcpu=532x,-m5307)
 cflags-$(CONFIG_M5407)         := $(call cc-option,-m5407,-m5200)
+cflags-$(CONFIG_M548x)         := $(call cc-option,-m5407,-m5200)
 cflags-$(CONFIG_M68328)                := -m68000
 cflags-$(CONFIG_M68EZ328)      := -m68000
 cflags-$(CONFIG_M68VZ328)      := -m68000
diff --git a/arch/m68knommu/kernel/.gitignore b/arch/m68knommu/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index 2433502..ffe02f4 100644 (file)
 int main(void)
 {
        /* offsets into the task struct */
-       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
-       DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 
        /* offsets into the irq_cpustat_t struct */
        DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
@@ -63,7 +57,7 @@ int main(void)
        DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
 #else
        /* bitfields are a bit difficult */
-       DEFINE(PT_OFF_VECTOR, offsetof(struct pt_regs, pc) + 4);
+       DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
 #endif
 
        /* signal defines */
@@ -75,11 +69,8 @@ int main(void)
        DEFINE(PT_PTRACED, PT_PTRACED);
 
        /* Offsets in thread_info structure */
-       DEFINE(TI_TASK, offsetof(struct thread_info, task));
-       DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
        DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
-       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 
        return 0;
 }
index f6be124..6fe7c38 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/signal.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -134,14 +135,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                        tmp >>= 16;
                        } else if (addr >= 21 && addr < 49) {
                                tmp = child->thread.fp[addr - 21];
-#ifdef CONFIG_M68KFPU_EMU
-                               /* Convert internal fpu reg representation
-                                * into long double format
-                                */
-                               if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
-                                       tmp = ((tmp & 0xffff0000) << 15) |
-                                             ((tmp & 0x0000ffff) << 16);
-#endif
                        } else if (addr == 49) {
                                tmp = child->mm->start_code;
                        } else if (addr == 50) {
@@ -175,16 +168,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        }
                        if (addr >= 21 && addr < 48)
                        {
-#ifdef CONFIG_M68KFPU_EMU
-                               /* Convert long double format
-                                * into internal fpu reg representation
-                                */
-                               if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
-                                       data = (unsigned long)data << 15;
-                                       data = (data & 0xffff0000) |
-                                              ((data & 0x0000ffff) >> 1);
-                               }
-#endif
                                child->thread.fp[addr - 21] = data;
                                ret = 0;
                        }
@@ -259,21 +242,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage int syscall_trace_enter(void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
+       int ret = 0;
+
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               ret = tracehook_report_syscall_entry(task_pt_regs(current));
+       return ret;
+}
+
+asmlinkage void syscall_trace_leave(void)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(task_pt_regs(current), 0);
 }
index ba92b90..c684adf 100644 (file)
@@ -54,9 +54,6 @@ void (*mach_reset)(void);
 void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
-#ifdef CONFIG_M68000
-       #define CPU "MC68000"
-#endif
 #ifdef CONFIG_M68328
        #define CPU "MC68328"
 #endif
index 7089dd9..d6ac2a4 100644 (file)
@@ -60,13 +60,16 @@ static unsigned long read_rtc_mmss(void)
 {
        unsigned int year, mon, day, hour, min, sec;
 
-       if (mach_gettod)
+       if (mach_gettod) {
                mach_gettod(&year, &mon, &day, &hour, &min, &sec);
-       else
-               year = mon = day = hour = min = sec = 0;
+               if ((year += 1900) < 1970)
+                       year += 100;
+       } else {
+               year = 1970;
+               mon = day = 1;
+               hour = min = sec = 0;
+       }
 
-       if ((year += 1900) < 1970)
-               year += 100;
 
        return  mktime(year, mon, day, hour, min, sec);
 }
index 3739c8f..a768008 100644 (file)
@@ -179,14 +179,16 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
 
 void bad_super_trap(struct frame *fp)
 {
+       int vector = (fp->ptregs.vector >> 2) & 0xff;
+
        console_verbose();
-       if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
+       if (vector < ARRAY_SIZE(vec_names))
                printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
-                       vec_names[(fp->ptregs.vector) >> 2],
+                       vec_names[vector],
                        fp->ptregs.format);
        else
                printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
-                       (fp->ptregs.vector) >> 2, 
+                       vector,
                        fp->ptregs.format);
        printk (KERN_WARNING "Current process id is %d\n", current->pid);
        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
@@ -195,10 +197,11 @@ void bad_super_trap(struct frame *fp)
 asmlinkage void trap_c(struct frame *fp)
 {
        int sig;
+       int vector = (fp->ptregs.vector >> 2) & 0xff;
        siginfo_t info;
 
        if (fp->ptregs.sr & PS_S) {
-               if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
+               if (vector == VEC_TRACE) {
                        /* traced a trapping instruction */
                } else
                        bad_super_trap(fp);
@@ -206,7 +209,7 @@ asmlinkage void trap_c(struct frame *fp)
        }
 
        /* send the appropriate signal to the user program */
-       switch ((fp->ptregs.vector) >> 2) {
+       switch (vector) {
            case VEC_ADDRERR:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
@@ -360,16 +363,3 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        else
                __show_stack(task, stack);
 }
-
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpemu_signal(int signal, int code, void *addr)
-{
-       siginfo_t info;
-
-       info.si_signo = signal;
-       info.si_errno = 0;
-       info.si_code = code;
-       info.si_addr = addr;
-       force_sig_info(signal, &info, current);
-}
-#endif
index 113c333..b5db056 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 113c333..b5db056 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 435ab34..ad3f4e5 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index b8f9b45..c04b8f7 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index f56225d..4bed30f 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 93673ef..34110fc 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 59278c0..65bb582 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
@@ -148,9 +150,23 @@ void __init config_BSP(char *commandp, int size)
 
 /***************************************************************************/
 
+/*
+ * Some 5272 based boards have the FEC ethernet diectly connected to
+ * an ethernet switch. In this case we need to use the fixed phy type,
+ * and we need to declare it early in boot.
+ */
+static struct fixed_phy_status nettel_fixed_phy_status __initdata = {
+       .link   = 1,
+       .speed  = 100,
+       .duplex = 0,
+};
+
+/***************************************************************************/
+
 static int __init init_BSP(void)
 {
        m5272_uarts_init();
+       fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status);
        platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices));
        return 0;
 }
index 7081e0a..3cf681c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/coldfire.h>
  * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
  * loose mapping of vector number to register and internal bits, but
  * a table is the easiest and quickest way to map them.
+ *
+ * Note that the external interrupts are edge triggered (unlike the
+ * internal interrupt sources which are level triggered). Which means
+ * they also need acknowledgeing via acknowledge bits.
  */
 struct irqmap {
        unsigned char   icr;
@@ -68,6 +73,11 @@ static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
        /*MCF_IRQ_SWTO*/        { .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
 };
 
+/*
+ * The act of masking the interrupt also has a side effect of 'ack'ing
+ * an interrupt on this irq (for the external irqs). So this mask function
+ * is also an ack_mask function.
+ */
 static void intc_irq_mask(unsigned int irq)
 {
        if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
@@ -95,7 +105,9 @@ static void intc_irq_ack(unsigned int irq)
                irq -= MCFINT_VECBASE;
                if (intc_irqmap[irq].ack) {
                        u32 v;
-                       v = 0xd << intc_irqmap[irq].index;
+                       v = readl(MCF_MBAR + intc_irqmap[irq].icr);
+                       v &= (0x7 << intc_irqmap[irq].index);
+                       v |= (0x8 << intc_irqmap[irq].index);
                        writel(v, MCF_MBAR + intc_irqmap[irq].icr);
                }
        }
@@ -103,21 +115,47 @@ static void intc_irq_ack(unsigned int irq)
 
 static int intc_irq_set_type(unsigned int irq, unsigned int type)
 {
-       /* We can set the edge type here for external interrupts */
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+               irq -= MCFINT_VECBASE;
+               if (intc_irqmap[irq].ack) {
+                       u32 v;
+                       v = readl(MCF_MBAR + MCFSIM_PITR);
+                       if (type == IRQ_TYPE_EDGE_FALLING)
+                               v &= ~(0x1 << (32 - irq));
+                       else
+                               v |= (0x1 << (32 - irq));
+                       writel(v, MCF_MBAR + MCFSIM_PITR);
+               }
+       }
        return 0;
 }
 
+/*
+ * Simple flow handler to deal with the external edge triggered interrupts.
+ * We need to be careful with the masking/acking due to the side effects
+ * of masking an interrupt.
+ */
+static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
+{
+       kstat_incr_irqs_this_cpu(irq, desc);
+       desc->status |= IRQ_INPROGRESS;
+       desc->chip->ack(irq);
+       handle_IRQ_event(irq, desc->action);
+       desc->status &= ~IRQ_INPROGRESS;
+}
+
 static struct irq_chip intc_irq_chip = {
        .name           = "CF-INTC",
        .mask           = intc_irq_mask,
        .unmask         = intc_irq_unmask,
+       .mask_ack       = intc_irq_mask,
        .ack            = intc_irq_ack,
        .set_type       = intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
 {
-       int irq;
+       int irq, edge;
 
        init_vectors();
 
@@ -128,11 +166,17 @@ void __init init_IRQ(void)
        writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               edge = 0;
+               if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX))
+                       edge = intc_irqmap[irq - MCFINT_VECBASE].ack;
+               if (edge) {
+                       set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+                       set_irq_handler(irq, intc_external_irq);
+               } else {
+                       set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+                       set_irq_handler(irq, handle_level_irq);
+               }
        }
 }
 
index 3d90e6d..6ac4b57 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 3d90e6d..6ac4b57 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 6de5269..d4293b7 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 4cc2324..ce01669 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index dee62c5..e83fe14 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
diff --git a/arch/m68knommu/platform/548x/Makefile b/arch/m68knommu/platform/548x/Makefile
new file mode 100644 (file)
index 0000000..e6035e7
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o
+
diff --git a/arch/m68knommu/platform/548x/config.c b/arch/m68knommu/platform/548x/config.c
new file mode 100644 (file)
index 0000000..9888846
--- /dev/null
@@ -0,0 +1,115 @@
+/***************************************************************************/
+
+/*
+ *     linux/arch/m68knommu/platform/548x/config.c
+ *
+ *     Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/m548xsim.h>
+#include <asm/mcfuart.h>
+#include <asm/m548xgpt.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m548x_uart_platform[] = {
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE1,
+               .irq            = 64 + 35,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE2,
+               .irq            = 64 + 34,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE3,
+               .irq            = 64 + 33,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE4,
+               .irq            = 64 + 32,
+       },
+};
+
+static struct platform_device m548x_uart = {
+       .name                   = "mcfuart",
+       .id                     = 0,
+       .dev.platform_data      = m548x_uart_platform,
+};
+
+static struct platform_device *m548x_devices[] __initdata = {
+       &m548x_uart,
+};
+
+
+/***************************************************************************/
+
+static void __init m548x_uart_init_line(int line, int irq)
+{
+       int rts_cts;
+
+       /* enable io pins */
+       switch (line) {
+       case 0:
+               rts_cts = 0; break;
+       case 1:
+               rts_cts = MCF_PAR_PSC_RTS_RTS; break;
+       case 2:
+               rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
+       case 3:
+               rts_cts = 0; break;
+       }
+       __raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
+                                               MCF_MBAR + MCF_PAR_PSC(line));
+}
+
+static void __init m548x_uarts_init(void)
+{
+       const int nrlines = ARRAY_SIZE(m548x_uart_platform);
+       int line;
+
+       for (line = 0; (line < nrlines); line++)
+               m548x_uart_init_line(line, m548x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void mcf548x_reset(void)
+{
+       /* disable interrupts and enable the watchdog */
+       asm("movew #0x2700, %sr\n");
+       __raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+       __raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
+                                               MCF_MBAR + MCF_GPT_GMS0);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+       mach_reset = mcf548x_reset;
+       m548x_uarts_init();
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+
+       platform_add_devices(m548x_devices, ARRAY_SIZE(m548x_devices));
+       return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
index 9d80d2c..27241e1 100644 (file)
@@ -43,10 +43,10 @@ badsys:
        jra     ret_from_exception
 
 do_trace:
-       movel   #-ENOSYS,%sp@(PT_OFF_D0)        /* needed for strace*/
+       movel   #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %sp@(PT_OFF_ORIG_D0),%d1
@@ -57,10 +57,10 @@ do_trace:
        lea     sys_call_table, %a0
        jbsr    %a0@(%d1)
 
-1:     movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
+1:     movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
@@ -71,16 +71,16 @@ ENTRY(system_call)
        SAVE_ALL
 
        /* save top of frame*/
-       pea     %sp@
-       jbsr    set_esp0
-       addql   #4,%sp
+       pea     %sp@
+       jbsr    set_esp0
+       addql   #4,%sp
 
        movel   %sp@(PT_OFF_ORIG_D0),%d0
 
        movel   %sp,%d1                 /* get thread_info pointer */
        andl    #-THREAD_SIZE,%d1
        movel   %d1,%a2
-       btst    #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS)
+       btst    #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
        jne     do_trace
        cmpl    #NR_syscalls,%d0
        jcc     badsys
@@ -88,10 +88,10 @@ ENTRY(system_call)
        lea     sys_call_table,%a0
        movel   %a0@(%d0), %a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_OFF_D0)             /* save the return value*/
+       movel   %d0,%sp@(PT_OFF_D0)     /* save the return value*/
 
 ret_from_exception:
-       btst    #5,%sp@(PT_OFF_SR)              /* check if returning to kernel*/
+       btst    #5,%sp@(PT_OFF_SR)      /* check if returning to kernel*/
        jeq     Luser_return            /* if so, skip resched, signals*/
 
 Lkernel_return:
@@ -133,7 +133,7 @@ Lreturn:
  */
 inthandler1:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -144,7 +144,7 @@ inthandler1:
 
 inthandler2:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -155,7 +155,7 @@ inthandler2:
 
 inthandler3:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -166,7 +166,7 @@ inthandler3:
 
 inthandler4:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -177,7 +177,7 @@ inthandler4:
 
 inthandler5:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -188,7 +188,7 @@ inthandler5:
 
 inthandler6:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -199,7 +199,7 @@ inthandler6:
 
 inthandler7:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -210,7 +210,7 @@ inthandler7:
 
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
index 92d9645..f632fdc 100644 (file)
@@ -1,11 +1,5 @@
 
-#if defined(CONFIG_RAM32MB)
-#define        MEM_END 0x02000000      /* Memory size 32Mb */
-#elif defined(CONFIG_RAM16MB)
-#define        MEM_END 0x01000000      /* Memory size 16Mb */
-#else
 #define        MEM_END 0x00800000      /* Memory size 8Mb */
-#endif
 
 #undef CRT_DEBUG
 
index 252b80b..7f1aeea 100644 (file)
@@ -67,33 +67,6 @@ pclp1:
        beq     pclp1
 #endif /* DEBUG */
 
-#ifdef CONFIG_RELOCATE
-       /* Copy me to RAM */
-       moveal  #__rom_start, %a0
-       moveal  #_stext, %a1
-       moveal  #_edata, %a2
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-       movel   %a0@+, %d0
-       movel   %d0, %a1@+
-       cmpal   %a1, %a2
-       bhi     LD1
-       
-#ifdef DEBUG
-       moveq   #74, %d7                /* 'J' */
-       moveb   %d7,0xfffff907          /* No absolute addresses */
-pclp2:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     pclp2
-#endif /* DEBUG */
-       /* jump into the RAM copy */
-       jmp     ram_jump
-ram_jump:
-
-#endif /* CONFIG_RELOCATE */
-
 #ifdef DEBUG
        moveq   #82, %d7                /* 'R' */
        moveb   %d7,0xfffff907          /* No absolute addresses */
index b91ee85..8658528 100644 (file)
@@ -179,10 +179,8 @@ void __init init_IRQ(void)
        IMR = ~0;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index 6d3460a..c131c6e 100644 (file)
@@ -42,7 +42,7 @@ do_trace:
        movel   #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %sp@(PT_OFF_ORIG_D0),%d1
@@ -56,7 +56,7 @@ do_trace:
 1:     movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
@@ -71,7 +71,12 @@ ENTRY(system_call)
        jbsr    set_esp0
        addql   #4,%sp
 
-       btst    #PF_TRACESYS_BIT,%a2@(TASK_FLAGS+PF_TRACESYS_OFF)
+       movel   %sp@(PT_OFF_ORIG_D0),%d0
+
+       movel   %sp,%d1                 /* get thread_info pointer */
+       andl    #-THREAD_SIZE,%d1
+       movel   %d1,%a2
+       btst    #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
        jne     do_trace
        cmpl    #NR_syscalls,%d0
        jcc     badsys
@@ -124,7 +129,7 @@ Lreturn:
  */
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and.l   #0x3ff, %d0
        lsr.l   #0x02,  %d0
 
index 6f22970..ad96ab1 100644 (file)
@@ -132,10 +132,8 @@ void init_IRQ(void)
        pquicc->intr_cimr = 0x00000000;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index fc5c630..eabaabe 100644 (file)
@@ -90,11 +90,6 @@ static void init_hardware(char *command, int size)
        PDIQEG &= ~PD(1);
        PDIRQEN |= PD(1);                       /* IRQ enabled */
 
-#ifdef CONFIG_68328_SERIAL_UART2
-       /* Enable RXD TXD port bits to enable UART2 */
-       PJSEL &= ~(PJ(5) | PJ(4));
-#endif
-
 #ifdef CONFIG_INIT_LCD
        /* initialize LCD controller */
        LSSA = (long) screen_bits;
index f72a0e5..45f501f 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
@@ -26,6 +26,7 @@ obj-$(CONFIG_M528x)   += pit.o intc-2.o
 obj-$(CONFIG_M5307)    += timers.o intc.o
 obj-$(CONFIG_M532x)    += timers.o intc-simr.o
 obj-$(CONFIG_M5407)    += timers.o intc.o
+obj-$(CONFIG_M548x)    += sltimers.o intc-2.o
 
 obj-y                  += pinmux.o gpio.o
 extra-y := head.o
index cd79d7e..5e92bed 100644 (file)
@@ -88,7 +88,7 @@ ENTRY(system_call)
        movel   %d2,PT_OFF_D0(%sp)      /* on syscall entry */
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %d3,%a0
@@ -96,7 +96,7 @@ ENTRY(system_call)
        movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
index 5598c8b..85daa2b 100644 (file)
@@ -1,5 +1,11 @@
 /*
- * intc-1.c
+ * intc-2.c
+ *
+ * General interrupt controller code for the many ColdFire cores that use
+ * interrupt controllers with 63 interrupt sources, organized as 56 fully-
+ * programmable + 7 fixed-level interrupt sources. This includes the 523x
+ * family, the 5270, 5271, 5274, 5275, and the 528x family which have two such
+ * controllers, and the 547x and 548x families which have only one of them.
  *
  * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
  *
 #include <asm/traps.h>
 
 /*
- *     Each vector needs a unique priority and level asscoiated with it.
+ * Bit definitions for the ICR family of registers.
+ */
+#define MCFSIM_ICR_LEVEL(l)    ((l)<<3)        /* Level l intr */
+#define MCFSIM_ICR_PRI(p)      (p)             /* Priority p intr */
+
+/*
+ *     Each vector needs a unique priority and level associated with it.
  *     We don't really care so much what they are, we don't rely on the
- *     tranditional priority interrupt scheme of the m68k/ColdFire.
+ *     traditional priority interrupt scheme of the m68k/ColdFire.
  */
-static u8 intc_intpri = 0x36;
+static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
+
+#ifdef MCFICM_INTC1
+#define NR_VECS        128
+#else
+#define NR_VECS        64
+#endif
 
 static void intc_irq_mask(unsigned int irq)
 {
-       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
                unsigned long imraddr;
                u32 val, imrbit;
 
                irq -= MCFINT_VECBASE;
                imraddr = MCF_IPSBAR;
+#ifdef MCFICM_INTC1
                imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+               imraddr += MCFICM_INTC0;
+#endif
                imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
                imrbit = 0x1 << (irq & 0x1f);
 
@@ -44,13 +66,17 @@ static void intc_irq_mask(unsigned int irq)
 
 static void intc_irq_unmask(unsigned int irq)
 {
-       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
                unsigned long intaddr, imraddr, icraddr;
                u32 val, imrbit;
 
                irq -= MCFINT_VECBASE;
                intaddr = MCF_IPSBAR;
+#ifdef MCFICM_INTC1
                intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+               intaddr += MCFICM_INTC0;
+#endif
                imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
                icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
                imrbit = 0x1 << (irq & 0x1f);
@@ -67,10 +93,16 @@ static void intc_irq_unmask(unsigned int irq)
        }
 }
 
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+       return 0;
+}
+
 static struct irq_chip intc_irq_chip = {
        .name           = "CF-INTC",
        .mask           = intc_irq_mask,
        .unmask         = intc_irq_unmask,
+       .set_type       = intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
@@ -81,13 +113,14 @@ void __init init_IRQ(void)
 
        /* Mask all interrupt sources */
        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+#ifdef MCFICM_INTC1
        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
+#endif
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index 1b01e79..bb70486 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * intc-simr.c
  *
+ * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts.
+ *
  * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -68,11 +70,9 @@ void __init init_IRQ(void)
                __raw_writeb(0xff, MCFINTC1_SIMR);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index a4560c8..60d2fcb 100644 (file)
@@ -143,11 +143,9 @@ void __init init_IRQ(void)
        mcf_maskimr(0xffffffff);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
diff --git a/arch/m68knommu/platform/coldfire/sltimers.c b/arch/m68knommu/platform/coldfire/sltimers.c
new file mode 100644 (file)
index 0000000..0a1b937
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************/
+
+/*
+ *     sltimers.c -- generic ColdFire slice timer support.
+ *
+ *     Copyright (C) 2009-2010, Philippe De Muyter <phdm@macqel.be>
+ *     based on
+ *     timers.c -- generic ColdFire hardware timer support.
+ *     Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfslt.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+#ifdef CONFIG_HIGHPROFILE
+
+/*
+ *     By default use Slice Timer 1 as the profiler clock timer.
+ */
+#define        PA(a)   (MCF_MBAR + MCFSLT_TIMER1 + (a))
+
+/*
+ *     Choose a reasonably fast profile timer. Make it an odd value to
+ *     try and get good coverage of kernel operations.
+ */
+#define        PROFILEHZ       1013
+
+irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 1 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, PA(MCFSLT_SSR));
+       if (current->pid)
+               profile_tick(CPU_PROFILING);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction mcfslt_profile_irq = {
+       .name    = "profile timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_profile_tick,
+};
+
+void mcfslt_profile_init(void)
+{
+       printk(KERN_INFO "PROFILE: lodging TIMER 1 @ %dHz as profile timer\n",
+              PROFILEHZ);
+
+       setup_irq(MCF_IRQ_PROFILER, &mcfslt_profile_irq);
+
+       /* Set up TIMER 2 as high speed profile clock */
+       __raw_writel(MCF_BUSCLK / PROFILEHZ - 1, PA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               PA(MCFSLT_SCR));
+
+}
+
+#endif /* CONFIG_HIGHPROFILE */
+
+/***************************************************************************/
+
+/*
+ *     By default use Slice Timer 0 as the system clock timer.
+ */
+#define        TA(a)   (MCF_MBAR + MCFSLT_TIMER0 + (a))
+
+static u32 mcfslt_cycles_per_jiffy;
+static u32 mcfslt_cnt;
+
+static irqreturn_t mcfslt_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 0 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
+       mcfslt_cnt += mcfslt_cycles_per_jiffy;
+       return arch_timer_interrupt(irq, dummy);
+}
+
+static struct irqaction mcfslt_timer_irq = {
+       .name    = "timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_tick,
+};
+
+static cycle_t mcfslt_read_clk(struct clocksource *cs)
+{
+       unsigned long flags;
+       u32 cycles;
+       u16 scnt;
+
+       local_irq_save(flags);
+       scnt = __raw_readl(TA(MCFSLT_SCNT));
+       cycles = mcfslt_cnt;
+       local_irq_restore(flags);
+
+       /* substract because slice timers count down */
+       return cycles - scnt;
+}
+
+static struct clocksource mcfslt_clk = {
+       .name   = "slt",
+       .rating = 250,
+       .read   = mcfslt_read_clk,
+       .shift  = 20,
+       .mask   = CLOCKSOURCE_MASK(32),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void hw_timer_init(void)
+{
+       mcfslt_cycles_per_jiffy = MCF_BUSCLK / HZ;
+       /*
+        *      The coldfire slice timer (SLT) runs from STCNT to 0 included,
+        *      then STCNT again and so on.  It counts thus actually
+        *      STCNT + 1 steps for 1 tick, not STCNT.  So if you want
+        *      n cycles, initialize STCNT with n - 1.
+        */
+       __raw_writel(mcfslt_cycles_per_jiffy - 1, TA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               TA(MCFSLT_SCR));
+       /* initialize mcfslt_cnt knowing that slice timers count down */
+       mcfslt_cnt = mcfslt_cycles_per_jiffy;
+
+       setup_irq(MCF_IRQ_TIMER, &mcfslt_timer_irq);
+
+       mcfslt_clk.mult = clocksource_hz2mult(MCF_BUSCLK, mcfslt_clk.shift);
+       clocksource_register(&mcfslt_clk);
+
+#ifdef CONFIG_HIGHPROFILE
+       mcfslt_profile_init();
+#endif
+}
index 692fdfc..dad40fc 100644 (file)
@@ -121,6 +121,23 @@ config CMDLINE_FORCE
          Set this to have arguments from the default kernel command string
          override those passed by the boot loader.
 
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       depends on PROC_FS
+       default y
+       help
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via /proc/<pid>/seccomp, it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
+         If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 menu "Advanced setup"
index e6e5e0d..e66e25c 100644 (file)
@@ -10,7 +10,7 @@ source "lib/Kconfig.debug"
 
 config EARLY_PRINTK
        bool "Early printk function for kernel"
-       depends on SERIAL_UARTLITE_CONSOLE
+       depends on SERIAL_UARTLITE_CONSOLE || SERIAL_8250_CONSOLE
        default n
        help
          This option turns on/off early printk messages to console.
index 592c707..15f1f1d 100644 (file)
@@ -42,11 +42,8 @@ KBUILD_CFLAGS += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
 LDFLAGS                :=
 LDFLAGS_vmlinux        :=
 
-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
 head-y := arch/microblaze/kernel/head.o
 libs-y += arch/microblaze/lib/
-libs-y += $(LIBGCC)
 core-y += arch/microblaze/kernel/
 core-y += arch/microblaze/mm/
 core-y += arch/microblaze/platform/
@@ -72,12 +69,16 @@ export MMU DTB
 
 all: linux.bin
 
-BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.%
+# With make 3.82 we cannot mix normal and wildcard targets
+BOOT_TARGETS1 = linux.bin linux.bin.gz
+BOOT_TARGETS2 = simpleImage.%
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-$(BOOT_TARGETS): vmlinux
+$(BOOT_TARGETS1): vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+$(BOOT_TARGETS2): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
index ce9c587..3190276 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _ASM_MICROBLAZE_BYTEORDER_H
 #define _ASM_MICROBLAZE_BYTEORDER_H
 
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* _ASM_MICROBLAZE_BYTEORDER_H */
index 128bf03..0185cbe 100644 (file)
@@ -24,8 +24,13 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
                "addc %0, %0, %3\n\t"
                "addc %0, %0, r0\n\t"
                : "+&d" (sum)
-               : "d" (saddr), "d" (daddr), "d" (len + proto));
-
+               : "d" (saddr), "d" (daddr),
+#ifdef __MICROBLAZEEL__
+       "d" ((len + proto) << 8)
+#else
+       "d" (len + proto)
+#endif
+);
        return sum;
 }
 
index b4f5ca3..cd25753 100644 (file)
@@ -38,6 +38,7 @@ struct cpuinfo {
        u32 use_exc;
        u32 ver_code;
        u32 mmu;
+       u32 endian;
 
        /* CPU caches */
        u32 use_icache;
@@ -76,7 +77,6 @@ struct cpuinfo {
        u32 num_rd_brk;
        u32 num_wr_brk;
        u32 cpu_clock_freq; /* store real freq of cpu */
-       u32 freq_div_hz; /* store freq/HZ */
 
        /* FPGA family */
        u32 fpga_family_code;
@@ -97,7 +97,8 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
        int *val;
-       return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0;
+       return (val = (int *) of_get_property(cpu, n, NULL)) ?
+                                                       be32_to_cpup(val) : 0;
 }
 
 #endif /* _ASM_MICROBLAZE_CPUINFO_H */
index 732caf1..098dfdd 100644 (file)
@@ -71,7 +71,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
-#ifdef __LITTLE_ENDIAN__
+#ifdef __MICROBLAZEEL__
 #define ELF_DATA       ELFDATA2LSB
 #else
 #define ELF_DATA       ELFDATA2MSB
index 2345ac3..2b2c18b 100644 (file)
@@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio)
        return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-       return -ENOSYS;
+       return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
index 00b5398..eae3222 100644 (file)
@@ -243,6 +243,8 @@ static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size,
 #define out_8(a, v) __raw_writeb((v), (a))
 #define in_8(a) __raw_readb(a)
 
+#define mmiowb()
+
 #define ioport_map(port, nr)   ((void __iomem *)(port))
 #define ioport_unmap(addr)
 
index cf377d9..ed9d0f6 100644 (file)
@@ -205,9 +205,6 @@ extern int page_is_ram(unsigned long pfn);
 #define TOPHYS(addr)  __virt_to_phys(addr)
 
 #ifdef CONFIG_MMU
-#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
-#define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */
-#endif
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
index 5a388ee..2232ff9 100644 (file)
@@ -165,5 +165,7 @@ extern void __init xilinx_pci_init(void);
 static inline void __init xilinx_pci_init(void) { return; }
 #endif
 
+#include <asm-generic/pci-dma-compat.h>
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_MICROBLAZE_PCI_H */
index c614a89..ebd3579 100644 (file)
@@ -165,7 +165,8 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
 
 #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte))
 
-#define pmd_populate(mm, pmd, pte)     (pmd_val(*(pmd)) = page_address(pte))
+#define pmd_populate(mm, pmd, pte) \
+                       (pmd_val(*(pmd)) = (unsigned long)page_address(pte))
 
 #define pmd_populate_kernel(mm, pmd, pte) \
                (pmd_val(*(pmd)) = (unsigned long) (pte))
index ca2d928..d4f4216 100644 (file)
@@ -57,6 +57,13 @@ static inline int pte_file(pte_t pte) { return 0; }
 
 #define pgprot_noncached_wc(prot)      prot
 
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define        VMALLOC_START   0
+#define        VMALLOC_END     0xffffffff
+
 #else /* CONFIG_MMU */
 
 #include <asm-generic/4level-fixup.h>
index 101fa09..bdc3831 100644 (file)
@@ -27,6 +27,7 @@
 
 /* Other Prototypes */
 extern int early_uartlite_console(void);
+extern int early_uart16550_console(void);
 
 #ifdef CONFIG_PCI
 /*
index 9578666..37db96a 100644 (file)
@@ -30,7 +30,9 @@ struct pvr_s {
 #define PVR0_USE_EXC_MASK              0x04000000
 #define PVR0_USE_ICACHE_MASK           0x02000000
 #define PVR0_USE_DCACHE_MASK           0x01000000
-#define PVR0_USE_MMU                   0x00800000      /* new */
+#define PVR0_USE_MMU                   0x00800000
+#define PVR0_USE_BTC                   0x00400000
+#define PVR0_ENDI                      0x00200000
 #define PVR0_VERSION_MASK              0x0000FF00
 #define PVR0_USER1_MASK                        0x000000FF
 
@@ -38,9 +40,9 @@ struct pvr_s {
 #define PVR1_USER2_MASK                        0xFFFFFFFF
 
 /* Configuration PVR masks */
-#define PVR2_D_OPB_MASK                        0x80000000
+#define PVR2_D_OPB_MASK                        0x80000000 /* or AXI */
 #define PVR2_D_LMB_MASK                        0x40000000
-#define PVR2_I_OPB_MASK                        0x20000000
+#define PVR2_I_OPB_MASK                        0x20000000 /* or AXI */
 #define PVR2_I_LMB_MASK                        0x10000000
 #define PVR2_INTERRUPT_IS_EDGE_MASK    0x08000000
 #define PVR2_EDGE_IS_POSITIVE_MASK     0x04000000
@@ -63,8 +65,8 @@ struct pvr_s {
 #define PVR2_OPCODE_0x0_ILL_MASK       0x00000040
 #define PVR2_UNALIGNED_EXC_MASK                0x00000020
 #define PVR2_ILL_OPCODE_EXC_MASK       0x00000010
-#define PVR2_IOPB_BUS_EXC_MASK         0x00000008
-#define PVR2_DOPB_BUS_EXC_MASK         0x00000004
+#define PVR2_IOPB_BUS_EXC_MASK         0x00000008 /* or AXI */
+#define PVR2_DOPB_BUS_EXC_MASK         0x00000004 /* or AXI */
 #define PVR2_DIV_ZERO_EXC_MASK         0x00000002
 #define PVR2_FPU_EXC_MASK              0x00000001
 
@@ -208,6 +210,8 @@ struct pvr_s {
 #define PVR_MMU_TLB_ACCESS(pvr)        (pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(pvr)     (pvr.pvr[11] & PVR11_MMU_ZONES)
 
+/* endian */
+#define PVR_ENDIAN(pvr)        (pvr.pvr[0] & PVR0_ENDI)
 
 int cpu_has_pvr(void);
 void get_pvr(struct pvr_s *pvr);
diff --git a/arch/microblaze/include/asm/seccomp.h b/arch/microblaze/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..0d91275
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_MICROBLAZE_SECCOMP_H
+#define _ASM_MICROBLAZE_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read              __NR_read
+#define __NR_seccomp_write             __NR_write
+#define __NR_seccomp_exit              __NR_exit
+#define __NR_seccomp_sigreturn         __NR_sigreturn
+
+#define __NR_seccomp_read_32           __NR_read
+#define __NR_seccomp_write_32          __NR_write
+#define __NR_seccomp_exit_32           __NR_exit
+#define __NR_seccomp_sigreturn_32      __NR_sigreturn
+
+#endif /* _ASM_MICROBLAZE_SECCOMP_H */
index 782b5c8..8f39689 100644 (file)
@@ -25,6 +25,12 @@ void early_printk(const char *fmt, ...);
 int setup_early_printk(char *opt);
 void disable_early_printk(void);
 
+#if defined(CONFIG_EARLY_PRINTK)
+#define eprintk early_printk
+#else
+#define eprintk printk
+#endif
+
 void heartbeat(void);
 void setup_heartbeat(void);
 
index 8a8e9fc..b73da2a 100644 (file)
@@ -127,23 +127,19 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_FREEZE             14      /* Freezing for suspend */
 
-/* FIXME change in entry.S */
-#define TIF_KERNEL_TRACE       8       /* kernel trace active */
-
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_POLLING_NRFLAG     16
 
-#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_IRET              (1<<TIF_IRET)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE            (1<<TIF_FREEZE)
+#define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
+#define _TIF_IRET              (1 << TIF_IRET)
+#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE            (1 << TIF_FREEZE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
-#define _TIF_KERNEL_TRACE      (1 << TIF_KERNEL_TRACE)
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK  (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
index 3658d91..2b97cbe 100644 (file)
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/be_byteshift.h>
 # include <linux/unaligned/le_byteshift.h>
 # include <linux/unaligned/generic.h>
 
-# define get_unaligned __get_unaligned_be
-# define put_unaligned __put_unaligned_be
+
+#  ifdef __MICROBLAZEEL__
+#   define get_unaligned       __get_unaligned_le
+#   define put_unaligned       __put_unaligned_le
+#  else
+#   define get_unaligned       __get_unaligned_be
+#   define put_unaligned       __put_unaligned_be
+#  endif
 
 # endif        /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNALIGNED_H */
index 2b67e92..d770b00 100644 (file)
 #define __NR_rt_tgsigqueueinfo 365 /* new */
 #define __NR_perf_event_open   366 /* new */
 #define __NR_recvmmsg          367 /* new */
+#define __NR_fanotify_init     368
+#define __NR_fanotify_mark     369
+#define __NR_prlimit64         370
 
-#define __NR_syscalls          368
+#define __NR_syscalls          371
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
index f72dbd6..f70a604 100644 (file)
@@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(pvr_user2, USER2);
 
        CI(mmu, USE_MMU);
+       CI(endian, ENDIAN);
 
        CI(use_icache, USE_ICACHE);
        CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
index 6095aa6..b16b994 100644 (file)
@@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
        ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+       ci->endian = fcpu(cpu, "xlnx,endianness");
 
        ci->ver_code = 0;
        ci->fpga_family_code = 0;
index 255ef88..87c79fa 100644 (file)
@@ -30,6 +30,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
        {"7.20.c", 0x0e},
        {"7.20.d", 0x0f},
        {"7.30.a", 0x10},
+       {"7.30.b", 0x11},
+       {"8.00.a", 0x12},
        {NULL, 0},
 };
 
index 7086e35..b4048af 100644 (file)
@@ -51,11 +51,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        count = seq_printf(m,
                        "CPU-Family:    MicroBlaze\n"
                        "FPGA-Arch:     %s\n"
-                       "CPU-Ver:       %s\n"
+                       "CPU-Ver:       %s, %s endian\n"
                        "CPU-MHz:       %d.%02d\n"
                        "BogoMips:      %lu.%02lu\n",
                        fpga_family,
                        cpu_ver,
+                       cpuinfo.endian ? "little" : "big",
                        cpuinfo.cpu_clock_freq /
                        1000000,
                        cpuinfo.cpu_clock_freq %
index 9bee938..e01afa6 100644 (file)
@@ -27,7 +27,7 @@
        register unsigned tmp __asm__("r3");                    \
        tmp = 0x0;      /* Prevent warning about unused */      \
        __asm__ __volatile__ (                                  \
-                       ".byte 0x94,0x60,0xa0, " #pvrid "\n\t"  \
+                       "mfs    %0, rpvr" #pvrid ";"    \
                        : "=r" (tmp) : : "memory");             \
        val = tmp;                                              \
 }
index 7de8492..c3616a0 100644 (file)
@@ -24,7 +24,8 @@
 static u32 early_console_initialized;
 static u32 base_addr;
 
-static void early_printk_putc(char c)
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+static void early_printk_uartlite_putc(char c)
 {
        /*
         * Limit how many times we'll spin waiting for TX FIFO status.
@@ -45,25 +46,70 @@ static void early_printk_putc(char c)
                out_be32(base_addr + 4, c & 0xff);
 }
 
-static void early_printk_write(struct console *unused,
+static void early_printk_uartlite_write(struct console *unused,
                                        const char *s, unsigned n)
 {
        while (*s && n-- > 0) {
-               early_printk_putc(*s);
+               early_printk_uartlite_putc(*s);
                if (*s == '\n')
-                       early_printk_putc('\r');
+                       early_printk_uartlite_putc('\r');
                s++;
        }
 }
 
-static struct console early_serial_console = {
+static struct console early_serial_uartlite_console = {
        .name = "earlyser",
-       .write = early_printk_write,
+       .write = early_printk_uartlite_write,
        .flags = CON_PRINTBUFFER,
        .index = -1,
 };
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
 
-static struct console *early_console = &early_serial_console;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void early_printk_uart16550_putc(char c)
+{
+       /*
+        * Limit how many times we'll spin waiting for TX FIFO status.
+        * This will prevent lockups if the base address is incorrectly
+        * set, or any other issue on the UARTLITE.
+        * This limit is pretty arbitrary, unless we are at about 10 baud
+        * we'll never timeout on a working UART.
+        */
+
+       #define UART_LSR_TEMT   0x40 /* Transmitter empty */
+       #define UART_LSR_THRE   0x20 /* Transmit-hold-register empty */
+       #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+       unsigned retries = 10000;
+
+       while (--retries &&
+               !((in_be32(base_addr + 0x14) & BOTH_EMPTY) == BOTH_EMPTY))
+               ;
+
+       if (retries)
+               out_be32(base_addr, c & 0xff);
+}
+
+static void early_printk_uart16550_write(struct console *unused,
+                                       const char *s, unsigned n)
+{
+       while (*s && n-- > 0) {
+               early_printk_uart16550_putc(*s);
+               if (*s == '\n')
+                       early_printk_uart16550_putc('\r');
+               s++;
+       }
+}
+
+static struct console early_serial_uart16550_console = {
+       .name = "earlyser",
+       .write = early_printk_uart16550_write,
+       .flags = CON_PRINTBUFFER,
+       .index = -1,
+};
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+static struct console *early_console;
 
 void early_printk(const char *fmt, ...)
 {
@@ -84,20 +130,43 @@ int __init setup_early_printk(char *opt)
        if (early_console_initialized)
                return 1;
 
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
        base_addr = early_uartlite_console();
        if (base_addr) {
                early_console_initialized = 1;
 #ifdef CONFIG_MMU
                early_console_reg_tlb_alloc(base_addr);
 #endif
+               early_console = &early_serial_uartlite_console;
                early_printk("early_printk_console is enabled at 0x%08x\n",
                                                        base_addr);
 
                /* register_console(early_console); */
 
                return 0;
-       } else
-               return 1;
+       }
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       base_addr = early_uart16550_console();
+       base_addr &= ~3; /* clear register offset */
+       if (base_addr) {
+               early_console_initialized = 1;
+#ifdef CONFIG_MMU
+               early_console_reg_tlb_alloc(base_addr);
+#endif
+               early_console = &early_serial_uart16550_console;
+
+               early_printk("early_printk_console is enabled at 0x%08x\n",
+                                                       base_addr);
+
+               /* register_console(early_console); */
+
+               return 0;
+       }
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+       return 1;
 }
 
 void __init disable_early_printk(void)
index 304882e..819238b 100644 (file)
        swi     r13, r1, PTO+PT_R13;    /* Save SDA2 */                 \
        swi     r14, r1, PTO+PT_PC;     /* PC, before IRQ/trap */       \
        swi     r15, r1, PTO+PT_R15;    /* Save LP */                   \
+       swi     r16, r1, PTO+PT_R16;                                    \
+       swi     r17, r1, PTO+PT_R17;                                    \
        swi     r18, r1, PTO+PT_R18;    /* Save asm scratch reg */      \
        swi     r19, r1, PTO+PT_R19;                                    \
        swi     r20, r1, PTO+PT_R20;                                    \
        lwi     r13, r1, PTO+PT_R13;    /* restore SDA2 */              \
        lwi     r14, r1, PTO+PT_PC;     /* RESTORE_LINK PC, before IRQ/trap */\
        lwi     r15, r1, PTO+PT_R15;    /* restore LP */                \
+       lwi     r16, r1, PTO+PT_R16;                                    \
+       lwi     r17, r1, PTO+PT_R17;                                    \
        lwi     r18, r1, PTO+PT_R18;    /* restore asm scratch reg */   \
        lwi     r19, r1, PTO+PT_R19;                                    \
        lwi     r20, r1, PTO+PT_R20;                                    \
@@ -295,6 +299,8 @@ C_ENTRY(_user_exception):
        /* addik        r1, r1, -STATE_SAVE_SIZE; */
        addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
        SAVE_REGS
+       swi     r0, r1, PTO + PT_R3
+       swi     r0, r1, PTO + PT_R4
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1;             /* Store user SP.  */
@@ -458,14 +464,8 @@ C_ENTRY(sys_execve):
        addik   r8, r1, PTO;            /* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
-       swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       swi     r4, r1, PTO+PT_R4;
-       brlid   r15, sys_rt_sigreturn   /* Do real work */
+       brid    sys_rt_sigreturn        /* Do real work */
        addik   r5, r1, PTO;            /* add user context as 1st arg */
-       lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       lwi     r4, r1, PTO+PT_R4;
-       bri ret_from_trap /* fall through will not work here due to align */
-       nop;
 
 /*
  * HW EXCEPTION rutine start
@@ -765,9 +765,7 @@ C_ENTRY(_debug_exception):
        /* save all regs to pt_reg structure */
        swi     r0, r1, PTO+PT_R0;      /* R0 must be saved too */
        swi     r14, r1, PTO+PT_R14     /* rewrite saved R14 value */
-       swi     r16, r1, PTO+PT_R16
        swi     r16, r1, PTO+PT_PC; /* PC and r16 are the same */
-       swi     r17, r1, PTO+PT_R17
        /* save special purpose registers to pt_regs */
        mfs     r11, rear;
        swi     r11, r1, PTO+PT_EAR;
@@ -801,8 +799,6 @@ C_ENTRY(_debug_exception):
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
        SAVE_REGS;
-       swi     r17, r1, PTO+PT_R17;
-       swi     r16, r1, PTO+PT_R16;
        swi     r16, r1, PTO+PT_PC;     /* Save LP */
        swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
@@ -848,8 +844,6 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
        tophys(r1,r1);
        /* MS: Restore all regs */
        RESTORE_REGS
-       lwi     r17, r1, PTO+PT_R17;
-       lwi     r16, r1, PTO+PT_R16;
        addik   r1, r1, STATE_SAVE_SIZE  /* Clean up stack space */
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
@@ -863,7 +857,6 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging */
        RESTORE_REGS
        lwi     r14, r1, PTO+PT_R14;
        lwi     r16, r1, PTO+PT_PC;
-       lwi     r17, r1, PTO+PT_R17;
        addik   r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
        tovirt(r1,r1);
 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
index b98ee8d..478f294 100644 (file)
@@ -72,7 +72,6 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                                                        int fsr, int addr)
 {
 #ifdef CONFIG_MMU
-       int code;
        addr = regs->pc;
 #endif
 
@@ -86,8 +85,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
        switch (type & 0x1F) {
        case MICROBLAZE_ILL_OPCODE_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Illegal opcode exception " \
-                                                       "in user mode.\n");
+                       pr_debug("Illegal opcode exception in user mode\n");
                        _exception(SIGILL, regs, ILL_ILLOPC, addr);
                        return;
                }
@@ -97,8 +95,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_IBUS_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Instruction bus error " \
-                                               "exception in user mode.\n");
+                       pr_debug("Instruction bus error exception in user mode\n");
                        _exception(SIGBUS, regs, BUS_ADRERR, addr);
                        return;
                }
@@ -108,8 +105,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_DBUS_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Data bus error exception " \
-                                                       "in user mode.\n");
+                       pr_debug("Data bus error exception in user mode\n");
                        _exception(SIGBUS, regs, BUS_ADRERR, addr);
                        return;
                }
@@ -119,8 +115,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_DIV_ZERO_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Divide by zero exception " \
-                                                       "in user mode\n");
+                       pr_debug("Divide by zero exception in user mode\n");
                        _exception(SIGILL, regs, FPE_INTDIV, addr);
                        return;
                }
@@ -129,7 +124,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                die("Divide by zero exception", regs, SIGBUS);
                break;
        case MICROBLAZE_FPU_EXCEPTION:
-               pr_debug(KERN_WARNING "FPU exception\n");
+               pr_debug("FPU exception\n");
                /* IEEE FP exception */
                /* I removed fsr variable and use code var for storing fsr */
                if (fsr & FSR_IO)
@@ -147,14 +142,8 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
 
 #ifdef CONFIG_MMU
        case MICROBLAZE_PRIVILEGED_EXCEPTION:
-               pr_debug(KERN_WARNING "Privileged exception\n");
-               /* "brk r0,r0" - used as debug breakpoint - old toolchain */
-               if (get_user(code, (unsigned long *)regs->pc) == 0
-                       && code == 0x980c0000) {
-                       _exception(SIGTRAP, regs, TRAP_BRKPT, addr);
-               } else {
-                       _exception(SIGILL, regs, ILL_PRVOPC, addr);
-               }
+               pr_debug("Privileged exception\n");
+               _exception(SIGILL, regs, ILL_PRVOPC, addr);
                break;
 #endif
        default:
index 5227517..154756f 100644 (file)
@@ -47,11 +47,10 @@ void setup_heartbeat(void)
        struct device_node *gpio = NULL;
        int *prop;
        int j;
-       char *gpio_list[] = {
-                               "xlnx,xps-gpio-1.00.a",
-                               "xlnx,opb-gpio-1.00.a",
-                               NULL
-                       };
+       const char * const gpio_list[] = {
+               "xlnx,xps-gpio-1.00.a",
+               NULL
+       };
 
        for (j = 0; gpio_list[j] != NULL; j++) {
                gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]);
@@ -60,7 +59,7 @@ void setup_heartbeat(void)
        }
 
        if (gpio) {
-               base_addr = *(int *) of_get_property(gpio, "reg", NULL);
+               base_addr = be32_to_cpup(of_get_property(gpio, "reg", NULL));
                base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
                printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
 
index 03172c1..d61ea33 100644 (file)
@@ -126,11 +126,8 @@ void __init init_IRQ(void)
                                0
                        };
 #endif
-       static char *intc_list[] = {
+       const char * const intc_list[] = {
                                "xlnx,xps-intc-1.00.a",
-                               "xlnx,opb-intc-1.00.c",
-                               "xlnx,opb-intc-1.00.b",
-                               "xlnx,opb-intc-1.00.a",
                                NULL
                        };
 
@@ -141,12 +138,15 @@ void __init init_IRQ(void)
        }
        BUG_ON(!intc);
 
-       intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
+       intc_baseaddr = be32_to_cpup(of_get_property(intc,
+                                                               "reg", NULL));
        intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
-       nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL);
+       nr_irq = be32_to_cpup(of_get_property(intc,
+                                               "xlnx,num-intr-inputs", NULL));
 
        intr_type =
-               *(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL);
+               be32_to_cpup(of_get_property(intc,
+                                               "xlnx,kind-of-intr", NULL));
        if (intr_type >= (1 << (nr_irq + 1)))
                printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
index bfc006b..09a5e82 100644 (file)
@@ -80,7 +80,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 void microblaze_kgdb_break(struct pt_regs *regs)
 {
        if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
-               return 0;
+               return;
 
        /* Jump over the first arch_kgdb_breakpoint which is barrier to
         * get kgdb work. The same solution is used for powerpc */
@@ -114,7 +114,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
 {
        char *ptr;
        unsigned long address;
-       int cpu = smp_processor_id();
 
        switch (remcom_in_buffer[0]) {
        case 'c':
@@ -143,5 +142,9 @@ void kgdb_arch_exit(void)
  * Global data
  */
 struct kgdb_arch arch_kgdb_ops = {
+#ifdef __MICROBLAZEEL__
+       .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */
+#else
        .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
+#endif
 };
index ff85f77..5cb0341 100644 (file)
 #include <linux/syscalls.h>
 
 #include <asm/checksum.h>
+#include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
-/*
- * libgcc functions - functions that are used internally by the
- * compiler... (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3(void);
-EXPORT_SYMBOL(__ashldi3);
-extern void __ashrdi3(void);
-EXPORT_SYMBOL(__ashrdi3);
-extern void __divsi3(void);
-EXPORT_SYMBOL(__divsi3);
-extern void __lshrdi3(void);
-EXPORT_SYMBOL(__lshrdi3);
-extern void __modsi3(void);
-EXPORT_SYMBOL(__modsi3);
-extern void __mulsi3(void);
-EXPORT_SYMBOL(__mulsi3);
-extern void __muldi3(void);
-EXPORT_SYMBOL(__muldi3);
-extern void __ucmpdi2(void);
-EXPORT_SYMBOL(__ucmpdi2);
-extern void __udivsi3(void);
-EXPORT_SYMBOL(__udivsi3);
-extern void __umodsi3(void);
-EXPORT_SYMBOL(__umodsi3);
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
 #ifdef CONFIG_FUNCTION_TRACER
@@ -63,3 +39,9 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 #endif
+
+#ifdef CONFIG_MMU
+EXPORT_SYMBOL(empty_zero_page);
+#endif
+
+EXPORT_SYMBOL(mbc);
index 427b13b..a105301 100644 (file)
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 
-void __init early_init_dt_scan_chosen_arch(unsigned long node)
-{
-       /* No Microblaze specific code here */
-}
-
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
        memblock_add(base, size);
@@ -77,11 +72,12 @@ static int __init early_init_dt_scan_serial(unsigned long node,
 /* find compatible node with uartlite */
        p = of_get_flat_dt_prop(node, "compatible", &l);
        if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0))
+                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
+                       (strncmp(p, "xlnx,axi-uartlite", 17) != 0))
                return 0;
 
        addr = of_get_flat_dt_prop(node, "reg", &l);
-       return *addr; /* return address */
+       return be32_to_cpup(addr); /* return address */
 }
 
 /* this function is looking for early uartlite console - Microblaze specific */
@@ -89,6 +85,40 @@ int __init early_uartlite_console(void)
 {
        return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
 }
+
+/* MS this is Microblaze specifig function */
+static int __init early_init_dt_scan_serial_full(unsigned long node,
+                               const char *uname, int depth, void *data)
+{
+       unsigned long l;
+       char *p;
+       unsigned int addr;
+
+       pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+/* find all serial nodes */
+       if (strncmp(uname, "serial", 6) != 0)
+               return 0;
+
+       early_init_dt_check_for_initrd(node);
+
+/* find compatible node with uartlite */
+       p = of_get_flat_dt_prop(node, "compatible", &l);
+
+       if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
+               (strncmp(p, "xlnx,axi-uart16550", 18) != 0))
+               return 0;
+
+       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+       addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
+       return be32_to_cpu(addr); /* return address */
+}
+
+/* this function is looking for early uartlite console - Microblaze specific */
+int __init early_uart16550_console(void)
+{
+       return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+}
 #endif
 
 void __init early_init_devtree(void *params)
index f5f7688..bb1558e 100644 (file)
@@ -92,12 +92,6 @@ inline unsigned get_romfs_len(unsigned *addr)
 }
 #endif /* CONFIG_MTD_UCLINUX_EBSS */
 
-#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
-#define eprintk early_printk
-#else
-#define eprintk printk
-#endif
-
 void __init machine_early_init(const char *cmdline, unsigned int ram,
                unsigned int fdt, unsigned int msr)
 {
index 03376dc..e88a930 100644 (file)
@@ -372,3 +372,6 @@ ENTRY(sys_call_table)
        .long sys_rt_tgsigqueueinfo     /* 365 */
        .long sys_perf_event_open
        .long sys_recvmmsg
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64     /* 370 */
index b1380ae..a5aa33d 100644 (file)
@@ -38,6 +38,9 @@ static unsigned int timer_baseaddr;
 #define TIMER_BASE     timer_baseaddr
 #endif
 
+unsigned int freq_div_hz;
+unsigned int timer_clock_freq;
+
 #define TCSR0  (0x00)
 #define TLR0   (0x04)
 #define TCR0   (0x08)
@@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
                printk(KERN_INFO "%s: periodic\n", __func__);
-               microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
+               microblaze_timer0_start_periodic(freq_div_hz);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                printk(KERN_INFO "%s: oneshot\n", __func__);
@@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = {
 static __init void microblaze_clockevent_init(void)
 {
        clockevent_microblaze_timer.mult =
-               div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+               div_sc(timer_clock_freq, NSEC_PER_SEC,
                                clockevent_microblaze_timer.shift);
        clockevent_microblaze_timer.max_delta_ns =
                clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
@@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = {
 
 int __init init_microblaze_timecounter(void)
 {
-       microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+       microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
                                microblaze_cc.shift);
 
        timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
@@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = {
 static int __init microblaze_clocksource_init(void)
 {
        clocksource_microblaze.mult =
-                       clocksource_hz2mult(cpuinfo.cpu_clock_freq,
+                       clocksource_hz2mult(timer_clock_freq,
                                                clocksource_microblaze.shift);
        if (clocksource_register(&clocksource_microblaze))
                panic("failed to register clocksource");
@@ -247,6 +250,7 @@ void __init time_init(void)
        u32 irq, i = 0;
        u32 timer_num = 1;
        struct device_node *timer = NULL;
+       const void *prop;
 #ifdef CONFIG_SELFMOD_TIMER
        unsigned int timer_baseaddr = 0;
        int arr_func[] = {
@@ -258,12 +262,10 @@ void __init time_init(void)
                                0
                        };
 #endif
-       char *timer_list[] = {
-                               "xlnx,xps-timer-1.00.a",
-                               "xlnx,opb-timer-1.00.b",
-                               "xlnx,opb-timer-1.00.a",
-                               NULL
-                       };
+       const char * const timer_list[] = {
+               "xlnx,xps-timer-1.00.a",
+               NULL
+       };
 
        for (i = 0; timer_list[i] != NULL; i++) {
                timer = of_find_compatible_node(NULL, NULL, timer_list[i]);
@@ -272,13 +274,13 @@ void __init time_init(void)
        }
        BUG_ON(!timer);
 
-       timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
+       timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
        timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
-       irq = *(int *) of_get_property(timer, "interrupts", NULL);
-       timer_num =
-               *(int *) of_get_property(timer, "xlnx,one-timer-only", NULL);
+       irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL));
+       timer_num = be32_to_cpup(of_get_property(timer,
+                                               "xlnx,one-timer-only", NULL));
        if (timer_num) {
-               printk(KERN_EMERG "Please enable two timers in HW\n");
+               eprintk(KERN_EMERG "Please enable two timers in HW\n");
                BUG();
        }
 
@@ -288,7 +290,14 @@ void __init time_init(void)
        printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
                timer_list[i], timer_baseaddr, irq);
 
-       cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+       /* If there is clock-frequency property than use it */
+       prop = of_get_property(timer, "clock-frequency", NULL);
+       if (prop)
+               timer_clock_freq = be32_to_cpup(prop);
+       else
+               timer_clock_freq = cpuinfo.cpu_clock_freq;
+
+       freq_div_hz = timer_clock_freq / HZ;
 
        setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT
index a09f296..96a88c3 100644 (file)
@@ -8,7 +8,6 @@
  * for more details.
  */
 
-OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze")
 OUTPUT_ARCH(microblaze)
 ENTRY(microblaze_start)
 
@@ -16,7 +15,11 @@ ENTRY(microblaze_start)
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 
+#ifdef __MICROBLAZEEL__
+jiffies = jiffies_64;
+#else
 jiffies = jiffies_64 + 4;
+#endif
 
 SECTIONS {
        . = CONFIG_KERNEL_START;
index 4dfe47d..f1fcbff 100644 (file)
@@ -11,3 +11,13 @@ lib-y += memcpy.o memmove.o
 endif
 
 lib-y += uaccess_old.o
+
+lib-y += ashldi3.o
+lib-y += ashrdi3.o
+lib-y += divsi3.o
+lib-y += lshrdi3.o
+lib-y += modsi3.o
+lib-y += muldi3.o
+lib-y += mulsi3.o
+lib-y += udivsi3.o
+lib-y += umodsi3.o
diff --git a/arch/microblaze/lib/ashldi3.c b/arch/microblaze/lib/ashldi3.c
new file mode 100644 (file)
index 0000000..beb80f3
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (unsigned int) uu.s.low << -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+               w.s.low = (unsigned int) uu.s.low << b;
+               w.s.high = ((unsigned int) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/microblaze/lib/ashrdi3.c b/arch/microblaze/lib/ashrdi3.c
new file mode 100644 (file)
index 0000000..c884a91
--- /dev/null
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high =
+                   uu.s.high >> 31;
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/microblaze/lib/divsi3.S b/arch/microblaze/lib/divsi3.S
new file mode 100644 (file)
index 0000000..595b02d
--- /dev/null
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* Divide operation for 32 bit integers.
+*      Input : Dividend in Reg r5
+*              Divisor in Reg r6
+*      Output: Result in Reg r3
+*/
+       .text
+       .globl  __divsi3
+       .type __divsi3, @function
+       .ent __divsi3
+__divsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -16
+       swi     r28, r1, 0
+       swi     r29, r1, 4
+       swi     r30, r1, 8
+       swi     r31, r1, 12
+
+       beqi    r6, div_by_zero /* div_by_zero - division error */
+       beqi    r5, result_is_zero /* result is zero */
+       bgeid   r5, r5_pos
+       xor     r28, r5, r6 /* get the sign of the result */
+       rsubi   r5, r5, 0 /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0 /* make r6 positive */
+r6_pos:
+       addik   r30, r0, 0 /* clear mod */
+       addik   r3, r0, 0 /* clear div */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+       /* first part try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2 /* this traps r5 == 0x80000000 */
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgtid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r30, r30, r30 /* move that bit into the mod register */
+       rsub    r31, r6, r30 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r30, r0, r31
+       addik   r3, r3, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r3, r3, r3 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bgei    r28, return_here
+       brid    return_here
+       rsubi   r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r28, r1, 0
+       lwi     r29, r1, 4
+       lwi     r30, r1, 8
+       lwi     r31, r1, 12
+       rtsd    r15, 8
+       addik   r1, r1, 16
+
+.size __divsi3, . - __divsi3
+.end __divsi3
diff --git a/arch/microblaze/lib/libgcc.h b/arch/microblaze/lib/libgcc.h
new file mode 100644 (file)
index 0000000..05909d5
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+       int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+       int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union {
+       struct DWstruct s;
+       long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/microblaze/lib/lshrdi3.c b/arch/microblaze/lib/lshrdi3.c
new file mode 100644 (file)
index 0000000..dcf8d68
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (unsigned int) uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = (unsigned int) uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
index 014bac9..cc495d7 100644 (file)
 #include <asm/system.h>
 
 #ifdef __HAVE_ARCH_MEMCPY
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
 {
        const char *src = v_src;
        char *dst = v_dst;
-#ifndef CONFIG_OPT_LIB_FUNCTION
+
        /* Simple, byte oriented memcpy. */
        while (c--)
                *dst++ = *src++;
 
        return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+       const char *src = v_src;
+       char *dst = v_dst;
+
        /* The following code tries to optimize the copy by using unsigned
         * alignment. This will work fine if both source and destination are
         * aligned on the same boundary. However, if they are aligned on
@@ -86,7 +93,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x1:       /* Unaligned - Off by 1 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 8;
 
@@ -95,7 +102,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 24;
                                buf_hold = value << 8;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFFFFFF00) >>8;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFF) << 24);
+                               buf_hold = (value & 0xFFFFFF00) >>8;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 3;
@@ -103,7 +119,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x2:       /* Unaligned - Off by 2 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 16;
 
@@ -112,7 +128,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 16;
                                buf_hold = value << 16;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFFFF0000 )>>16;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFFFF)<<16);
+                               buf_hold = (value & 0xFFFF0000) >>16;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 2;
@@ -120,7 +145,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x3:       /* Unaligned - Off by 3 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 24;
 
@@ -129,7 +154,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 8;
                                buf_hold = value << 24;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFF000000) >> 24;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8);
+                               buf_hold = (value & 0xFF000000) >> 24;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 1;
@@ -150,7 +184,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
        }
 
        return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memcpy);
 #endif /* __HAVE_ARCH_MEMCPY */
index 0929198..123e361 100644 (file)
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMMOVE
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 {
        const char *src = v_src;
        char *dst = v_dst;
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
-       const uint32_t *i_src;
-       uint32_t *i_dst;
-#endif
-
        if (!c)
                return v_dst;
 
@@ -48,7 +44,6 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
        if (v_dst <= v_src)
                return memcpy(v_dst, v_src, c);
 
-#ifndef CONFIG_OPT_LIB_FUNCTION
        /* copy backwards, from end to beginning */
        src += c;
        dst += c;
@@ -58,7 +53,22 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                *--dst = *--src;
 
        return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+       const char *src = v_src;
+       char *dst = v_dst;
+       const uint32_t *i_src;
+       uint32_t *i_dst;
+
+       if (!c)
+               return v_dst;
+
+       /* Use memcpy when source is higher than dest */
+       if (v_dst <= v_src)
+               return memcpy(v_dst, v_src, c);
+
        /* The following code tries to optimize the copy by using unsigned
         * alignment. This will work fine if both source and destination are
         * aligned on the same boundary. However, if they are aligned on
@@ -104,7 +114,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x1:       /* Unaligned - Off by 1 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 24;
 
@@ -113,7 +123,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 8 | value;
                                buf_hold = value >> 24;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFF) << 24;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8);
+                               buf_hold = (value  & 0xFF) << 24;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 1;
@@ -121,7 +140,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x2:       /* Unaligned - Off by 2 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 16;
 
@@ -130,7 +149,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 16 | value;
                                buf_hold = value >> 16;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFFFF) << 16;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFFFF0000)>>16);
+                               buf_hold = (value & 0xFFFF) << 16;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 2;
@@ -138,7 +166,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x3:       /* Unaligned - Off by 3 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 8;
 
@@ -147,7 +175,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 24 | value;
                                buf_hold = value >> 8;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFFFFFF) << 8;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
+                               buf_hold = (value & 0xFFFFFF) << 8;;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 3;
@@ -169,7 +206,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                *--dst = *--src;
        }
        return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memmove);
 #endif /* __HAVE_ARCH_MEMMOVE */
index ecfb663..834565d 100644 (file)
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMSET
+#ifndef CONFIG_OPT_LIB_FUNCTION
+void *memset(void *v_src, int c, __kernel_size_t n)
+{
+       char *src = v_src;
+
+       /* Truncate c to 8 bits */
+       c = (c & 0xFF);
+
+       /* Simple, byte oriented memset or the rest of count. */
+       while (n--)
+               *src++ = c;
+
+       return v_src;
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
 void *memset(void *v_src, int c, __kernel_size_t n)
 {
        char *src = v_src;
-#ifdef CONFIG_OPT_LIB_FUNCTION
        uint32_t *i_src;
        uint32_t w32 = 0;
-#endif
+
        /* Truncate c to 8 bits */
        c = (c & 0xFF);
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
        if (unlikely(c)) {
                /* Make a repeating word out of it */
                w32 = c;
@@ -72,12 +85,13 @@ void *memset(void *v_src, int c, __kernel_size_t n)
 
                src  = (void *)i_src;
        }
-#endif
+
        /* Simple, byte oriented memset or the rest of count. */
        while (n--)
                *src++ = c;
 
        return v_src;
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memset);
 #endif /* __HAVE_ARCH_MEMSET */
diff --git a/arch/microblaze/lib/modsi3.S b/arch/microblaze/lib/modsi3.S
new file mode 100644 (file)
index 0000000..84e0bee
--- /dev/null
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* modulo operation for 32 bit integers.
+*      Input : op1 in Reg r5
+*              op2 in Reg r6
+*      Output: op1 mod op2 in Reg r3
+*/
+
+       .text
+       .globl  __modsi3
+       .type __modsi3,  @function
+       .ent __modsi3
+
+__modsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -16
+       swi     r28, r1, 0
+       swi     r29, r1, 4
+       swi     r30, r1, 8
+       swi     r31, r1, 12
+
+       beqi    r6, div_by_zero /* div_by_zero division error */
+       beqi    r5, result_is_zero /* result is zero */
+       bgeid   r5, r5_pos
+       /* get the sign of the result [ depends only on the first arg] */
+       add     r28, r5, r0
+       rsubi   r5, r5, 0        /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0        /* make r6 positive */
+r6_pos:
+       addik   r3, r0, 0 /* clear mod */
+       addik   r30, r0, 0 /* clear div */
+       addik   r29, r0, 32 /* initialize the loop count */
+/* first part try to find the first '1' in the r5 */
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgeid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r3, r3, r3 /* move that bit into the mod register */
+       rsub    r31, r6, r3 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r3, r0, r31
+       addik   r30, r30, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r30, r30, r30 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bgei    r28, return_here
+       brid    return_here
+       rsubi   r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 [both mod as well as div are 0] */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r28, r1, 0
+       lwi     r29, r1, 4
+       lwi     r30, r1, 8
+       lwi     r31, r1, 12
+       rtsd    r15, 8
+       addik   r1, r1, 16
+
+.size __modsi3,  . - __modsi3
+.end __modsi3
diff --git a/arch/microblaze/lib/muldi3.S b/arch/microblaze/lib/muldi3.S
new file mode 100644 (file)
index 0000000..ceeaa8c
--- /dev/null
@@ -0,0 +1,121 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 64 bit integers, for devices with hard multiply
+ *     Input : Operand1[H] in Reg r5
+ *             Operand1[L] in Reg r6
+ *             Operand2[H] in Reg r7
+ *             Operand2[L] in Reg r8
+ *     Output: Result[H] in Reg r3
+ *             Result[L] in Reg r4
+ *
+ * Explaination:
+ *
+ *     Both the input numbers are divided into 16 bit number as follows
+ *             op1 = A B C D
+ *             op2 = E F G H
+ *     result = D * H
+ *              + (C * H + D * G) << 16
+ *              + (B * H + C * G + D * F) << 32
+ *              + (A * H + B * G + C * F + D * E) << 48
+ *
+ *     Only 64 bits of the output are considered
+ */
+
+       .text
+       .globl  __muldi3
+       .type __muldi3, @function
+       .ent __muldi3
+
+__muldi3:
+       addi    r1, r1, -40
+
+/* Save the input operands on the caller's stack */
+       swi     r5, r1, 44
+       swi     r6, r1, 48
+       swi     r7, r1, 52
+       swi     r8, r1, 56
+
+/* Store all the callee saved registers */
+       sw      r20, r1, r0
+       swi     r21, r1, 4
+       swi     r22, r1, 8
+       swi     r23, r1, 12
+       swi     r24, r1, 16
+       swi     r25, r1, 20
+       swi     r26, r1, 24
+       swi     r27, r1, 28
+
+/* Load all the 16 bit values for A thru H */
+       lhui    r20, r1, 44 /* A */
+       lhui    r21, r1, 46 /* B */
+       lhui    r22, r1, 48 /* C */
+       lhui    r23, r1, 50 /* D */
+       lhui    r24, r1, 52 /* E */
+       lhui    r25, r1, 54 /* F */
+       lhui    r26, r1, 56 /* G */
+       lhui    r27, r1, 58 /* H */
+
+/* D * H ==> LSB of the result on stack ==> Store1 */
+       mul     r9, r23, r27
+       swi     r9, r1, 36 /* Pos2 and Pos3 */
+
+/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */
+/* Store the carry generated in position 2 for Pos 3 */
+       lhui    r11, r1, 36 /* Pos2 */
+       mul     r9, r22, r27 /* C * H */
+       mul     r10, r23, r26 /* D * G */
+       add     r9, r9, r10
+       addc    r12, r0, r0
+       add     r9, r9, r11
+       addc    r12, r12, r0 /* Store the Carry */
+       shi     r9, r1, 36 /* Store Pos2 */
+       swi     r9, r1, 32
+       lhui    r11, r1, 32
+       shi     r11, r1, 34 /* Store Pos1 */
+
+/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */
+       mul     r9, r21, r27 /* B * H */
+       mul     r10, r22, r26 /* C * G */
+       mul     r7, r23, r25 /* D * F */
+       add     r9, r9, r11
+       add     r9, r9, r10
+       add     r9, r9, r7
+       swi     r9, r1, 32 /* Pos0 and Pos1 */
+
+/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */
+       lhui    r11, r1, 32 /* Pos0 */
+       mul     r9, r20, r27 /* A * H */
+       mul     r10, r21, r26 /* B * G */
+       mul     r7, r22, r25 /* C * F */
+       mul     r8, r23, r24 /* D * E */
+       add     r9, r9, r11
+       add     r9, r9, r10
+       add     r9, r9, r7
+       add     r9, r9, r8
+       sext16  r9, r9 /* Sign extend the MSB */
+       shi     r9, r1, 32
+
+/* Move results to r3 and r4 */
+       lhui    r3, r1, 32
+       add     r3, r3, r12
+       shi     r3, r1, 32
+       lwi     r3, r1, 32 /* Hi Part */
+       lwi     r4, r1, 36 /* Lo Part */
+
+/* Restore Callee saved registers */
+       lw      r20, r1, r0
+       lwi     r21, r1, 4
+       lwi     r22, r1, 8
+       lwi     r23, r1, 12
+       lwi     r24, r1, 16
+       lwi     r25, r1, 20
+       lwi     r26, r1, 24
+       lwi     r27, r1, 28
+
+/* Restore Frame and return */
+       rtsd    r15, 8
+       addi    r1, r1, 40
+
+.size __muldi3, . - __muldi3
+.end __muldi3
diff --git a/arch/microblaze/lib/mulsi3.S b/arch/microblaze/lib/mulsi3.S
new file mode 100644 (file)
index 0000000..90bd7b9
--- /dev/null
@@ -0,0 +1,46 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 32 bit integers.
+ *     Input : Operand1 in Reg r5
+ *             Operand2 in Reg r6
+ *     Output: Result [op1 * op2] in Reg r3
+ */
+       .text
+       .globl  __mulsi3
+       .type __mulsi3,  @function
+       .ent __mulsi3
+
+__mulsi3:
+       .frame  r1, 0, r15
+       add     r3, r0, r0
+       beqi    r5, result_is_zero /* multiply by zero */
+       beqi    r6, result_is_zero /* multiply by zero */
+       bgeid   r5, r5_pos
+       xor     r4, r5, r6 /* get the sign of the result */
+       rsubi   r5, r5, 0 /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0 /* make r6 positive */
+r6_pos:
+       bri     l1
+l2:
+       add     r5, r5, r5
+l1:
+       srl     r6, r6
+       addc    r7, r0, r0
+       beqi    r7, l2
+       bneid   r6, l2
+       add     r3, r3, r5
+       blti    r4, negateresult
+       rtsd    r15, 8
+       nop
+negateresult:
+       rtsd    r15, 8
+       rsub    r3, r3, r0
+result_is_zero:
+       rtsd    r15, 8
+       addi    r3, r0, 0
+
+.size __mulsi3,  . - __mulsi3
+.end __mulsi3
diff --git a/arch/microblaze/lib/udivsi3.S b/arch/microblaze/lib/udivsi3.S
new file mode 100644 (file)
index 0000000..64cf57e
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/linkage.h>
+
+/*
+* Unsigned divide operation.
+*      Input : Divisor in Reg r5
+*              Dividend in Reg r6
+*      Output: Result in Reg r3
+*/
+
+       .text
+       .globl  __udivsi3
+       .type __udivsi3, @function
+       .ent __udivsi3
+
+__udivsi3:
+
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -12
+       swi     r29, r1, 0
+       swi     r30, r1, 4
+       swi     r31, r1, 8
+
+       beqi    r6, div_by_zero /* div_by_zero /* division error */
+       beqid   r5, result_is_zero /* result is zero */
+       addik   r30, r0, 0 /* clear mod */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal - if yes, return 1 */
+       rsub    r18, r5, r6
+       beqid   r18, return_here
+       addik   r3, r0, 1
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */
+       xor     r18, r5, r6
+       bgeid   r18, 16
+       add     r3, r0, r0 /* we would anyways clear r3 */
+       blti    r6, return_here /* r6[bit 31 = 1] hence is greater */
+       bri     checkr6
+       rsub    r18, r6, r5 /* microblazecmp */
+       blti    r18, return_here
+
+/* if r6 [bit 31] is set, then return result as 1 */
+checkr6:
+       bgti    r6, div0
+       brid    return_here
+       addik   r3, r0, 1
+
+/* first part try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgtid   r5, div1
+       addik   r29, r29, -1
+div2:
+/* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r30, r30, r30 /* move that bit into the mod register */
+       rsub    r31, r6, r30 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+/* move the r31 to mod since the result was positive */
+       or      r30, r0, r31
+       addik   r3, r3, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r3, r3, r3 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bri     return_here
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r29, r1, 0
+       lwi     r30, r1, 4
+       lwi     r31, r1, 8
+       rtsd    r15, 8
+       addik   r1, r1, 12
+
+.size __udivsi3, . - __udivsi3
+.end __udivsi3
diff --git a/arch/microblaze/lib/umodsi3.S b/arch/microblaze/lib/umodsi3.S
new file mode 100644 (file)
index 0000000..17d16ba
--- /dev/null
@@ -0,0 +1,86 @@
+#include <linux/linkage.h>
+
+/*
+ * Unsigned modulo operation for 32 bit integers.
+ *     Input : op1 in Reg r5
+ *             op2 in Reg r6
+ *     Output: op1 mod op2 in Reg r3
+ */
+
+       .text
+       .globl  __umodsi3
+       .type __umodsi3, @function
+       .ent __umodsi3
+
+__umodsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -12
+       swi     r29, r1, 0
+       swi     r30, r1, 4
+       swi     r31, r1, 8
+
+       beqi    r6, div_by_zero /* div_by_zero - division error */
+       beqid   r5, result_is_zero /* result is zero */
+       addik   r3, r0, 0 /* clear div */
+       addik   r30, r0, 0 /* clear mod */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal /* if yes, return 0 */
+       rsub    r18, r5, r6
+       beqi    r18, return_here
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */
+       xor     r18, r5, r6
+       bgeid   r18, 16
+       addik   r3, r5, 0
+       blti    r6, return_here
+       bri     $lcheckr6
+       rsub    r18, r5, r6 /* microblazecmp */
+       bgti    r18, return_here
+
+/* if r6 [bit 31] is set, then return result as r5-r6 */
+$lcheckr6:
+       bgtid   r6, div0
+       addik   r3, r0, 0
+       addik   r18, r0, 0x7fffffff
+       and     r5, r5, r18
+       and     r6, r6, r18
+       brid    return_here
+       rsub    r3, r6, r5
+/* first part: try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgeid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r3, r3, r3 /* move that bit into the mod register */
+       rsub    r31, r6, r3 /* try to subtract (r3 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r3, r0, r31
+       addik   r30, r30, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r30, r30, r30 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bri     return_here
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r29, r1, 0
+       lwi     r30, r1, 4
+       lwi     r31, r1, 8
+       rtsd    r15, 8
+       addik   r1, r1, 12
+
+.size __umodsi3, . - __umodsi3
+.end __umodsi3
index 55ef532..e363615 100644 (file)
@@ -60,21 +60,6 @@ struct dma_map_ops *get_pci_dma_ops(void)
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       int rc;
-
-       rc = dma_set_mask(&dev->dev, mask);
-       dev->dev.coherent_dma_mask = dev->dma_mask;
-
-       return rc;
-}
-
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
        struct pci_controller *phb;
@@ -1075,8 +1060,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                 bus->number, bus->self ? pci_name(bus->self) : "PHB");
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               struct dev_archdata *sd = &dev->dev.archdata;
-
                /* Setup OF node pointer in archdata */
                dev->dev.of_node = pci_device_to_OF_node(dev);
 
@@ -1086,8 +1069,8 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
 
                /* Hook up default DMA ops */
-               sd->dma_ops = pci_dma_ops;
-               sd->dma_data = (void *)PCI_DRAM_OFFSET;
+               set_dma_ops(&dev->dev, pci_dma_ops);
+               dev->dev.archdata.dma_data = (void *)PCI_DRAM_OFFSET;
 
                /* Read default IRQs and fixup if necessary */
                pci_read_irq_line(dev);
index 2d5c417..3f85df2 100644 (file)
@@ -85,6 +85,7 @@
                        xlnx,dynamic-bus-sizing = <0x1>;
                        xlnx,edge-is-positive = <0x1>;
                        xlnx,family = "virtex5";
+                       xlnx,endianness = <0x1>;
                        xlnx,fpu-exception = <0x1>;
                        xlnx,fsl-data-size = <0x20>;
                        xlnx,fsl-exception = <0x0>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "xlnx,compound";
+                       ranges ;
                        ethernet@81c00000 {
                                compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
                                device_type = "network";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "xlnx,mpmc-4.02.a";
+                       ranges ;
                        PIM3: sdma@84600180 {
                                compatible = "xlnx,ll-dma-1.00.a";
                                interrupt-parent = <&xps_intc_0>;
index 5b89b58..b9529ca 100644 (file)
@@ -17,9 +17,6 @@
 
 static struct of_device_id xilinx_of_bus_ids[] __initdata = {
        { .compatible = "simple-bus", },
-       { .compatible = "xlnx,plb-v46-1.00.a", },
-       { .compatible = "xlnx,opb-v20-1.10.c", },
-       { .compatible = "xlnx,opb-v20-1.10.b", },
        { .compatible = "xlnx,compound", },
        {}
 };
index 784cf82..46cae2b 100644 (file)
@@ -2128,6 +2128,13 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
+config USE_OF
+       bool "Flattened Device Tree support"
+       select OF
+       select OF_FLATTREE
+       help
+         Include support for flattened device tree machine descriptions.
+
 endmenu
 
 config LOCKDEP_SUPPORT
index 3fa34c3..fbb5593 100644 (file)
@@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = {
        .resource       = au1200_psc1_res,
 };
 
+static struct platform_device db1200_stac_dev = {
+       .name           = "ac97-codec",
+       .id             = 1,    /* on PSC1 */
+};
+
 static struct platform_device *db1200_devs[] __initdata = {
        NULL,           /* PSC0, selected by S6.8 */
        &db1200_ide_dev,
@@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = {
        &db1200_rtc_dev,
        &db1200_nand_dev,
        &db1200_audio_dev,
+       &db1200_stac_dev,
 };
 
 static int __init db1200_dev_init(void)
index dea4aed..b003ed5 100644 (file)
 
 #include <irq.h>
 
+static inline void irq_dispose_mapping(unsigned int virq)
+{
+       return;
+}
+
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
 {
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h
new file mode 100644 (file)
index 0000000..f29b862
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  arch/mips/include/asm/prom.h
+ *
+ *  Copyright (C) 2010 Cisco Systems Inc. <dediao@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MIPS_PROM_H
+#define __ASM_MIPS_PROM_H
+
+#ifdef CONFIG_OF
+#include <asm/bootinfo.h>
+
+/* which is compatible with the flattened device tree (FDT) */
+#define cmd_line arcs_cmdline
+
+extern int early_init_dt_scan_memory_arch(unsigned long node,
+       const char *uname, int depth, void *data);
+
+extern int reserve_mem_mach(unsigned long addr, unsigned long size);
+extern void free_mem_mach(unsigned long addr, unsigned long size);
+
+extern void device_tree_init(void);
+#else /* CONFIG_OF */
+static inline void device_tree_init(void) { }
+#endif /* CONFIG_OF */
+
+#endif /* _ASM_MIPS_PROM_H */
index 06f8482..8088498 100644 (file)
@@ -96,6 +96,8 @@ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)    += spinlock_test.o
 
+obj-$(CONFIG_OF)               += prom.o
+
 CFLAGS_cpu-bugs64.o    = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)  += 8250-platform.o
index 9a526ba..802e616 100644 (file)
@@ -103,7 +103,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
        if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
                goto out_unlock;
 
-       retval = security_task_setscheduler(p)
+       retval = security_task_setscheduler(p);
        if (retval)
                goto out_unlock;
 
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
new file mode 100644 (file)
index 0000000..e000b27
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * MIPS support for CONFIG_OF device tree support
+ *
+ * Copyright (C) 2010 Cisco Systems Inc. <dediao@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/debugfs.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/page.h>
+#include <asm/prom.h>
+
+int __init early_init_dt_scan_memory_arch(unsigned long node,
+                                         const char *uname, int depth,
+                                         void *data)
+{
+       return early_init_dt_scan_memory(node, uname, depth, data);
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+       return add_memory_region(base, size, BOOT_MEM_RAM);
+}
+
+int __init reserve_mem_mach(unsigned long addr, unsigned long size)
+{
+       return reserve_bootmem(addr, size, BOOTMEM_DEFAULT);
+}
+
+void __init free_mem_mach(unsigned long addr, unsigned long size)
+{
+       return free_bootmem(addr, size);
+}
+
+u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+       return virt_to_phys(
+               __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS))
+               );
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+                                           unsigned long end)
+{
+       initrd_start = (unsigned long)__va(start);
+       initrd_end = (unsigned long)__va(end);
+       initrd_below_start_ok = 1;
+}
+#endif
+
+/*
+ * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
+ *
+ * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
+ * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
+ * supported.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+                                  const u32 *intspec, unsigned int intsize)
+{
+       return intspec[0];
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+void __init early_init_devtree(void *params)
+{
+       /* Setup flat device-tree pointer */
+       initial_boot_params = params;
+
+       /* Retrieve various informations from the /chosen node of the
+        * device-tree, including the platform type, initrd location and
+        * size, and more ...
+        */
+       of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+       /* Scan memory nodes */
+       of_scan_flat_dt(early_init_dt_scan_root, NULL);
+       of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
+}
+
+void __init device_tree_init(void)
+{
+       unsigned long base, size;
+
+       if (!initial_boot_params)
+               return;
+
+       base = virt_to_phys((void *)initial_boot_params);
+       size = initial_boot_params->totalsize;
+
+       /* Before we do anything, lets reserve the dt blob */
+       reserve_mem_mach(base, size);
+
+       unflatten_device_tree();
+
+       /* free the space reserved for the dt blob */
+       free_mem_mach(base, size);
+}
index 85aef3f..a6b900f 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
 #include <asm/system.h>
+#include <asm/prom.h>
 
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
@@ -487,6 +488,7 @@ static void __init arch_mem_init(char **cmdline_p)
        }
 
        bootmem_init();
+       device_tree_init();
        sparse_init();
        paging_init();
 }
index 10549dc..febbeee 100644 (file)
@@ -70,7 +70,7 @@ SECTIONS
        .exit.text : { EXIT_TEXT; }
        .exit.data : { EXIT_DATA; }
 
-  PERCPU(32)
+  PERCPU(PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
index 9535ce6..83c3218 100644 (file)
 
                ssi@16100 {
                        compatible = "fsl,mpc8610-ssi";
+                       status = "disabled";
                        cell-index = <1>;
                        reg = <0x16100 0x100>;
                        interrupt-parent = <&mpic>;
index c3b113b..3aeb594 100644 (file)
@@ -124,6 +124,9 @@ CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_FSL_DIU=y
+# CONFIG_VGA_CONSOLE is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
index a075da2..d62c801 100644 (file)
@@ -126,6 +126,9 @@ CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_FSL_DIU=y
+# CONFIG_VGA_CONSOLE is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
similarity index 66%
rename from arch/powerpc/include/asm/immap_86xx.h
rename to arch/powerpc/include/asm/fsl_guts.h
index 0f165e5..bebd124 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * MPC86xx Internal Memory Map
+ * Freecale 85xx and 86xx Global Utilties register set
  *
  * Authors: Jeff Brown
  *          Timur Tabi <timur@freescale.com>
  * 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 header file defines structures for various 86xx SOC devices that are
- * used by multiple source files.
  */
 
-#ifndef __ASM_POWERPC_IMMAP_86XX_H__
-#define __ASM_POWERPC_IMMAP_86XX_H__
+#ifndef __ASM_POWERPC_FSL_GUTS_H__
+#define __ASM_POWERPC_FSL_GUTS_H__
 #ifdef __KERNEL__
 
-/* Global Utility Registers */
-struct ccsr_guts {
+/*
+ * These #ifdefs are safe because it's not possible to build a kernel that
+ * runs on e500 and e600 cores.
+ */
+
+#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx)
+#error Only 85xx and 86xx SOCs are supported
+#endif
+
+/**
+ * Global Utility Registers.
+ *
+ * Not all registers defined in this structure are available on all chips, so
+ * you are expected to know whether a given register actually exists on your
+ * chip before you access it.
+ *
+ * Also, some registers are similar on different chips but have slightly
+ * different names.  In these cases, one name is chosen to avoid extraneous
+ * #ifdefs.
+ */
+#ifdef CONFIG_PPC_85xx
+struct ccsr_guts_85xx {
+#else
+struct ccsr_guts_86xx {
+#endif
        __be32  porpllsr;       /* 0x.0000 - POR PLL Ratio Status Register */
        __be32  porbmsr;        /* 0x.0004 - POR Boot Mode Status Register */
        __be32  porimpscr;      /* 0x.0008 - POR I/O Impedance Status and Control Register */
        __be32  pordevsr;       /* 0x.000c - POR I/O Device Status Register */
        __be32  pordbgmsr;      /* 0x.0010 - POR Debug Mode Status Register */
-       u8      res1[0x20 - 0x14];
+       __be32  pordevsr2;      /* 0x.0014 - POR device status register 2 */
+       u8      res018[0x20 - 0x18];
        __be32  porcir;         /* 0x.0020 - POR Configuration Information Register */
-       u8      res2[0x30 - 0x24];
+       u8      res024[0x30 - 0x24];
        __be32  gpiocr;         /* 0x.0030 - GPIO Control Register */
-       u8      res3[0x40 - 0x34];
+       u8      res034[0x40 - 0x34];
        __be32  gpoutdr;        /* 0x.0040 - General-Purpose Output Data Register */
-       u8      res4[0x50 - 0x44];
+       u8      res044[0x50 - 0x44];
        __be32  gpindr;         /* 0x.0050 - General-Purpose Input Data Register */
-       u8      res5[0x60 - 0x54];
+       u8      res054[0x60 - 0x54];
        __be32  pmuxcr;         /* 0x.0060 - Alternate Function Signal Multiplex Control */
-       u8      res6[0x70 - 0x64];
+        __be32  pmuxcr2;       /* 0x.0064 - Alternate function signal multiplex control 2 */
+        __be32  dmuxcr;                /* 0x.0068 - DMA Mux Control Register */
+        u8     res06c[0x70 - 0x6c];
        __be32  devdisr;        /* 0x.0070 - Device Disable Control */
        __be32  devdisr2;       /* 0x.0074 - Device Disable Control 2 */
-       u8      res7[0x80 - 0x78];
+       u8      res078[0x7c - 0x78];
+       __be32  pmjcr;          /* 0x.007c - 4 Power Management Jog Control Register */
        __be32  powmgtcsr;      /* 0x.0080 - Power Management Status and Control Register */
-       u8      res8[0x90 - 0x84];
+       __be32  pmrccr;         /* 0x.0084 - Power Management Reset Counter Configuration Register */
+       __be32  pmpdccr;        /* 0x.0088 - Power Management Power Down Counter Configuration Register */
+       __be32  pmcdr;          /* 0x.008c - 4Power management clock disable register */
        __be32  mcpsumr;        /* 0x.0090 - Machine Check Summary Register */
        __be32  rstrscr;        /* 0x.0094 - Reset Request Status and Control Register */
-       u8      res9[0xA0 - 0x98];
+       __be32  ectrstcr;       /* 0x.0098 - Exception reset control register */
+       __be32  autorstsr;      /* 0x.009c - Automatic reset status register */
        __be32  pvr;            /* 0x.00a0 - Processor Version Register */
        __be32  svr;            /* 0x.00a4 - System Version Register */
-       u8      res10[0xB0 - 0xA8];
+       u8      res0a8[0xb0 - 0xa8];
        __be32  rstcr;          /* 0x.00b0 - Reset Control Register */
-       u8      res11[0xC0 - 0xB4];
+       u8      res0b4[0xc0 - 0xb4];
+#ifdef CONFIG_PPC_85xx
+       __be32  iovselsr;       /* 0x.00c0 - I/O voltage select status register */
+#else
        __be32  elbcvselcr;     /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
-       u8      res12[0x800 - 0xC4];
+#endif
+       u8      res0c4[0x224 - 0xc4];
+       __be32  iodelay1;       /* 0x.0224 - IO delay control register 1 */
+       __be32  iodelay2;       /* 0x.0228 - IO delay control register 2 */
+       u8      res22c[0x800 - 0x22c];
        __be32  clkdvdr;        /* 0x.0800 - Clock Divide Register */
-       u8      res13[0x900 - 0x804];
+       u8      res804[0x900 - 0x804];
        __be32  ircr;           /* 0x.0900 - Infrared Control Register */
-       u8      res14[0x908 - 0x904];
+       u8      res904[0x908 - 0x904];
        __be32  dmacr;          /* 0x.0908 - DMA Control Register */
-       u8      res15[0x914 - 0x90C];
+       u8      res90c[0x914 - 0x90c];
        __be32  elbccr;         /* 0x.0914 - eLBC Control Register */
-       u8      res16[0xB20 - 0x918];
+       u8      res918[0xb20 - 0x918];
        __be32  ddr1clkdr;      /* 0x.0b20 - DDR1 Clock Disable Register */
        __be32  ddr2clkdr;      /* 0x.0b24 - DDR2 Clock Disable Register */
        __be32  ddrclkdr;       /* 0x.0b28 - DDR Clock Disable Register */
-       u8      res17[0xE00 - 0xB2C];
+       u8      resb2c[0xe00 - 0xb2c];
        __be32  clkocr;         /* 0x.0e00 - Clock Out Select Register */
-       u8      res18[0xE10 - 0xE04];
+       u8      rese04[0xe10 - 0xe04];
        __be32  ddrdllcr;       /* 0x.0e10 - DDR DLL Control Register */
-       u8      res19[0xE20 - 0xE14];
+       u8      rese14[0xe20 - 0xe14];
        __be32  lbcdllcr;       /* 0x.0e20 - LBC DLL Control Register */
-       u8      res20[0xF04 - 0xE24];
+       __be32  cpfor;          /* 0x.0e24 - L2 charge pump fuse override register */
+       u8      rese28[0xf04 - 0xe28];
        __be32  srds1cr0;       /* 0x.0f04 - SerDes1 Control Register 0 */
        __be32  srds1cr1;       /* 0x.0f08 - SerDes1 Control Register 0 */
-       u8      res21[0xF40 - 0xF0C];
-       __be32  srds2cr0;       /* 0x.0f40 - SerDes1 Control Register 0 */
-       __be32  srds2cr1;       /* 0x.0f44 - SerDes1 Control Register 0 */
+       u8      resf0c[0xf2c - 0xf0c];
+       __be32  itcr;           /* 0x.0f2c - Internal transaction control register */
+       u8      resf30[0xf40 - 0xf30];
+       __be32  srds2cr0;       /* 0x.0f40 - SerDes2 Control Register 0 */
+       __be32  srds2cr1;       /* 0x.0f44 - SerDes2 Control Register 0 */
 } __attribute__ ((packed));
 
+#ifdef CONFIG_PPC_86xx
+
 #define CCSR_GUTS_DMACR_DEV_SSI        0       /* DMA controller/channel set to SSI */
 #define CCSR_GUTS_DMACR_DEV_IR 1       /* DMA controller/channel set to IR */
 
@@ -93,7 +132,7 @@ struct ccsr_guts {
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
  */
-static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
+static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int device)
 {
        unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
  * ch: The channel on the DMA controller (0, 1, 2, or 3)
  * value: the new value for the bit (0 or 1)
  */
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,
        unsigned int co, unsigned int ch, unsigned int value)
 {
        if ((ch == 0) || (ch == 3)) {
@@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
 #define CCSR_GUTS_CLKDVDR_SSICLK_MASK  0x000000FF
 #define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
 
-#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */
-#endif /* __KERNEL__ */
+#endif
+
+#endif
+#endif
index 9b626cf..f62efdf 100644 (file)
@@ -162,13 +162,10 @@ static int ibmebus_create_device(struct device_node *dn)
        dev->dev.bus = &ibmebus_bus_type;
        dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
 
-       ret = of_device_register(dev);
-       if (ret) {
-               of_device_free(dev);
-               return ret;
-       }
-
-       return 0;
+       ret = of_device_add(dev);
+       if (ret)
+               platform_device_put(dev);
+       return ret;
 }
 
 static int ibmebus_create_devices(const struct of_device_id *matches)
index c1fd0f9..c834757 100644 (file)
@@ -52,14 +52,14 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
                                  phys_addr_t taddr, unsigned long irq,
                                  upf_t flags, int irq_check_parent)
 {
-       const u32 *clk, *spd;
+       const __be32 *clk, *spd;
        u32 clock = BASE_BAUD * 16;
        int index;
 
        /* get clock freq. if present */
        clk = of_get_property(np, "clock-frequency", NULL);
        if (clk && *clk)
-               clock = *clk;
+               clock = be32_to_cpup(clk);
 
        /* get default speed if present */
        spd = of_get_property(np, "current-speed", NULL);
@@ -109,7 +109,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
        legacy_serial_infos[index].taddr = taddr;
        legacy_serial_infos[index].np = of_node_get(np);
        legacy_serial_infos[index].clock = clock;
-       legacy_serial_infos[index].speed = spd ? *spd : 0;
+       legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
        legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
        printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
@@ -168,7 +168,7 @@ static int __init add_legacy_soc_port(struct device_node *np,
 static int __init add_legacy_isa_port(struct device_node *np,
                                      struct device_node *isa_brg)
 {
-       const u32 *reg;
+       const __be32 *reg;
        const char *typep;
        int index = -1;
        u64 taddr;
@@ -181,7 +181,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
                return -1;
 
        /* Verify it's an IO port, we don't support anything else */
-       if (!(reg[0] & 0x00000001))
+       if (!(be32_to_cpu(reg[0]) & 0x00000001))
                return -1;
 
        /* Now look for an "ibm,aix-loc" property that gives us ordering
@@ -202,7 +202,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
                taddr = 0;
 
        /* Add port, irq will be dealt with later */
-       return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
+       return add_legacy_port(np, index, UPIO_PORT, be32_to_cpu(reg[1]), taddr,
                               NO_IRQ, UPF_BOOT_AUTOCONF, 0);
 
 }
@@ -251,9 +251,9 @@ static int __init add_legacy_pci_port(struct device_node *np,
         * we get to their "reg" property
         */
        if (np != pci_dev) {
-               const u32 *reg = of_get_property(np, "reg", NULL);
-               if (reg && (*reg < 4))
-                       index = lindex = *reg;
+               const __be32 *reg = of_get_property(np, "reg", NULL);
+               if (reg && (be32_to_cpup(reg) < 4))
+                       index = lindex = be32_to_cpup(reg);
        }
 
        /* Local index means it's the Nth port in the PCI chip. Unfortunately
@@ -507,7 +507,7 @@ static int __init check_legacy_serial_console(void)
        struct device_node *prom_stdout = NULL;
        int i, speed = 0, offset = 0;
        const char *name;
-       const u32 *spd;
+       const __be32 *spd;
 
        DBG(" -> check_legacy_serial_console()\n");
 
@@ -547,7 +547,7 @@ static int __init check_legacy_serial_console(void)
        }
        spd = of_get_property(prom_stdout, "current-speed", NULL);
        if (spd)
-               speed = *spd;
+               speed = be32_to_cpup(spd);
 
        if (strcmp(name, "serial") != 0)
                goto not_found;
index c3c6a88..9e3132d 100644 (file)
@@ -364,10 +364,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
        return 0;
 }
 
-void __init early_init_dt_scan_chosen_arch(unsigned long node)
+int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
+                                        int depth, void *data)
 {
        unsigned long *lprop;
 
+       /* Use common scan routine to determine if this is the chosen node */
+       if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
+               return 0;
+
 #ifdef CONFIG_PPC64
        /* check if iommu is forced on or off */
        if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -399,6 +404,9 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node)
        if (lprop)
                crashk_res.end = crashk_res.start + *lprop - 1;
 #endif
+
+       /* break now */
+       return 1;
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -683,7 +691,7 @@ void __init early_init_devtree(void *params)
         * device-tree, including the platform type, initrd location and
         * size, TCE reserve, and more ...
         */
-       of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+       of_scan_flat_dt(early_init_dt_scan_chosen_ppc, NULL);
 
        /* Scan memory nodes and rebuild MEMBLOCKs */
        memblock_init();
index 2b390d1..7eb5c40 100644 (file)
@@ -8,7 +8,6 @@
  * Copyright 2010 Freescale Semiconductor, Inc.
  *
  * This file is taken from the Freescale P1022DS BSP, with modifications:
- * 1) No DIU support (pending rewrite of DIU code)
  * 2) No AMP support
  * 3) No PCI endpoint support
  *
 #include <linux/pci.h>
 #include <linux/of_platform.h>
 #include <linux/memblock.h>
-
+#include <asm/div64.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/fsl_guts.h>
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/*
+ * Board-specific initialization of the DIU.  This code should probably be
+ * executed when the DIU is opened, rather than in arch code, but the DIU
+ * driver does not have a mechanism for this (yet).
+ *
+ * This is especially problematic on the P1022DS because the local bus (eLBC)
+ * and the DIU video signals share the same pins, which means that enabling the
+ * DIU will disable access to NOR flash.
+ */
+
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN         0x80000000
+#define CLKDVDR_PXCKINV                0x10000000
+#define CLKDVDR_PXCKDLY                0x06000000
+#define CLKDVDR_PXCLK_MASK     0x00FF0000
+
+/* Some ngPIXIS register definitions */
+#define PX_BRDCFG1_DVIEN       0x80
+#define PX_BRDCFG1_DFPEN       0x40
+#define PX_BRDCFG1_BACKLIGHT   0x20
+#define PX_BRDCFG1_DDCEN       0x10
+
+/*
+ * DIU Area Descriptor
+ *
+ * Note that we need to byte-swap the value before it's written to the AD
+ * register.  So even though the registers don't look like they're in the same
+ * bit positions as they are on the MPC8610, the same value is written to the
+ * AD register on the MPC8610 and on the P1022.
+ */
+#define AD_BYTE_F              0x10000000
+#define AD_ALPHA_C_MASK                0x0E000000
+#define AD_ALPHA_C_SHIFT       25
+#define AD_BLUE_C_MASK         0x01800000
+#define AD_BLUE_C_SHIFT                23
+#define AD_GREEN_C_MASK                0x00600000
+#define AD_GREEN_C_SHIFT       21
+#define AD_RED_C_MASK          0x00180000
+#define AD_RED_C_SHIFT         19
+#define AD_PALETTE             0x00040000
+#define AD_PIXEL_S_MASK                0x00030000
+#define AD_PIXEL_S_SHIFT       16
+#define AD_COMP_3_MASK         0x0000F000
+#define AD_COMP_3_SHIFT                12
+#define AD_COMP_2_MASK         0x00000F00
+#define AD_COMP_2_SHIFT                8
+#define AD_COMP_1_MASK         0x000000F0
+#define AD_COMP_1_SHIFT                4
+#define AD_COMP_0_MASK         0x0000000F
+#define AD_COMP_0_SHIFT                0
+
+#define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
+       cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
+       (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
+       (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
+       (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
+       (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
+
+/**
+ * p1022ds_get_pixel_format: return the Area Descriptor for a given pixel depth
+ *
+ * The Area Descriptor is a 32-bit value that determine which bits in each
+ * pixel are to be used for each color.
+ */
+static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
+       int monitor_port)
+{
+       switch (bits_per_pixel) {
+       case 32:
+               /* 0x88883316 */
+               return MAKE_AD(3, 2, 0, 1, 3, 8, 8, 8, 8);
+       case 24:
+               /* 0x88082219 */
+               return MAKE_AD(4, 0, 1, 2, 2, 0, 8, 8, 8);
+       case 16:
+               /* 0x65053118 */
+               return MAKE_AD(4, 2, 1, 0, 1, 5, 6, 5, 0);
+       default:
+               pr_err("fsl-diu: unsupported pixel depth %u\n", bits_per_pixel);
+               return 0;
+       }
+}
+
+/**
+ * p1022ds_set_gamma_table: update the gamma table, if necessary
+ *
+ * On some boards, the gamma table for some ports may need to be modified.
+ * This is not the case on the P1022DS, so we do nothing.
+*/
+static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
+{
+}
+
+/**
+ * p1022ds_set_monitor_port: switch the output to a different monitor port
+ *
+ */
+static void p1022ds_set_monitor_port(int monitor_port)
+{
+       struct device_node *pixis_node;
+       u8 __iomem *brdcfg1;
+
+       pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
+       if (!pixis_node) {
+               pr_err("p1022ds: missing ngPIXIS node\n");
+               return;
+       }
+
+       brdcfg1 = of_iomap(pixis_node, 0);
+       if (!brdcfg1) {
+               pr_err("p1022ds: could not map ngPIXIS registers\n");
+               return;
+       }
+       brdcfg1 += 9;   /* BRDCFG1 is at offset 9 in the ngPIXIS */
+
+       switch (monitor_port) {
+       case 0: /* DVI */
+               /* Enable the DVI port, disable the DFP and the backlight */
+               clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
+                            PX_BRDCFG1_DVIEN);
+               break;
+       case 1: /* Single link LVDS */
+               /* Enable the DFP port, disable the DVI and the backlight */
+               clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
+                            PX_BRDCFG1_DFPEN);
+               break;
+       default:
+               pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
+       }
+}
+
+/**
+ * p1022ds_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
+void p1022ds_set_pixel_clock(unsigned int pixclock)
+{
+       struct device_node *guts_np = NULL;
+       struct ccsr_guts_85xx __iomem *guts;
+       unsigned long freq;
+       u64 temp;
+       u32 pxclk;
+
+       /* Map the global utilities registers. */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (!guts_np) {
+               pr_err("p1022ds: missing global utilties device node\n");
+               return;
+       }
+
+       guts = of_iomap(guts_np, 0);
+       of_node_put(guts_np);
+       if (!guts) {
+               pr_err("p1022ds: could not map global utilties device\n");
+               return;
+       }
+
+       /* Convert pixclock from a wavelength to a frequency */
+       temp = 1000000000000ULL;
+       do_div(temp, pixclock);
+       freq = temp;
+
+       /* pixclk is the ratio of the platform clock to the pixel clock */
+       pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+
+       /* Disable the pixel clock, and set it to non-inverted and no delay */
+       clrbits32(&guts->clkdvdr,
+                 CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+       /* Enable the clock and set the pxclk */
+       setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+}
+
+/**
+ * p1022ds_show_monitor_port: show the current monitor
+ *
+ * This function returns a string indicating whether the current monitor is
+ * set to DVI or LVDS.
+ */
+ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
+{
+       return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
+               monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
+}
+
+/**
+ * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
+ */
+int p1022ds_set_sysfs_monitor_port(int val)
+{
+       return val < 2 ? val : 0;
+}
+
+#endif
 
 void __init p1022_ds_pic_init(void)
 {
@@ -92,6 +290,15 @@ static void __init p1022_ds_setup_arch(void)
        }
 #endif
 
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+       diu_ops.get_pixel_format        = p1022ds_get_pixel_format;
+       diu_ops.set_gamma_table         = p1022ds_set_gamma_table;
+       diu_ops.set_monitor_port        = p1022ds_set_monitor_port;
+       diu_ops.set_pixel_clock         = p1022ds_set_pixel_clock;
+       diu_ops.show_monitor_port       = p1022ds_show_monitor_port;
+       diu_ops.set_sysfs_monitor_port  = p1022ds_set_sysfs_monitor_port;
+#endif
+
 #ifdef CONFIG_SMP
        mpc85xx_smp_init();
 #endif
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
new file mode 100644 (file)
index 0000000..ae4b010
--- /dev/null
@@ -0,0 +1,6 @@
+obj-y += kernel/
+obj-y += mm/
+obj-y += crypto/
+obj-y += appldata/
+obj-y += hypfs/
+obj-y += kvm/
index 75976a1..068e55d 100644 (file)
@@ -60,6 +60,9 @@ config NO_IOMEM
 config NO_DMA
        def_bool y
 
+config ARCH_DMA_ADDR_T_64BIT
+       def_bool 64BIT
+
 config GENERIC_LOCKBREAK
        bool
        default y
@@ -101,6 +104,7 @@ config S390
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
+       select HAVE_GET_USER_PAGES_FAST
        select ARCH_INLINE_SPIN_TRYLOCK
        select ARCH_INLINE_SPIN_TRYLOCK_BH
        select ARCH_INLINE_SPIN_LOCK
@@ -286,6 +290,14 @@ config MARCH_Z10
          machines such as the z990, z890, z900, z800, z9-109, z9-ec
          and z9-bc.
 
+config MARCH_Z196
+       bool "IBM zEnterprise 196"
+       help
+         Select this to enable optimizations for IBM zEnterprise 196.
+         The kernel will be slightly faster but will not work on older
+         machines such as the z990, z890, z900, z800, z9-109, z9-ec,
+         z9-bc, z10-ec and z10-bc.
+
 endchoice
 
 config PACK_STACK
index 0c9e6c6..d5b8a6a 100644 (file)
@@ -40,6 +40,7 @@ cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
 cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
 cflags-$(CONFIG_MARCH_Z9_109) += $(call cc-option,-march=z9-109)
 cflags-$(CONFIG_MARCH_Z10) += $(call cc-option,-march=z10)
+cflags-$(CONFIG_MARCH_Z196) += $(call cc-option,-march=z196)
 
 #KBUILD_IMAGE is necessary for make rpm
 KBUILD_IMAGE   :=arch/s390/boot/image
@@ -94,8 +95,8 @@ head-y                := arch/s390/kernel/head.o
 head-y         += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
 head-y         += arch/s390/kernel/init_task.o
 
-core-y         += arch/s390/mm/ arch/s390/kernel/ arch/s390/crypto/ \
-                  arch/s390/appldata/ arch/s390/hypfs/ arch/s390/kvm/
+# See arch/s390/Kbuild for content of core part of the kernel
+core-y         += arch/s390/
 
 libs-y         += arch/s390/lib/
 drivers-y      += drivers/s390/
index 0ef9829..7ee9a1b 100644 (file)
@@ -297,7 +297,7 @@ static inline int crypt_s390_func_available(int func)
        int ret;
 
        /* check if CPACF facility (bit 17) is available */
-       if (!(stfl() & 1ULL << (31 - 17)))
+       if (!test_facility(17))
                return 0;
 
        switch (func & CRYPT_S390_OP_MASK) {
index f3ba0fa..e850111 100644 (file)
@@ -92,6 +92,16 @@ struct ccw_device {
 };
 
 /*
+ * Possible events used by the path_event notifier.
+ */
+#define PE_NONE                                0x0
+#define PE_PATH_GONE                   0x1 /* A path is no longer available. */
+#define PE_PATH_AVAILABLE              0x2 /* A path has become available and
+                                              was successfully verified. */
+#define PE_PATHGROUP_ESTABLISHED       0x4 /* A pathgroup was reset and had
+                                              to be established again. */
+
+/*
  * Possible CIO actions triggered by the unit check handler.
  */
 enum uc_todo {
@@ -109,6 +119,7 @@ enum uc_todo {
  * @set_online: called when setting device online
  * @set_offline: called when setting device offline
  * @notify: notify driver of device state changes
+ * @path_event: notify driver of channel path events
  * @shutdown: called at device shutdown
  * @prepare: prepare for pm state transition
  * @complete: undo work done in @prepare
@@ -127,6 +138,7 @@ struct ccw_driver {
        int (*set_online) (struct ccw_device *);
        int (*set_offline) (struct ccw_device *);
        int (*notify) (struct ccw_device *, int);
+       void (*path_event) (struct ccw_device *, int *);
        void (*shutdown) (struct ccw_device *);
        int (*prepare) (struct ccw_device *);
        void (*complete) (struct ccw_device *);
index 471234b..e0b6954 100644 (file)
@@ -20,7 +20,7 @@ struct cpuid
        unsigned int ident   : 24;
        unsigned int machine : 16;
        unsigned int unused  : 16;
-} __packed;
+} __attribute__ ((packed, aligned(8)));
 
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_S390_CPU_H */
index bb8343d..b56403c 100644 (file)
@@ -37,32 +37,6 @@ static inline int prepare_hugepage_range(struct file *file,
 int arch_prepare_hugepage(struct page *page);
 void arch_release_hugepage(struct page *page);
 
-static inline pte_t pte_mkhuge(pte_t pte)
-{
-       /*
-        * PROT_NONE needs to be remapped from the pte type to the ste type.
-        * The HW invalid bit is also different for pte and ste. The pte
-        * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
-        * bit, so we don't have to clear it.
-        */
-       if (pte_val(pte) & _PAGE_INVALID) {
-               if (pte_val(pte) & _PAGE_SWT)
-                       pte_val(pte) |= _HPAGE_TYPE_NONE;
-               pte_val(pte) |= _SEGMENT_ENTRY_INV;
-       }
-       /*
-        * Clear SW pte bits SWT and SWX, there are no SW bits in a segment
-        * table entry.
-        */
-       pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX);
-       /*
-        * Also set the change-override bit because we don't need dirty bit
-        * tracking for hugetlbfs pages.
-        */
-       pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
-       return pte;
-}
-
 static inline pte_t huge_pte_wrprotect(pte_t pte)
 {
        pte_val(pte) |= _PAGE_RO;
index 0f97ef2..65e172f 100644 (file)
@@ -150,9 +150,10 @@ struct _lowcore {
         */
        __u32   ipib;                           /* 0x0e00 */
        __u32   ipib_checksum;                  /* 0x0e04 */
+       __u8    pad_0x0e08[0x0f00-0x0e08];      /* 0x0e08 */
 
-       /* Align to the top 1k of prefix area */
-       __u8    pad_0x0e08[0x1000-0x0e08];      /* 0x0e08 */
+       /* Extended facility list */
+       __u64   stfle_fac_list[32];             /* 0x0f00 */
 } __packed;
 
 #else /* CONFIG_32BIT */
@@ -285,7 +286,11 @@ struct _lowcore {
         */
        __u64   ipib;                           /* 0x0e00 */
        __u32   ipib_checksum;                  /* 0x0e08 */
-       __u8    pad_0x0e0c[0x11b8-0x0e0c];      /* 0x0e0c */
+       __u8    pad_0x0e0c[0x0f00-0x0e0c];      /* 0x0e0c */
+
+       /* Extended facility list */
+       __u64   stfle_fac_list[32];             /* 0x0f00 */
+       __u8    pad_0x1000[0x11b8-0x1000];      /* 0x1000 */
 
        /* 64 bit extparam used for pfault/diag 250: defined by architecture */
        __u64   ext_params2;                    /* 0x11B8 */
index af650fb..a8729ea 100644 (file)
@@ -108,9 +108,13 @@ typedef pte_t *pgtable_t;
 #define __pgprot(x)     ((pgprot_t) { (x) } )
 
 static inline void
-page_set_storage_key(unsigned long addr, unsigned int skey)
+page_set_storage_key(unsigned long addr, unsigned int skey, int mapped)
 {
-       asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
+       if (!mapped)
+               asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0"
+                            : : "d" (skey), "a" (addr));
+       else
+               asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));
 }
 
 static inline unsigned int
index 68940d0..082eb4e 100644 (file)
 
 unsigned long *crst_table_alloc(struct mm_struct *, int);
 void crst_table_free(struct mm_struct *, unsigned long *);
+void crst_table_free_rcu(struct mm_struct *, unsigned long *);
 
 unsigned long *page_table_alloc(struct mm_struct *);
 void page_table_free(struct mm_struct *, unsigned long *);
+void page_table_free_rcu(struct mm_struct *, unsigned long *);
 void disable_noexec(struct mm_struct *, struct task_struct *);
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
@@ -176,4 +178,6 @@ static inline void pmd_populate(struct mm_struct *mm,
 #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
 #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
 
+extern void rcu_table_freelist_finish(void);
+
 #endif /* _S390_PGALLOC_H */
index 3157441..986dc94 100644 (file)
@@ -38,6 +38,7 @@
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
 extern void vmem_map_init(void);
+extern void fault_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -46,11 +47,27 @@ extern void vmem_map_init(void);
 #define update_mmu_cache(vma, address, ptep)     do { } while (0)
 
 /*
- * ZERO_PAGE is a global shared page that is always zero: used
+ * ZERO_PAGE is a global shared page that is always zero; used
  * for zero-mapped memory areas etc..
  */
-extern char empty_zero_page[PAGE_SIZE];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern unsigned long empty_zero_page;
+extern unsigned long zero_page_mask;
+
+#define ZERO_PAGE(vaddr) \
+       (virt_to_page((void *)(empty_zero_page + \
+        (((unsigned long)(vaddr)) &zero_page_mask))))
+
+#define is_zero_pfn is_zero_pfn
+static inline int is_zero_pfn(unsigned long pfn)
+{
+       extern unsigned long zero_pfn;
+       unsigned long offset_from_zero_pfn = pfn - zero_pfn;
+       return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
+}
+
+#define my_zero_pfn(addr)      page_to_pfn(ZERO_PAGE(addr))
+
 #endif /* !__ASSEMBLY__ */
 
 /*
@@ -300,6 +317,7 @@ extern unsigned long VMALLOC_START;
 
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_ORIGIN  0x7fffffc0UL    /* page table origin        */
+#define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
 #define _SEGMENT_ENTRY_INV     0x20    /* invalid segment table entry      */
 #define _SEGMENT_ENTRY_COMMON  0x10    /* common segment bit               */
 #define _SEGMENT_ENTRY_PTL     0x0f    /* page table length                */
@@ -572,7 +590,7 @@ static inline void rcp_unlock(pte_t *ptep)
 }
 
 /* forward declaration for SetPageUptodate in page-flags.h*/
-static inline void page_clear_dirty(struct page *page);
+static inline void page_clear_dirty(struct page *page, int mapped);
 #include <linux/page-flags.h>
 
 static inline void ptep_rcp_copy(pte_t *ptep)
@@ -754,6 +772,34 @@ static inline pte_t pte_mkspecial(pte_t pte)
        return pte;
 }
 
+#ifdef CONFIG_HUGETLB_PAGE
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+       /*
+        * PROT_NONE needs to be remapped from the pte type to the ste type.
+        * The HW invalid bit is also different for pte and ste. The pte
+        * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE
+        * bit, so we don't have to clear it.
+        */
+       if (pte_val(pte) & _PAGE_INVALID) {
+               if (pte_val(pte) & _PAGE_SWT)
+                       pte_val(pte) |= _HPAGE_TYPE_NONE;
+               pte_val(pte) |= _SEGMENT_ENTRY_INV;
+       }
+       /*
+        * Clear SW pte bits SWT and SWX, there are no SW bits in a segment
+        * table entry.
+        */
+       pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX);
+       /*
+        * Also set the change-override bit because we don't need dirty bit
+        * tracking for hugetlbfs pages.
+        */
+       pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO);
+       return pte;
+}
+#endif
+
 #ifdef CONFIG_PGSTE
 /*
  * Get (and clear) the user dirty bit for a PTE.
@@ -782,7 +828,7 @@ static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm,
        }
        dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste);
        if (skey & _PAGE_CHANGED)
-               page_clear_dirty(page);
+               page_clear_dirty(page, 1);
        rcp_unlock(ptep);
        return dirty;
 }
@@ -957,9 +1003,9 @@ static inline int page_test_dirty(struct page *page)
 }
 
 #define __HAVE_ARCH_PAGE_CLEAR_DIRTY
-static inline void page_clear_dirty(struct page *page)
+static inline void page_clear_dirty(struct page *page, int mapped)
 {
-       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY);
+       page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped);
 }
 
 /*
index 73e2598..8d6f871 100644 (file)
@@ -82,8 +82,6 @@ struct thread_struct {
         unsigned long prot_addr;        /* address of protection-excep.     */
         unsigned int trap_no;
         per_struct per_info;
-       /* Used to give failing instruction back to user for ieee exceptions */
-       unsigned long ieee_instruction_pointer; 
         /* pfault_wait is used to block the process on a pfault event */
        unsigned long pfault_wait;
 };
index e2c218d..d9d42b1 100644 (file)
@@ -481,8 +481,7 @@ struct user_regs_struct
         * watchpoints. This is the way intel does it.
         */
        per_struct per_info;
-       unsigned long ieee_instruction_pointer; 
-       /* Used to give failing instruction back to user for ieee exceptions */
+       unsigned long ieee_instruction_pointer; /* obsolete, always 0 */
 };
 
 #ifdef __KERNEL__
index 2afc060..1a9307e 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 
-typedef void (*ext_int_handler_t)(__u16 code);
+typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long);
 
 typedef struct ext_int_info_t {
        struct ext_int_info_t *next;
index 35d786f..6d45ef6 100644 (file)
@@ -1 +1,3 @@
 #include <asm-generic/scatterlist.h>
+
+#define ARCH_HAS_SG_CHAIN
index 25e831d..d5e2ef1 100644 (file)
@@ -73,6 +73,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_PFMF      (1UL << 11)
 #define MACHINE_FLAG_LPAR      (1UL << 12)
 #define MACHINE_FLAG_SPP       (1UL << 13)
+#define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -90,6 +91,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_HPAGE      (0)
 #define MACHINE_HAS_PFMF       (0)
 #define MACHINE_HAS_SPP                (0)
+#define MACHINE_HAS_TOPOLOGY   (0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -100,6 +102,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_HPAGE      (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE)
 #define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
+#define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
index 8429686..5c0246b 100644 (file)
@@ -65,8 +65,6 @@ static inline void syscall_get_arguments(struct task_struct *task,
        if (test_tsk_thread_flag(task, TIF_31BIT))
                mask = 0xffffffff;
 #endif
-       if (i + n == 6)
-               args[--n] = regs->args[0] & mask;
        while (n-- > 0)
                if (i + n > 0)
                        args[n] = regs->gprs[2 + i + n] & mask;
@@ -80,8 +78,6 @@ static inline void syscall_set_arguments(struct task_struct *task,
                                         const unsigned long *args)
 {
        BUG_ON(i + n > 6);
-       if (i + n == 6)
-               regs->args[0] = args[--n];
        while (n-- > 0)
                if (i + n > 0)
                        regs->gprs[2 + i + n] = args[n];
index 22bdb2a..79d3d6e 100644 (file)
 #ifndef __ASM_S390_SYSINFO_H
 #define __ASM_S390_SYSINFO_H
 
+#include <asm/bitsperlong.h>
+
 struct sysinfo_1_1_1 {
-       char reserved_0[32];
+       unsigned short :16;
+       unsigned char ccr;
+       unsigned char cai;
+       char reserved_0[28];
        char manufacturer[16];
        char type[4];
        char reserved_1[12];
@@ -104,6 +109,39 @@ struct sysinfo_3_2_2 {
        char reserved_544[3552];
 };
 
+#define TOPOLOGY_CPU_BITS      64
+#define TOPOLOGY_NR_MAG                6
+
+struct topology_cpu {
+       unsigned char reserved0[4];
+       unsigned char :6;
+       unsigned char pp:2;
+       unsigned char reserved1;
+       unsigned short origin;
+       unsigned long mask[TOPOLOGY_CPU_BITS / BITS_PER_LONG];
+};
+
+struct topology_container {
+       unsigned char reserved[7];
+       unsigned char id;
+};
+
+union topology_entry {
+       unsigned char nl;
+       struct topology_cpu cpu;
+       struct topology_container container;
+};
+
+struct sysinfo_15_1_x {
+       unsigned char reserved0[2];
+       unsigned short length;
+       unsigned char mag[TOPOLOGY_NR_MAG];
+       unsigned char reserved1;
+       unsigned char mnest;
+       unsigned char reserved2[4];
+       union topology_entry tle[0];
+};
+
 static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
 {
        register int r0 asm("0") = (fc << 28) | sel1;
index 1f2ebc4..3ad16db 100644 (file)
@@ -85,14 +85,16 @@ static inline void restore_access_regs(unsigned int *acrs)
        asm volatile("lam 0,15,%0" : : "Q" (*acrs));
 }
 
-#define switch_to(prev,next,last) do {                                      \
-       if (prev == next)                                                    \
-               break;                                                       \
-       save_fp_regs(&prev->thread.fp_regs);                                 \
-       restore_fp_regs(&next->thread.fp_regs);                              \
-       save_access_regs(&prev->thread.acrs[0]);                             \
-       restore_access_regs(&next->thread.acrs[0]);                          \
-       prev = __switch_to(prev,next);                                       \
+#define switch_to(prev,next,last) do {                                 \
+       if (prev->mm) {                                                 \
+               save_fp_regs(&prev->thread.fp_regs);                    \
+               save_access_regs(&prev->thread.acrs[0]);                \
+       }                                                               \
+       if (next->mm) {                                                 \
+               restore_fp_regs(&next->thread.fp_regs);                 \
+               restore_access_regs(&next->thread.acrs[0]);             \
+       }                                                               \
+       prev = __switch_to(prev,next);                                  \
 } while (0)
 
 extern void account_vtime(struct task_struct *, struct task_struct *);
@@ -418,30 +420,21 @@ extern void smp_ctl_clear_bit(int cr, int bit);
 
 #endif /* CONFIG_SMP */
 
-static inline unsigned int stfl(void)
-{
-       asm volatile(
-               "       .insn   s,0xb2b10000,0(0)\n" /* stfl */
-               "0:\n"
-               EX_TABLE(0b,0b));
-       return S390_lowcore.stfl_fac_list;
-}
+#define MAX_FACILITY_BIT (256*8)       /* stfle_fac_list has 256 bytes */
 
-static inline int __stfle(unsigned long long *list, int doublewords)
+/*
+ * The test_facility function uses the bit odering where the MSB is bit 0.
+ * That makes it easier to query facility bits with the bit number as
+ * documented in the Principles of Operation.
+ */
+static inline int test_facility(unsigned long nr)
 {
-       typedef struct { unsigned long long _[doublewords]; } addrtype;
-       register unsigned long __nr asm("0") = doublewords - 1;
-
-       asm volatile(".insn s,0xb2b00000,%0" /* stfle */
-                    : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc");
-       return __nr + 1;
-}
+       unsigned char *ptr;
 
-static inline int stfle(unsigned long long *list, int doublewords)
-{
-       if (!(stfl() & (1UL << 24)))
-               return -EOPNOTSUPP;
-       return __stfle(list, doublewords);
+       if (nr >= MAX_FACILITY_BIT)
+               return 0;
+       ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3);
+       return (*ptr & (0x80 >> (nr & 7))) != 0;
 }
 
 static inline unsigned short stap(void)
index fd1c00d..f1f644f 100644 (file)
@@ -64,10 +64,9 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb,
        if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS))
                __tlb_flush_mm(tlb->mm);
        while (tlb->nr_ptes > 0)
-               pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]);
+               page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]);
        while (tlb->nr_pxds < TLB_NR_PTRS)
-               /* pgd_free frees the pointer as region or segment table */
-               pgd_free(tlb->mm, tlb->array[tlb->nr_pxds++]);
+               crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]);
 }
 
 static inline void tlb_finish_mmu(struct mmu_gather *tlb,
@@ -75,6 +74,8 @@ static inline void tlb_finish_mmu(struct mmu_gather *tlb,
 {
        tlb_flush_mmu(tlb, start, end);
 
+       rcu_table_freelist_finish();
+
        /* keep the page table cache within bounds */
        check_pgt_cache();
 
@@ -103,7 +104,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
                if (tlb->nr_ptes >= tlb->nr_pxds)
                        tlb_flush_mmu(tlb, 0, 0);
        } else
-               pte_free(tlb->mm, pte);
+               page_table_free(tlb->mm, (unsigned long *) pte);
 }
 
 /*
@@ -124,7 +125,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
                if (tlb->nr_ptes >= tlb->nr_pxds)
                        tlb_flush_mmu(tlb, 0, 0);
        } else
-               pmd_free(tlb->mm, pmd);
+               crst_table_free(tlb->mm, (unsigned long *) pmd);
 #endif
 }
 
@@ -146,7 +147,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
                if (tlb->nr_ptes >= tlb->nr_pxds)
                        tlb_flush_mmu(tlb, 0, 0);
        } else
-               pud_free(tlb->mm, pud);
+               crst_table_free(tlb->mm, (unsigned long *) pud);
 #endif
 }
 
index 051107a..c533883 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_S390_TOPOLOGY_H
 
 #include <linux/cpumask.h>
+#include <asm/sysinfo.h>
 
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
@@ -32,6 +33,7 @@ static inline const struct cpumask *cpu_book_mask(unsigned int cpu)
 
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
+void store_topology(struct sysinfo_15_1_x *info);
 
 #define POLARIZATION_UNKNWN    (-1)
 #define POLARIZATION_HRZ       (0)
index 5232278..f3c1b82 100644 (file)
@@ -84,6 +84,7 @@ int main(void)
        DEFINE(__LC_SVC_INT_CODE, offsetof(struct _lowcore, svc_code));
        DEFINE(__LC_PGM_ILC, offsetof(struct _lowcore, pgm_ilc));
        DEFINE(__LC_PGM_INT_CODE, offsetof(struct _lowcore, pgm_code));
+       DEFINE(__LC_TRANS_EXC_CODE, offsetof(struct _lowcore, trans_exc_code));
        DEFINE(__LC_PER_ATMID, offsetof(struct _lowcore, per_perc_atmid));
        DEFINE(__LC_PER_ADDRESS, offsetof(struct _lowcore, per_address));
        DEFINE(__LC_PER_ACCESS_ID, offsetof(struct _lowcore, per_access_id));
@@ -142,10 +143,8 @@ int main(void)
        DEFINE(__LC_GPREGS_SAVE_AREA, offsetof(struct _lowcore, gpregs_save_area));
        DEFINE(__LC_CREGS_SAVE_AREA, offsetof(struct _lowcore, cregs_save_area));
 #ifdef CONFIG_32BIT
-       DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params));
        DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, extended_save_area_addr));
 #else /* CONFIG_32BIT */
-       DEFINE(__LC_PFAULT_INTPARM, offsetof(struct _lowcore, ext_params2));
        DEFINE(__LC_EXT_PARAMS2, offsetof(struct _lowcore, ext_params2));
        DEFINE(SAVE_AREA_BASE, offsetof(struct _lowcore, floating_pt_save_area));
        DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
index 123dd66..3141025 100644 (file)
@@ -51,8 +51,7 @@ struct user_regs_struct32
         * watchpoints. This is the way intel does it.
         */
        per_struct32 per_info;
-       u32  ieee_instruction_pointer; 
-       /* Used to give failing instruction back to user for ieee exceptions */
+       u32  ieee_instruction_pointer;  /* obsolete, always 0 */
 };
 
 struct user32 {
index b39b27d..c83726c 100644 (file)
@@ -113,7 +113,7 @@ enum {
        INSTR_INVALID,
        INSTR_E,
        INSTR_RIE_R0IU, INSTR_RIE_R0UU, INSTR_RIE_RRP, INSTR_RIE_RRPU,
-       INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU,
+       INSTR_RIE_RRUUU, INSTR_RIE_RUPI, INSTR_RIE_RUPU, INSTR_RIE_RRI0,
        INSTR_RIL_RI, INSTR_RIL_RP, INSTR_RIL_RU, INSTR_RIL_UP,
        INSTR_RIS_R0RDU, INSTR_RIS_R0UU, INSTR_RIS_RURDI, INSTR_RIS_RURDU,
        INSTR_RI_RI, INSTR_RI_RP, INSTR_RI_RU, INSTR_RI_UP,
@@ -122,13 +122,14 @@ enum {
        INSTR_RRE_RR, INSTR_RRE_RR_OPT,
        INSTR_RRF_0UFF, INSTR_RRF_F0FF, INSTR_RRF_F0FF2, INSTR_RRF_F0FR,
        INSTR_RRF_FFRU, INSTR_RRF_FUFF, INSTR_RRF_M0RR, INSTR_RRF_R0RR,
-       INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF, INSTR_RRF_U0RR,
-       INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
+       INSTR_RRF_R0RR2, INSTR_RRF_RURR, INSTR_RRF_U0FF, INSTR_RRF_U0RF,
+       INSTR_RRF_U0RR, INSTR_RRF_UUFF, INSTR_RRR_F0FF, INSTR_RRS_RRRDU,
        INSTR_RR_FF, INSTR_RR_R0, INSTR_RR_RR, INSTR_RR_U0, INSTR_RR_UR,
        INSTR_RSE_CCRD, INSTR_RSE_RRRD, INSTR_RSE_RURD,
        INSTR_RSI_RRP,
        INSTR_RSL_R0RD,
        INSTR_RSY_AARD, INSTR_RSY_CCRD, INSTR_RSY_RRRD, INSTR_RSY_RURD,
+       INSTR_RSY_RDRM,
        INSTR_RS_AARD, INSTR_RS_CCRD, INSTR_RS_R0RD, INSTR_RS_RRRD,
        INSTR_RS_RURD,
        INSTR_RXE_FRRD, INSTR_RXE_RRRD,
@@ -139,7 +140,7 @@ enum {
        INSTR_SIY_IRD, INSTR_SIY_URD,
        INSTR_SI_URD,
        INSTR_SSE_RDRD,
-       INSTR_SSF_RRDRD,
+       INSTR_SSF_RRDRD, INSTR_SSF_RRDRD2,
        INSTR_SS_L0RDRD, INSTR_SS_LIRDRD, INSTR_SS_LLRDRD, INSTR_SS_RRRDRD,
        INSTR_SS_RRRDRD2, INSTR_SS_RRRDRD3,
        INSTR_S_00, INSTR_S_RD,
@@ -152,7 +153,7 @@ struct operand {
 };
 
 struct insn {
-       const char name[6];
+       const char name[5];
        unsigned char opfrag;
        unsigned char format;
 };
@@ -217,6 +218,7 @@ static const unsigned char formats[][7] = {
        [INSTR_RIE_RRP]   = { 0xff, R_8,R_12,J16_16,0,0,0 },
        [INSTR_RIE_RRUUU] = { 0xff, R_8,R_12,U8_16,U8_24,U8_32,0 },
        [INSTR_RIE_RUPI]  = { 0xff, R_8,I8_32,U4_12,J16_16,0,0 },
+       [INSTR_RIE_RRI0]  = { 0xff, R_8,R_12,I16_16,0,0,0 },
        [INSTR_RIL_RI]    = { 0x0f, R_8,I32_16,0,0,0,0 },
        [INSTR_RIL_RP]    = { 0x0f, R_8,J32_16,0,0,0,0 },
        [INSTR_RIL_RU]    = { 0x0f, R_8,U32_16,0,0,0,0 },
@@ -248,6 +250,7 @@ static const unsigned char formats[][7] = {
        [INSTR_RRF_FUFF]  = { 0xff, F_24,F_16,F_28,U4_20,0,0 },
        [INSTR_RRF_M0RR]  = { 0xff, R_24,R_28,M_16,0,0,0 },
        [INSTR_RRF_R0RR]  = { 0xff, R_24,R_16,R_28,0,0,0 },
+       [INSTR_RRF_R0RR2] = { 0xff, R_24,R_28,R_16,0,0,0 },
        [INSTR_RRF_RURR]  = { 0xff, R_24,R_28,R_16,U4_20,0,0 },
        [INSTR_RRF_U0FF]  = { 0xff, F_24,U4_16,F_28,0,0,0 },
        [INSTR_RRF_U0RF]  = { 0xff, R_24,U4_16,F_28,0,0,0 },
@@ -269,6 +272,7 @@ static const unsigned char formats[][7] = {
        [INSTR_RSY_CCRD]  = { 0xff, C_8,C_12,D20_20,B_16,0,0 },
        [INSTR_RSY_RRRD]  = { 0xff, R_8,R_12,D20_20,B_16,0,0 },
        [INSTR_RSY_RURD]  = { 0xff, R_8,U4_12,D20_20,B_16,0,0 },
+       [INSTR_RSY_RDRM]  = { 0xff, R_8,D20_20,B_16,U4_12,0,0 },
        [INSTR_RS_AARD]   = { 0xff, A_8,A_12,D_20,B_16,0,0 },
        [INSTR_RS_CCRD]   = { 0xff, C_8,C_12,D_20,B_16,0,0 },
        [INSTR_RS_R0RD]   = { 0xff, R_8,D_20,B_16,0,0,0 },
@@ -290,6 +294,7 @@ static const unsigned char formats[][7] = {
        [INSTR_SI_URD]    = { 0xff, D_20,B_16,U8_8,0,0,0 },
        [INSTR_SSE_RDRD]  = { 0xff, D_20,B_16,D_36,B_32,0,0 },
        [INSTR_SSF_RRDRD] = { 0x00, D_20,B_16,D_36,B_32,R_8,0 },
+       [INSTR_SSF_RRDRD2]= { 0x00, R_8,D_20,B_16,D_36,B_32,0 },
        [INSTR_SS_L0RDRD] = { 0xff, D_20,L8_8,B_16,D_36,B_32,0 },
        [INSTR_SS_LIRDRD] = { 0xff, D_20,L4_8,B_16,D_36,B_32,U4_12 },
        [INSTR_SS_LLRDRD] = { 0xff, D_20,L4_8,B_16,D_36,L4_12,B_32 },
@@ -300,6 +305,36 @@ static const unsigned char formats[][7] = {
        [INSTR_S_RD]      = { 0xff, D_20,B_16,0,0,0,0 },
 };
 
+enum {
+       LONG_INSN_ALGHSIK,
+       LONG_INSN_ALHSIK,
+       LONG_INSN_CLFHSI,
+       LONG_INSN_CLGFRL,
+       LONG_INSN_CLGHRL,
+       LONG_INSN_CLGHSI,
+       LONG_INSN_CLHHSI,
+       LONG_INSN_LLGFRL,
+       LONG_INSN_LLGHRL,
+       LONG_INSN_POPCNT,
+       LONG_INSN_RISBHG,
+       LONG_INSN_RISBLG,
+};
+
+static char *long_insn_name[] = {
+       [LONG_INSN_ALGHSIK] = "alghsik",
+       [LONG_INSN_ALHSIK] = "alhsik",
+       [LONG_INSN_CLFHSI] = "clfhsi",
+       [LONG_INSN_CLGFRL] = "clgfrl",
+       [LONG_INSN_CLGHRL] = "clghrl",
+       [LONG_INSN_CLGHSI] = "clghsi",
+       [LONG_INSN_CLHHSI] = "clhhsi",
+       [LONG_INSN_LLGFRL] = "llgfrl",
+       [LONG_INSN_LLGHRL] = "llghrl",
+       [LONG_INSN_POPCNT] = "popcnt",
+       [LONG_INSN_RISBHG] = "risbhg",
+       [LONG_INSN_RISBLG] = "risblk",
+};
+
 static struct insn opcode[] = {
 #ifdef CONFIG_64BIT
        { "lmd", 0xef, INSTR_SS_RRRDRD3 },
@@ -881,6 +916,35 @@ static struct insn opcode_b9[] = {
        { "pfmf", 0xaf, INSTR_RRE_RR },
        { "trte", 0xbf, INSTR_RRF_M0RR },
        { "trtre", 0xbd, INSTR_RRF_M0RR },
+       { "ahhhr", 0xc8, INSTR_RRF_R0RR2 },
+       { "shhhr", 0xc9, INSTR_RRF_R0RR2 },
+       { "alhhh", 0xca, INSTR_RRF_R0RR2 },
+       { "alhhl", 0xca, INSTR_RRF_R0RR2 },
+       { "slhhh", 0xcb, INSTR_RRF_R0RR2 },
+       { "chhr ", 0xcd, INSTR_RRE_RR },
+       { "clhhr", 0xcf, INSTR_RRE_RR },
+       { "ahhlr", 0xd8, INSTR_RRF_R0RR2 },
+       { "shhlr", 0xd9, INSTR_RRF_R0RR2 },
+       { "slhhl", 0xdb, INSTR_RRF_R0RR2 },
+       { "chlr", 0xdd, INSTR_RRE_RR },
+       { "clhlr", 0xdf, INSTR_RRE_RR },
+       { { 0, LONG_INSN_POPCNT }, 0xe1, INSTR_RRE_RR },
+       { "locgr", 0xe2, INSTR_RRF_M0RR },
+       { "ngrk", 0xe4, INSTR_RRF_R0RR2 },
+       { "ogrk", 0xe6, INSTR_RRF_R0RR2 },
+       { "xgrk", 0xe7, INSTR_RRF_R0RR2 },
+       { "agrk", 0xe8, INSTR_RRF_R0RR2 },
+       { "sgrk", 0xe9, INSTR_RRF_R0RR2 },
+       { "algrk", 0xea, INSTR_RRF_R0RR2 },
+       { "slgrk", 0xeb, INSTR_RRF_R0RR2 },
+       { "locr", 0xf2, INSTR_RRF_M0RR },
+       { "nrk", 0xf4, INSTR_RRF_R0RR2 },
+       { "ork", 0xf6, INSTR_RRF_R0RR2 },
+       { "xrk", 0xf7, INSTR_RRF_R0RR2 },
+       { "ark", 0xf8, INSTR_RRF_R0RR2 },
+       { "srk", 0xf9, INSTR_RRF_R0RR2 },
+       { "alrk", 0xfa, INSTR_RRF_R0RR2 },
+       { "slrk", 0xfb, INSTR_RRF_R0RR2 },
 #endif
        { "kmac", 0x1e, INSTR_RRE_RR },
        { "lrvr", 0x1f, INSTR_RRE_RR },
@@ -949,9 +1013,9 @@ static struct insn opcode_c4[] = {
        { "lgfrl", 0x0c, INSTR_RIL_RP },
        { "lhrl", 0x05, INSTR_RIL_RP },
        { "lghrl", 0x04, INSTR_RIL_RP },
-       { "llgfrl", 0x0e, INSTR_RIL_RP },
+       { { 0, LONG_INSN_LLGFRL }, 0x0e, INSTR_RIL_RP },
        { "llhrl", 0x02, INSTR_RIL_RP },
-       { "llghrl", 0x06, INSTR_RIL_RP },
+       { { 0, LONG_INSN_LLGHRL }, 0x06, INSTR_RIL_RP },
        { "strl", 0x0f, INSTR_RIL_RP },
        { "stgrl", 0x0b, INSTR_RIL_RP },
        { "sthrl", 0x07, INSTR_RIL_RP },
@@ -968,9 +1032,9 @@ static struct insn opcode_c6[] = {
        { "cghrl", 0x04, INSTR_RIL_RP },
        { "clrl", 0x0f, INSTR_RIL_RP },
        { "clgrl", 0x0a, INSTR_RIL_RP },
-       { "clgfrl", 0x0e, INSTR_RIL_RP },
+       { { 0, LONG_INSN_CLGFRL }, 0x0e, INSTR_RIL_RP },
        { "clhrl", 0x07, INSTR_RIL_RP },
-       { "clghrl", 0x06, INSTR_RIL_RP },
+       { { 0, LONG_INSN_CLGHRL }, 0x06, INSTR_RIL_RP },
        { "pfdrl", 0x02, INSTR_RIL_UP },
        { "exrl", 0x00, INSTR_RIL_RP },
 #endif
@@ -982,6 +1046,20 @@ static struct insn opcode_c8[] = {
        { "mvcos", 0x00, INSTR_SSF_RRDRD },
        { "ectg", 0x01, INSTR_SSF_RRDRD },
        { "csst", 0x02, INSTR_SSF_RRDRD },
+       { "lpd", 0x04, INSTR_SSF_RRDRD2 },
+       { "lpdg ", 0x05, INSTR_SSF_RRDRD2 },
+#endif
+       { "", 0, INSTR_INVALID }
+};
+
+static struct insn opcode_cc[] = {
+#ifdef CONFIG_64BIT
+       { "brcth", 0x06, INSTR_RIL_RP },
+       { "aih", 0x08, INSTR_RIL_RI },
+       { "alsih", 0x0a, INSTR_RIL_RI },
+       { "alsih", 0x0b, INSTR_RIL_RI },
+       { "cih", 0x0d, INSTR_RIL_RI },
+       { "clih ", 0x0f, INSTR_RIL_RI },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1063,6 +1141,16 @@ static struct insn opcode_e3[] = {
        { "mfy", 0x5c, INSTR_RXY_RRRD },
        { "mhy", 0x7c, INSTR_RXY_RRRD },
        { "pfd", 0x36, INSTR_RXY_URRD },
+       { "lbh", 0xc0, INSTR_RXY_RRRD },
+       { "llch", 0xc2, INSTR_RXY_RRRD },
+       { "stch", 0xc3, INSTR_RXY_RRRD },
+       { "lhh", 0xc4, INSTR_RXY_RRRD },
+       { "llhh", 0xc6, INSTR_RXY_RRRD },
+       { "sthh", 0xc7, INSTR_RXY_RRRD },
+       { "lfh", 0xca, INSTR_RXY_RRRD },
+       { "stfh", 0xcb, INSTR_RXY_RRRD },
+       { "chf", 0xcd, INSTR_RXY_RRRD },
+       { "clhf", 0xcf, INSTR_RXY_RRRD },
 #endif
        { "lrv", 0x1e, INSTR_RXY_RRRD },
        { "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1080,9 +1168,9 @@ static struct insn opcode_e5[] = {
        { "chhsi", 0x54, INSTR_SIL_RDI },
        { "chsi", 0x5c, INSTR_SIL_RDI },
        { "cghsi", 0x58, INSTR_SIL_RDI },
-       { "clhhsi", 0x55, INSTR_SIL_RDU },
-       { "clfhsi", 0x5d, INSTR_SIL_RDU },
-       { "clghsi", 0x59, INSTR_SIL_RDU },
+       { { 0, LONG_INSN_CLHHSI }, 0x55, INSTR_SIL_RDU },
+       { { 0, LONG_INSN_CLFHSI }, 0x5d, INSTR_SIL_RDU },
+       { { 0, LONG_INSN_CLGHSI }, 0x59, INSTR_SIL_RDU },
        { "mvhhi", 0x44, INSTR_SIL_RDI },
        { "mvhi", 0x4c, INSTR_SIL_RDI },
        { "mvghi", 0x48, INSTR_SIL_RDI },
@@ -1137,6 +1225,24 @@ static struct insn opcode_eb[] = {
        { "alsi", 0x6e, INSTR_SIY_IRD },
        { "algsi", 0x7e, INSTR_SIY_IRD },
        { "ecag", 0x4c, INSTR_RSY_RRRD },
+       { "srak", 0xdc, INSTR_RSY_RRRD },
+       { "slak", 0xdd, INSTR_RSY_RRRD },
+       { "srlk", 0xde, INSTR_RSY_RRRD },
+       { "sllk", 0xdf, INSTR_RSY_RRRD },
+       { "locg", 0xe2, INSTR_RSY_RDRM },
+       { "stocg", 0xe3, INSTR_RSY_RDRM },
+       { "lang", 0xe4, INSTR_RSY_RRRD },
+       { "laog", 0xe6, INSTR_RSY_RRRD },
+       { "laxg", 0xe7, INSTR_RSY_RRRD },
+       { "laag", 0xe8, INSTR_RSY_RRRD },
+       { "laalg", 0xea, INSTR_RSY_RRRD },
+       { "loc", 0xf2, INSTR_RSY_RDRM },
+       { "stoc", 0xf3, INSTR_RSY_RDRM },
+       { "lan", 0xf4, INSTR_RSY_RRRD },
+       { "lao", 0xf6, INSTR_RSY_RRRD },
+       { "lax", 0xf7, INSTR_RSY_RRRD },
+       { "laa", 0xf8, INSTR_RSY_RRRD },
+       { "laal", 0xfa, INSTR_RSY_RRRD },
 #endif
        { "rll", 0x1d, INSTR_RSY_RRRD },
        { "mvclu", 0x8e, INSTR_RSY_RRRD },
@@ -1172,6 +1278,12 @@ static struct insn opcode_ec[] = {
        { "rxsbg", 0x57, INSTR_RIE_RRUUU },
        { "rosbg", 0x56, INSTR_RIE_RRUUU },
        { "risbg", 0x55, INSTR_RIE_RRUUU },
+       { { 0, LONG_INSN_RISBLG }, 0x51, INSTR_RIE_RRUUU },
+       { { 0, LONG_INSN_RISBHG }, 0x5D, INSTR_RIE_RRUUU },
+       { "ahik", 0xd8, INSTR_RIE_RRI0 },
+       { "aghik", 0xd9, INSTR_RIE_RRI0 },
+       { { 0, LONG_INSN_ALHSIK }, 0xda, INSTR_RIE_RRI0 },
+       { { 0, LONG_INSN_ALGHSIK }, 0xdb, INSTR_RIE_RRI0 },
 #endif
        { "", 0, INSTR_INVALID }
 };
@@ -1321,6 +1433,9 @@ static struct insn *find_insn(unsigned char *code)
        case 0xc8:
                table = opcode_c8;
                break;
+       case 0xcc:
+               table = opcode_cc;
+               break;
        case 0xe3:
                table = opcode_e3;
                opfrag = code[5];
@@ -1367,7 +1482,11 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
        ptr = buffer;
        insn = find_insn(code);
        if (insn) {
-               ptr += sprintf(ptr, "%.5s\t", insn->name);
+               if (insn->name[0] == '\0')
+                       ptr += sprintf(ptr, "%s\t",
+                                      long_insn_name[(int) insn->name[1]]);
+               else
+                       ptr += sprintf(ptr, "%.5s\t", insn->name);
                /* Extract the operands. */
                separator = 0;
                for (ops = formats[insn->format] + 1, i = 0;
index c00856a..d149609 100644 (file)
@@ -208,7 +208,8 @@ static noinline __init void init_kernel_storage_key(void)
        end_pfn = PFN_UP(__pa(&_end));
 
        for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
-               page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+               page_set_storage_key(init_pfn << PAGE_SHIFT,
+                                    PAGE_DEFAULT_KEY, 0);
 }
 
 static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
@@ -255,13 +256,35 @@ static noinline __init void setup_lowcore_early(void)
        s390_base_pgm_handler_fn = early_pgm_check_handler;
 }
 
+static noinline __init void setup_facility_list(void)
+{
+       unsigned long nr;
+
+       S390_lowcore.stfl_fac_list = 0;
+       asm volatile(
+               "       .insn   s,0xb2b10000,0(0)\n" /* stfl */
+               "0:\n"
+               EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list));
+       memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
+       nr = 4;                         /* # bytes stored by stfl */
+       if (test_facility(7)) {
+               /* More facility bits available with stfle */
+               register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1;
+               asm volatile(".insn s,0xb2b00000,%0" /* stfle */
+                            : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0)
+                            : : "cc");
+               nr = (reg0 + 1) * 8;    /* # bytes stored by stfle */
+       }
+       memset((char *) S390_lowcore.stfle_fac_list + nr, 0,
+              MAX_FACILITY_BIT/8 - nr);
+}
+
 static noinline __init void setup_hpage(void)
 {
 #ifndef CONFIG_DEBUG_PAGEALLOC
        unsigned int facilities;
 
-       facilities = stfl();
-       if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29)))
+       if (!test_facility(2) || !test_facility(8))
                return;
        S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE;
        __ctl_set_bit(0, 23);
@@ -355,18 +378,15 @@ static __init void detect_diag44(void)
 static __init void detect_machine_facilities(void)
 {
 #ifdef CONFIG_64BIT
-       unsigned int facilities;
-       unsigned long long facility_bits;
-
-       facilities = stfl();
-       if (facilities & (1 << 28))
+       if (test_facility(3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
-       if (facilities & (1 << 23))
+       if (test_facility(8))
                S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
-       if (facilities & (1 << 4))
+       if (test_facility(11))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
+       if (test_facility(27))
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
-       if ((stfle(&facility_bits, 1) > 0) &&
-           (facility_bits & (1ULL << (63 - 40))))
+       if (test_facility(40))
                S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
 #endif
 }
@@ -447,6 +467,7 @@ void __init startup_init(void)
        lockdep_off();
        sort_main_extable();
        setup_lowcore_early();
+       setup_facility_list();
        detect_machine_type();
        ipl_update_parameters();
        setup_boot_command_line();
index bea9ee3..5efce72 100644 (file)
@@ -72,25 +72,9 @@ STACK_SIZE  = 1 << STACK_SHIFT
        l       %r1,BASED(.Ltrace_irq_off_caller)
        basr    %r14,%r1
        .endm
-
-       .macro  TRACE_IRQS_CHECK_ON
-       tm      SP_PSW(%r15),0x03       # irqs enabled?
-       bz      BASED(0f)
-       TRACE_IRQS_ON
-0:
-       .endm
-
-       .macro  TRACE_IRQS_CHECK_OFF
-       tm      SP_PSW(%r15),0x03       # irqs enabled?
-       bz      BASED(0f)
-       TRACE_IRQS_OFF
-0:
-       .endm
 #else
 #define TRACE_IRQS_ON
 #define TRACE_IRQS_OFF
-#define TRACE_IRQS_CHECK_ON
-#define TRACE_IRQS_CHECK_OFF
 #endif
 
 #ifdef CONFIG_LOCKDEP
@@ -198,6 +182,12 @@ STACK_SIZE  = 1 << STACK_SHIFT
        lpsw    \psworg                 # back to caller
        .endm
 
+       .macro REENABLE_IRQS
+       mvc     __SF_EMPTY(1,%r15),SP_PSW(%r15)
+       ni      __SF_EMPTY(%r15),0xbf
+       ssm     __SF_EMPTY(%r15)
+       .endm
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -264,12 +254,11 @@ sysc_do_svc:
        bnl     BASED(sysc_nr_ok)
        lr      %r7,%r1           # copy svc number to %r7
 sysc_nr_ok:
-       mvc     SP_ARGS(4,%r15),SP_R7(%r15)
-sysc_do_restart:
        sth     %r7,SP_SVCNR(%r15)
        sll     %r7,2             # svc number *4
        l       %r8,BASED(.Lsysc_table)
        tm      __TI_flags+2(%r9),_TIF_SYSCALL
+       mvc     SP_ARGS(4,%r15),SP_R7(%r15)
        l       %r8,0(%r7,%r8)    # get system call addr.
        bnz     BASED(sysc_tracesys)
        basr    %r14,%r8          # call sys_xxxx
@@ -357,7 +346,7 @@ sysc_restart:
        l       %r7,SP_R2(%r15)         # load new svc number
        mvc     SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
        lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
-       b       BASED(sysc_do_restart)  # restart svc
+       b       BASED(sysc_nr_ok)       # restart svc
 
 #
 # _TIF_SINGLE_STEP is set, call do_single_step
@@ -390,6 +379,7 @@ sysc_tracesys:
        l       %r8,0(%r7,%r8)
 sysc_tracego:
        lm      %r3,%r6,SP_R3(%r15)
+       mvc     SP_ARGS(4,%r15),SP_R7(%r15)
        l       %r2,SP_ORIG_R2(%r15)
        basr    %r14,%r8                # call sys_xxx
        st      %r2,SP_R2(%r15)         # store return value
@@ -440,13 +430,11 @@ kernel_execve:
        br      %r14
        # execve succeeded.
 0:     stnsm   __SF_EMPTY(%r15),0xfc   # disable interrupts
-       TRACE_IRQS_OFF
        l       %r15,__LC_KERNEL_STACK  # load ksp
        s       %r15,BASED(.Lc_spsize)  # make room for registers & psw
        l       %r9,__LC_THREAD_INFO
        mvc     SP_PTREGS(__PT_SIZE,%r15),0(%r12)       # copy pt_regs
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
-       TRACE_IRQS_ON
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        l       %r1,BASED(.Lexecve_tail)
        basr    %r14,%r1
@@ -483,9 +471,10 @@ pgm_check_handler:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime:
-       TRACE_IRQS_CHECK_OFF
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        l       %r3,__LC_PGM_ILC        # load program interruption code
+       l       %r4,__LC_TRANS_EXC_CODE
+       REENABLE_IRQS
        la      %r8,0x7f
        nr      %r8,%r3
 pgm_do_call:
@@ -495,7 +484,6 @@ pgm_do_call:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r7                # branch to interrupt-handler
 pgm_exit:
-       TRACE_IRQS_CHECK_ON
        b       BASED(sysc_return)
 
 #
@@ -523,7 +511,6 @@ pgm_per_std:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
 pgm_no_vtime2:
-       TRACE_IRQS_CHECK_OFF
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        l       %r1,__TI_task(%r9)
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
@@ -533,6 +520,8 @@ pgm_no_vtime2:
        mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
        oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
        l       %r3,__LC_PGM_ILC        # load program interruption code
+       l       %r4,__LC_TRANS_EXC_CODE
+       REENABLE_IRQS
        la      %r8,0x7f
        nr      %r8,%r3                 # clear per-event-bit and ilc
        be      BASED(pgm_exit2)        # only per or per+check ?
@@ -542,8 +531,6 @@ pgm_no_vtime2:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r7                # branch to interrupt-handler
 pgm_exit2:
-       TRACE_IRQS_ON
-       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        b       BASED(sysc_return)
 
 #
@@ -557,13 +544,11 @@ pgm_svcper:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        lh      %r7,0x8a                # get svc number from lowcore
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
-       TRACE_IRQS_OFF
        l       %r8,__TI_task(%r9)
        mvc     __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
        mvc     __THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
        oi      __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-       TRACE_IRQS_ON
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        lm      %r2,%r6,SP_R2(%r15)     # load svc arguments
        b       BASED(sysc_do_svc)
@@ -737,7 +722,8 @@ ext_no_vtime:
        l       %r9,__LC_THREAD_INFO    # load pointer to thread_info struct
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
-       lh      %r3,__LC_EXT_INT_CODE   # get interruption code
+       l       %r3,__LC_CPU_ADDRESS    # get cpu address + interruption code
+       l       %r4,__LC_EXT_PARAMS     # get external parameters
        l       %r1,BASED(.Ldo_extint)
        basr    %r14,%r1
        b       BASED(io_return)
index ff579b6..95c1dfc 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 
-typedef void pgm_check_handler_t(struct pt_regs *, long);
+typedef void pgm_check_handler_t(struct pt_regs *, long, unsigned long);
 extern pgm_check_handler_t *pgm_check_table[128];
 pgm_check_handler_t do_protection_exception;
 pgm_check_handler_t do_dat_exception;
@@ -19,7 +19,7 @@ void do_signal(struct pt_regs *regs);
 int handle_signal32(unsigned long sig, struct k_sigaction *ka,
                    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
 
-void do_extint(struct pt_regs *regs, unsigned short code);
+void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
 int __cpuinit start_secondary(void *cpuvoid);
 void __init startup_init(void);
 void die(const char * str, struct pt_regs * regs, long err);
index 8bccec1..a2be239 100644 (file)
@@ -79,25 +79,9 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
        basr    %r2,%r0
        brasl   %r14,trace_hardirqs_off_caller
        .endm
-
-       .macro TRACE_IRQS_CHECK_ON
-       tm      SP_PSW(%r15),0x03       # irqs enabled?
-       jz      0f
-       TRACE_IRQS_ON
-0:
-       .endm
-
-       .macro TRACE_IRQS_CHECK_OFF
-       tm      SP_PSW(%r15),0x03       # irqs enabled?
-       jz      0f
-       TRACE_IRQS_OFF
-0:
-       .endm
 #else
 #define TRACE_IRQS_ON
 #define TRACE_IRQS_OFF
-#define TRACE_IRQS_CHECK_ON
-#define TRACE_IRQS_CHECK_OFF
 #endif
 
 #ifdef CONFIG_LOCKDEP
@@ -207,6 +191,12 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
 0:
        .endm
 
+       .macro REENABLE_IRQS
+       mvc     __SF_EMPTY(1,%r15),SP_PSW(%r15)
+       ni      __SF_EMPTY(%r15),0xbf
+       ssm     __SF_EMPTY(%r15)
+       .endm
+
 /*
  * Scheduler resume function, called by switch_to
  *  gpr2 = (task_struct *) prev
@@ -256,7 +246,6 @@ sysc_saveall:
        CREATE_STACK_FRAME __LC_SAVE_AREA
        mvc     SP_PSW(16,%r15),__LC_SVC_OLD_PSW
        mvc     SP_ILC(4,%r15),__LC_SVC_ILC
-       stg     %r7,SP_ARGS(%r15)
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
 sysc_vtime:
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -284,6 +273,7 @@ sysc_nr_ok:
 sysc_noemu:
 #endif
        tm      __TI_flags+6(%r12),_TIF_SYSCALL
+       mvc     SP_ARGS(8,%r15),SP_R7(%r15)
        lgf     %r8,0(%r7,%r10) # load address of system call routine
        jnz     sysc_tracesys
        basr    %r14,%r8        # call sys_xxxx
@@ -397,6 +387,7 @@ sysc_tracesys:
        lgf     %r8,0(%r7,%r10)
 sysc_tracego:
        lmg     %r3,%r6,SP_R3(%r15)
+       mvc     SP_ARGS(8,%r15),SP_R7(%r15)
        lg      %r2,SP_ORIG_R2(%r15)
        basr    %r14,%r8                # call sys_xxx
        stg     %r2,SP_R2(%r15)         # store return value
@@ -443,14 +434,12 @@ kernel_execve:
        br      %r14
        # execve succeeded.
 0:     stnsm   __SF_EMPTY(%r15),0xfc   # disable interrupts
-#      TRACE_IRQS_OFF
        lg      %r15,__LC_KERNEL_STACK  # load ksp
        aghi    %r15,-SP_SIZE           # make room for registers & psw
        lg      %r13,__LC_SVC_NEW_PSW+8
        mvc     SP_PTREGS(__PT_SIZE,%r15),0(%r12)       # copy pt_regs
        lg      %r12,__LC_THREAD_INFO
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
-#      TRACE_IRQS_ON
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        brasl   %r14,execve_tail
        j       sysc_return
@@ -490,19 +479,18 @@ pgm_check_handler:
        LAST_BREAK
 pgm_no_vtime:
        HANDLE_SIE_INTERCEPT
-       TRACE_IRQS_CHECK_OFF
        stg     %r11,SP_ARGS(%r15)
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
+       lg      %r4,__LC_TRANS_EXC_CODE
+       REENABLE_IRQS
        lghi    %r8,0x7f
        ngr     %r8,%r3
-pgm_do_call:
        sll     %r8,3
        larl    %r1,pgm_check_table
        lg      %r1,0(%r8,%r1)          # load address of handler routine
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r1                # branch to interrupt-handler
 pgm_exit:
-       TRACE_IRQS_CHECK_ON
        j       sysc_return
 
 #
@@ -533,7 +521,6 @@ pgm_per_std:
        LAST_BREAK
 pgm_no_vtime2:
        HANDLE_SIE_INTERCEPT
-       TRACE_IRQS_CHECK_OFF
        lg      %r1,__TI_task(%r12)
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
        jz      kernel_per
@@ -542,6 +529,8 @@ pgm_no_vtime2:
        mvc     __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
        oi      __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
+       lg      %r4,__LC_TRANS_EXC_CODE
+       REENABLE_IRQS
        lghi    %r8,0x7f
        ngr     %r8,%r3                 # clear per-event-bit and ilc
        je      pgm_exit2
@@ -551,8 +540,6 @@ pgm_no_vtime2:
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        basr    %r14,%r1                # branch to interrupt-handler
 pgm_exit2:
-       TRACE_IRQS_ON
-       stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        j       sysc_return
 
 #
@@ -568,13 +555,11 @@ pgm_svcper:
        UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        LAST_BREAK
-       TRACE_IRQS_OFF
        lg      %r8,__TI_task(%r12)
        mvc     __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
        mvc     __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS
        mvc     __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
        oi      __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-       TRACE_IRQS_ON
        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
        lmg     %r2,%r6,SP_R2(%r15)     # load svc arguments
        j       sysc_do_svc
@@ -743,8 +728,11 @@ ext_int_handler:
 ext_no_vtime:
        HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
+       lghi    %r1,4096
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
-       llgh    %r3,__LC_EXT_INT_CODE   # get interruption code
+       llgf    %r3,__LC_CPU_ADDRESS    # get cpu address + interruption code
+       llgf    %r4,__LC_EXT_PARAMS     # get external parameter
+       lg      %r5,__LC_EXT_PARAMS2-4096(%r1)  # get 64 bit external parameter
        brasl   %r14,do_extint
        j       io_return
 
@@ -966,7 +954,6 @@ cleanup_system_call:
        CREATE_STACK_FRAME __LC_SAVE_AREA
        mvc     SP_PSW(16,%r15),__LC_SVC_OLD_PSW
        mvc     SP_ILC(4,%r15),__LC_SVC_ILC
-       stg     %r7,SP_ARGS(%r15)
        mvc     8(8,%r12),__LC_THREAD_INFO
 cleanup_vtime:
        clc     __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
index db1696e..7061398 100644 (file)
@@ -488,7 +488,9 @@ startup:
        .align 16
 2:     .long   0x000a0000,0x8badcccc
 #if defined(CONFIG_64BIT)
-#if defined(CONFIG_MARCH_Z10)
+#if defined(CONFIG_MARCH_Z196)
+       .long 0xc100efe3, 0xf46c0000
+#elif defined(CONFIG_MARCH_Z10)
        .long 0xc100efe3, 0xf0680000
 #elif defined(CONFIG_MARCH_Z9_109)
        .long 0xc100efc3, 0x00000000
@@ -498,7 +500,9 @@ startup:
        .long 0xc0000000, 0x00000000
 #endif
 #else
-#if defined(CONFIG_MARCH_Z10)
+#if defined(CONFIG_MARCH_Z196)
+       .long 0x8100c880, 0x00000000
+#elif defined(CONFIG_MARCH_Z10)
        .long 0x8100c880, 0x00000000
 #elif defined(CONFIG_MARCH_Z9_109)
        .long 0x8100c880, 0x00000000
index d3a2d1c..ec2e03b 100644 (file)
@@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 static void default_idle(void)
 {
        /* CPU is going idle. */
-       local_irq_disable();
-       if (need_resched()) {
-               local_irq_enable();
-               return;
-       }
 #ifdef CONFIG_HOTPLUG_CPU
        if (cpu_is_offline(smp_processor_id())) {
                preempt_enable_no_resched();
                cpu_die();
        }
 #endif
+       local_irq_disable();
+       if (need_resched()) {
+               local_irq_enable();
+               return;
+       }
        local_mcck_disable();
        if (test_thread_flag(TIF_MCCK_PENDING)) {
                local_mcck_enable();
index ecb2d02..644548e 100644 (file)
@@ -42,7 +42,7 @@ void __cpuinit print_cpu_info(void)
        struct cpuid *id = &per_cpu(cpu_id, smp_processor_id());
 
        pr_info("Processor %d started, address %d, identification %06X\n",
-               S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, id->ident);
+               S390_lowcore.cpu_nr, stap(), id->ident);
 }
 
 /*
index 9ce641b..bd1db50 100644 (file)
@@ -113,12 +113,15 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
        return 0;
 }
 
-void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
+void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
+                          unsigned int param32, unsigned long param64)
 {
+       struct pt_regs *old_regs;
+       unsigned short code;
         ext_int_info_t *p;
         int index;
-       struct pt_regs *old_regs;
 
+       code = (unsigned short) ext_int_code;
        old_regs = set_irq_regs(regs);
        s390_idle_check(regs, S390_lowcore.int_clock,
                        S390_lowcore.async_enter_timer);
@@ -132,7 +135,7 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code)
         index = ext_hash(code);
        for (p = ext_int_hash[index]; p; p = p->next) {
                if (likely(p->code == code))
-                       p->handler(code);
+                       p->handler(ext_int_code, param32, param64);
        }
        irq_exit();
        set_irq_regs(old_regs);
index c8e8e13..e3ceb91 100644 (file)
@@ -409,6 +409,9 @@ setup_lowcore(void)
        lc->current_task = (unsigned long) init_thread_union.thread_info.task;
        lc->thread_info = (unsigned long) &init_thread_union;
        lc->machine_flags = S390_lowcore.machine_flags;
+       lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
+       memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
+              MAX_FACILITY_BIT/8);
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE) {
                lc->extended_save_area_addr = (__u32)
@@ -627,7 +630,8 @@ setup_memory(void)
                add_active_range(0, start_chunk, end_chunk);
                pfn = max(start_chunk, start_pfn);
                for (; pfn < end_chunk; pfn++)
-                       page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
+                       page_set_storage_key(PFN_PHYS(pfn),
+                                            PAGE_DEFAULT_KEY, 0);
        }
 
        psw_set_key(PAGE_DEFAULT_KEY);
@@ -674,12 +678,9 @@ setup_memory(void)
 static void __init setup_hwcaps(void)
 {
        static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
-       unsigned long long facility_list_extended;
-       unsigned int facility_list;
        struct cpuid cpu_id;
        int i;
 
-       facility_list = stfl();
        /*
         * The store facility list bits numbers as found in the principles
         * of operation are numbered with bit 1UL<<31 as number 0 to
@@ -699,11 +700,10 @@ static void __init setup_hwcaps(void)
         *   HWCAP_S390_ETF3EH bit 8 (22 && 30).
         */
        for (i = 0; i < 6; i++)
-               if (facility_list & (1UL << (31 - stfl_bits[i])))
+               if (test_facility(stfl_bits[i]))
                        elf_hwcap |= 1UL << i;
 
-       if ((facility_list & (1UL << (31 - 22)))
-           && (facility_list & (1UL << (31 - 30))))
+       if (test_facility(22) && test_facility(30))
                elf_hwcap |= HWCAP_S390_ETF3EH;
 
        /*
@@ -719,12 +719,8 @@ static void __init setup_hwcaps(void)
         * translated to:
         *   HWCAP_S390_DFP bit 6 (42 && 44).
         */
-       if ((elf_hwcap & (1UL << 2)) &&
-           __stfle(&facility_list_extended, 1) > 0) {
-               if ((facility_list_extended & (1ULL << (63 - 42)))
-                   && (facility_list_extended & (1ULL << (63 - 44))))
-                       elf_hwcap |= HWCAP_S390_DFP;
-       }
+       if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44))
+               elf_hwcap |= HWCAP_S390_DFP;
 
        /*
         * Huge page support HWCAP_S390_HPAGE is bit 7.
index 8127ebd..94cf510 100644 (file)
@@ -156,7 +156,8 @@ void smp_send_stop(void)
  * cpus are handled.
  */
 
-static void do_ext_call_interrupt(__u16 code)
+static void do_ext_call_interrupt(unsigned int ext_int_code,
+                                 unsigned int param32, unsigned long param64)
 {
        unsigned long bits;
 
@@ -593,6 +594,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
        cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;
        cpu_lowcore->machine_flags = S390_lowcore.machine_flags;
        cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
+       memcpy(cpu_lowcore->stfle_fac_list, S390_lowcore.stfle_fac_list,
+              MAX_FACILITY_BIT/8);
        eieio();
 
        while (sigp(cpu, sigp_restart) == sigp_busy)
index a0ffc77..f04d93a 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/ebcdic.h>
 #include <asm/sysinfo.h>
 #include <asm/cpcmd.h>
+#include <asm/topology.h>
 
 /* Sigh, math-emu. Don't ask. */
 #include <asm/sfp-util.h>
@@ -74,6 +75,42 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
                               "Model Temp. Capacity: %-16.16s %08u\n",
                               info->model_temp_cap,
                               *(u32 *) info->model_temp_cap_rating);
+       if (info->cai) {
+               len += sprintf(page + len,
+                              "Capacity Adj. Ind.:   %d\n",
+                              info->cai);
+               len += sprintf(page + len, "Capacity Ch. Reason:  %d\n",
+                              info->ccr);
+       }
+       return len;
+}
+
+static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
+{
+       static int max_mnest;
+       int i, rc;
+
+       len += sprintf(page + len, "\n");
+       if (!MACHINE_HAS_TOPOLOGY)
+               return len;
+       if (max_mnest) {
+               stsi(info, 15, 1, max_mnest);
+       } else {
+               for (max_mnest = 6; max_mnest > 1; max_mnest--) {
+                       rc = stsi(info, 15, 1, max_mnest);
+                       if (rc != -ENOSYS)
+                               break;
+               }
+       }
+       len += sprintf(page + len, "CPU Topology HW:     ");
+       for (i = 0; i < TOPOLOGY_NR_MAG; i++)
+               len += sprintf(page + len, " %d", info->mag[i]);
+       len += sprintf(page + len, "\n");
+       store_topology(info);
+       len += sprintf(page + len, "CPU Topology SW:     ");
+       for (i = 0; i < TOPOLOGY_NR_MAG; i++)
+               len += sprintf(page + len, " %d", info->mag[i]);
+       len += sprintf(page + len, "\n");
        return len;
 }
 
@@ -87,7 +124,6 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
        ext = (struct sysinfo_1_2_2_extension *)
                ((unsigned long) info + info->acc_offset);
 
-       len += sprintf(page + len, "\n");
        len += sprintf(page + len, "CPUs Total:           %d\n",
                       info->cpus_total);
        len += sprintf(page + len, "CPUs Configured:      %d\n",
@@ -217,6 +253,9 @@ static int proc_read_sysinfo(char *page, char **start,
                len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len);
 
        if (level >= 1)
+               len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len);
+
+       if (level >= 1)
                len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len);
 
        if (level >= 2)
index 2896cac..f754a6d 100644 (file)
@@ -155,7 +155,9 @@ void init_cpu_timer(void)
        __ctl_set_bit(0, 4);
 }
 
-static void clock_comparator_interrupt(__u16 code)
+static void clock_comparator_interrupt(unsigned int ext_int_code,
+                                      unsigned int param32,
+                                      unsigned long param64)
 {
        if (S390_lowcore.clock_comparator == -1ULL)
                set_clock_comparator(S390_lowcore.clock_comparator);
@@ -164,14 +166,13 @@ static void clock_comparator_interrupt(__u16 code)
 static void etr_timing_alert(struct etr_irq_parm *);
 static void stp_timing_alert(struct stp_irq_parm *);
 
-static void timing_alert_interrupt(__u16 code)
+static void timing_alert_interrupt(unsigned int ext_int_code,
+                                  unsigned int param32, unsigned long param64)
 {
-       if (S390_lowcore.ext_params & 0x00c40000)
-               etr_timing_alert((struct etr_irq_parm *)
-                                &S390_lowcore.ext_params);
-       if (S390_lowcore.ext_params & 0x00038000)
-               stp_timing_alert((struct stp_irq_parm *)
-                                &S390_lowcore.ext_params);
+       if (param32 & 0x00c40000)
+               etr_timing_alert((struct etr_irq_parm *) &param32);
+       if (param32 & 0x00038000)
+               stp_timing_alert((struct stp_irq_parm *) &param32);
 }
 
 static void etr_reset(void);
index 13559c9..a9dee90 100644 (file)
 #include <linux/cpuset.h>
 #include <asm/delay.h>
 #include <asm/s390_ext.h>
-#include <asm/sysinfo.h>
-
-#define CPU_BITS 64
-#define NR_MAG 6
 
 #define PTF_HORIZONTAL (0UL)
 #define PTF_VERTICAL   (1UL)
 #define PTF_CHECK      (2UL)
 
-struct tl_cpu {
-       unsigned char reserved0[4];
-       unsigned char :6;
-       unsigned char pp:2;
-       unsigned char reserved1;
-       unsigned short origin;
-       unsigned long mask[CPU_BITS / BITS_PER_LONG];
-};
-
-struct tl_container {
-       unsigned char reserved[7];
-       unsigned char id;
-};
-
-union tl_entry {
-       unsigned char nl;
-       struct tl_cpu cpu;
-       struct tl_container container;
-};
-
-struct tl_info {
-       unsigned char reserved0[2];
-       unsigned short length;
-       unsigned char mag[NR_MAG];
-       unsigned char reserved1;
-       unsigned char mnest;
-       unsigned char reserved2[4];
-       union tl_entry tle[0];
-};
-
 struct mask_info {
        struct mask_info *next;
        unsigned char id;
        cpumask_t mask;
 };
 
-static int topology_enabled;
+static int topology_enabled = 1;
 static void topology_work_fn(struct work_struct *work);
-static struct tl_info *tl_info;
-static int machine_has_topology;
+static struct sysinfo_15_1_x *tl_info;
 static struct timer_list topology_timer;
 static void set_topology_timer(void);
 static DECLARE_WORK(topology_work, topology_work_fn);
@@ -88,7 +53,7 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        cpumask_t mask;
 
        cpus_clear(mask);
-       if (!topology_enabled || !machine_has_topology)
+       if (!topology_enabled || !MACHINE_HAS_TOPOLOGY)
                return cpu_possible_map;
        while (info) {
                if (cpu_isset(cpu, info->mask)) {
@@ -102,18 +67,18 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        return mask;
 }
 
-static void add_cpus_to_mask(struct tl_cpu *tl_cpu, struct mask_info *book,
-                            struct mask_info *core)
+static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
+                            struct mask_info *book, struct mask_info *core)
 {
        unsigned int cpu;
 
-       for (cpu = find_first_bit(&tl_cpu->mask[0], CPU_BITS);
-            cpu < CPU_BITS;
-            cpu = find_next_bit(&tl_cpu->mask[0], CPU_BITS, cpu + 1))
+       for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS);
+            cpu < TOPOLOGY_CPU_BITS;
+            cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1))
        {
                unsigned int rcpu, lcpu;
 
-               rcpu = CPU_BITS - 1 - cpu + tl_cpu->origin;
+               rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
                for_each_present_cpu(lcpu) {
                        if (cpu_logical_map(lcpu) != rcpu)
                                continue;
@@ -146,15 +111,14 @@ static void clear_masks(void)
 #endif
 }
 
-static union tl_entry *next_tle(union tl_entry *tle)
+static union topology_entry *next_tle(union topology_entry *tle)
 {
-       if (tle->nl)
-               return (union tl_entry *)((struct tl_container *)tle + 1);
-       else
-               return (union tl_entry *)((struct tl_cpu *)tle + 1);
+       if (!tle->nl)
+               return (union topology_entry *)((struct topology_cpu *)tle + 1);
+       return (union topology_entry *)((struct topology_container *)tle + 1);
 }
 
-static void tl_to_cores(struct tl_info *info)
+static void tl_to_cores(struct sysinfo_15_1_x *info)
 {
 #ifdef CONFIG_SCHED_BOOK
        struct mask_info *book = &book_info;
@@ -162,13 +126,13 @@ static void tl_to_cores(struct tl_info *info)
        struct mask_info *book = NULL;
 #endif
        struct mask_info *core = &core_info;
-       union tl_entry *tle, *end;
+       union topology_entry *tle, *end;
 
 
        spin_lock_irq(&topology_lock);
        clear_masks();
        tle = info->tle;
-       end = (union tl_entry *)((unsigned long)info + info->length);
+       end = (union topology_entry *)((unsigned long)info + info->length);
        while (tle < end) {
                switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
@@ -186,7 +150,6 @@ static void tl_to_cores(struct tl_info *info)
                        break;
                default:
                        clear_masks();
-                       machine_has_topology = 0;
                        goto out;
                }
                tle = next_tle(tle);
@@ -223,7 +186,7 @@ int topology_set_cpu_management(int fc)
        int cpu;
        int rc;
 
-       if (!machine_has_topology)
+       if (!MACHINE_HAS_TOPOLOGY)
                return -EOPNOTSUPP;
        if (fc)
                rc = ptf(PTF_VERTICAL);
@@ -251,7 +214,7 @@ static void update_cpu_core_map(void)
        spin_unlock_irqrestore(&topology_lock, flags);
 }
 
-static void store_topology(struct tl_info *info)
+void store_topology(struct sysinfo_15_1_x *info)
 {
 #ifdef CONFIG_SCHED_BOOK
        int rc;
@@ -265,11 +228,11 @@ static void store_topology(struct tl_info *info)
 
 int arch_update_cpu_topology(void)
 {
-       struct tl_info *info = tl_info;
+       struct sysinfo_15_1_x *info = tl_info;
        struct sys_device *sysdev;
        int cpu;
 
-       if (!machine_has_topology) {
+       if (!MACHINE_HAS_TOPOLOGY) {
                update_cpu_core_map();
                topology_update_polarization_simple();
                return 0;
@@ -311,9 +274,9 @@ static void set_topology_timer(void)
 
 static int __init early_parse_topology(char *p)
 {
-       if (strncmp(p, "on", 2))
+       if (strncmp(p, "off", 3))
                return 0;
-       topology_enabled = 1;
+       topology_enabled = 0;
        return 0;
 }
 early_param("topology", early_parse_topology);
@@ -323,7 +286,7 @@ static int __init init_topology_update(void)
        int rc;
 
        rc = 0;
-       if (!machine_has_topology) {
+       if (!MACHINE_HAS_TOPOLOGY) {
                topology_update_polarization_simple();
                goto out;
        }
@@ -335,13 +298,14 @@ out:
 }
 __initcall(init_topology_update);
 
-static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset)
+static void alloc_masks(struct sysinfo_15_1_x *info, struct mask_info *mask,
+                       int offset)
 {
        int i, nr_masks;
 
-       nr_masks = info->mag[NR_MAG - offset];
+       nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
        for (i = 0; i < info->mnest - offset; i++)
-               nr_masks *= info->mag[NR_MAG - offset - 1 - i];
+               nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
        nr_masks = max(nr_masks, 1);
        for (i = 0; i < nr_masks; i++) {
                mask->next = alloc_bootmem(sizeof(struct mask_info));
@@ -351,21 +315,16 @@ static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset
 
 void __init s390_init_cpu_topology(void)
 {
-       unsigned long long facility_bits;
-       struct tl_info *info;
+       struct sysinfo_15_1_x *info;
        int i;
 
-       if (stfle(&facility_bits, 1) <= 0)
-               return;
-       if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61)))
+       if (!MACHINE_HAS_TOPOLOGY)
                return;
-       machine_has_topology = 1;
-
        tl_info = alloc_bootmem_pages(PAGE_SIZE);
        info = tl_info;
        store_topology(info);
        pr_info("The CPU configuration topology of the machine is:");
-       for (i = 0; i < NR_MAG; i++)
+       for (i = 0; i < TOPOLOGY_NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
        alloc_masks(info, &core_info, 2);
index 5d8f0f3..7064082 100644 (file)
@@ -329,27 +329,19 @@ int is_valid_bugaddr(unsigned long addr)
        return 1;
 }
 
-static void __kprobes inline do_trap(long interruption_code, int signr,
-                                       char *str, struct pt_regs *regs,
-                                       siginfo_t *info)
+static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str,
+                                    struct pt_regs *regs, siginfo_t *info)
 {
-       /*
-        * We got all needed information from the lowcore and can
-        * now safely switch on interrupts.
-        */
-        if (regs->psw.mask & PSW_MASK_PSTATE)
-               local_irq_enable();
-
-       if (notify_die(DIE_TRAP, str, regs, interruption_code,
-                               interruption_code, signr) == NOTIFY_STOP)
+       if (notify_die(DIE_TRAP, str, regs, pgm_int_code,
+                      pgm_int_code, signr) == NOTIFY_STOP)
                return;
 
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                 struct task_struct *tsk = current;
 
-                tsk->thread.trap_no = interruption_code & 0xffff;
+               tsk->thread.trap_no = pgm_int_code & 0xffff;
                force_sig_info(signr, info, tsk);
-               report_user_fault(regs, interruption_code, signr);
+               report_user_fault(regs, pgm_int_code, signr);
         } else {
                 const struct exception_table_entry *fixup;
                 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
@@ -361,14 +353,16 @@ static void __kprobes inline do_trap(long interruption_code, int signr,
                        btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
                        if (btt == BUG_TRAP_TYPE_WARN)
                                return;
-                       die(str, regs, interruption_code);
+                       die(str, regs, pgm_int_code);
                }
         }
 }
 
-static inline void __user *get_check_address(struct pt_regs *regs)
+static inline void __user *get_psw_address(struct pt_regs *regs,
+                                          long pgm_int_code)
 {
-       return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
+       return (void __user *)
+               ((regs->psw.addr - (pgm_int_code >> 16)) & PSW_ADDR_INSN);
 }
 
 void __kprobes do_single_step(struct pt_regs *regs)
@@ -381,57 +375,57 @@ void __kprobes do_single_step(struct pt_regs *regs)
                force_sig(SIGTRAP, current);
 }
 
-static void default_trap_handler(struct pt_regs * regs, long interruption_code)
+static void default_trap_handler(struct pt_regs *regs, long pgm_int_code,
+                                unsigned long trans_exc_code)
 {
         if (regs->psw.mask & PSW_MASK_PSTATE) {
-               local_irq_enable();
-               report_user_fault(regs, interruption_code, SIGSEGV);
+               report_user_fault(regs, pgm_int_code, SIGSEGV);
                do_exit(SIGSEGV);
        } else
-               die("Unknown program exception", regs, interruption_code);
+               die("Unknown program exception", regs, pgm_int_code);
 }
 
-#define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
-static void name(struct pt_regs * regs, long interruption_code) \
+#define DO_ERROR_INFO(name, signr, sicode, str) \
+static void name(struct pt_regs *regs, long pgm_int_code, \
+                unsigned long trans_exc_code) \
 { \
         siginfo_t info; \
         info.si_signo = signr; \
         info.si_errno = 0; \
         info.si_code = sicode; \
-       info.si_addr = siaddr; \
-        do_trap(interruption_code, signr, str, regs, &info); \
+       info.si_addr = get_psw_address(regs, pgm_int_code); \
+       do_trap(pgm_int_code, signr, str, regs, &info);     \
 }
 
-DO_ERROR_INFO(SIGILL, "addressing exception", addressing_exception,
-             ILL_ILLADR, get_check_address(regs))
-DO_ERROR_INFO(SIGILL,  "execute exception", execute_exception,
-             ILL_ILLOPN, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "fixpoint divide exception", divide_exception,
-             FPE_INTDIV, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "fixpoint overflow exception", overflow_exception,
-             FPE_INTOVF, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "HFP overflow exception", hfp_overflow_exception,
-             FPE_FLTOVF, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "HFP underflow exception", hfp_underflow_exception,
-             FPE_FLTUND, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "HFP significance exception", hfp_significance_exception,
-             FPE_FLTRES, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "HFP divide exception", hfp_divide_exception,
-             FPE_FLTDIV, get_check_address(regs))
-DO_ERROR_INFO(SIGFPE,  "HFP square root exception", hfp_sqrt_exception,
-             FPE_FLTINV, get_check_address(regs))
-DO_ERROR_INFO(SIGILL,  "operand exception", operand_exception,
-             ILL_ILLOPN, get_check_address(regs))
-DO_ERROR_INFO(SIGILL,  "privileged operation", privileged_op,
-             ILL_PRVOPC, get_check_address(regs))
-DO_ERROR_INFO(SIGILL,  "special operation exception", special_op_exception,
-             ILL_ILLOPN, get_check_address(regs))
-DO_ERROR_INFO(SIGILL,  "translation exception", translation_exception,
-             ILL_ILLOPN, get_check_address(regs))
-
-static inline void
-do_fp_trap(struct pt_regs *regs, void __user *location,
-           int fpc, long interruption_code)
+DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
+             "addressing exception")
+DO_ERROR_INFO(execute_exception, SIGILL, ILL_ILLOPN,
+             "execute exception")
+DO_ERROR_INFO(divide_exception, SIGFPE, FPE_INTDIV,
+             "fixpoint divide exception")
+DO_ERROR_INFO(overflow_exception, SIGFPE, FPE_INTOVF,
+             "fixpoint overflow exception")
+DO_ERROR_INFO(hfp_overflow_exception, SIGFPE, FPE_FLTOVF,
+             "HFP overflow exception")
+DO_ERROR_INFO(hfp_underflow_exception, SIGFPE, FPE_FLTUND,
+             "HFP underflow exception")
+DO_ERROR_INFO(hfp_significance_exception, SIGFPE, FPE_FLTRES,
+             "HFP significance exception")
+DO_ERROR_INFO(hfp_divide_exception, SIGFPE, FPE_FLTDIV,
+             "HFP divide exception")
+DO_ERROR_INFO(hfp_sqrt_exception, SIGFPE, FPE_FLTINV,
+             "HFP square root exception")
+DO_ERROR_INFO(operand_exception, SIGILL, ILL_ILLOPN,
+             "operand exception")
+DO_ERROR_INFO(privileged_op, SIGILL, ILL_PRVOPC,
+             "privileged operation")
+DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
+             "special operation exception")
+DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN,
+             "translation exception")
+
+static inline void do_fp_trap(struct pt_regs *regs, void __user *location,
+                             int fpc, long pgm_int_code)
 {
        siginfo_t si;
 
@@ -453,26 +447,19 @@ do_fp_trap(struct pt_regs *regs, void __user *location,
                else if (fpc & 0x0800) /* inexact */
                        si.si_code = FPE_FLTRES;
        }
-       current->thread.ieee_instruction_pointer = (addr_t) location;
-       do_trap(interruption_code, SIGFPE,
+       do_trap(pgm_int_code, SIGFPE,
                "floating point exception", regs, &si);
 }
 
-static void illegal_op(struct pt_regs * regs, long interruption_code)
+static void illegal_op(struct pt_regs *regs, long pgm_int_code,
+                      unsigned long trans_exc_code)
 {
        siginfo_t info;
         __u8 opcode[6];
        __u16 __user *location;
        int signal = 0;
 
-       location = get_check_address(regs);
-
-       /*
-        * We got all needed information from the lowcore and can
-        * now safely switch on interrupts.
-        */
-       if (regs->psw.mask & PSW_MASK_PSTATE)
-               local_irq_enable();
+       location = get_psw_address(regs, pgm_int_code);
 
        if (regs->psw.mask & PSW_MASK_PSTATE) {
                if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
@@ -512,7 +499,7 @@ static void illegal_op(struct pt_regs * regs, long interruption_code)
                 * If we get an illegal op in kernel mode, send it through the
                 * kprobes notifier. If kprobes doesn't pick it up, SIGILL
                 */
-               if (notify_die(DIE_BPT, "bpt", regs, interruption_code,
+               if (notify_die(DIE_BPT, "bpt", regs, pgm_int_code,
                               3, SIGTRAP) != NOTIFY_STOP)
                        signal = SIGILL;
        }
@@ -520,13 +507,13 @@ static void illegal_op(struct pt_regs * regs, long interruption_code)
 #ifdef CONFIG_MATHEMU
         if (signal == SIGFPE)
                do_fp_trap(regs, location,
-                           current->thread.fp_regs.fpc, interruption_code);
+                          current->thread.fp_regs.fpc, pgm_int_code);
         else if (signal == SIGSEGV) {
                info.si_signo = signal;
                info.si_errno = 0;
                info.si_code = SEGV_MAPERR;
                info.si_addr = (void __user *) location;
-               do_trap(interruption_code, signal,
+               do_trap(pgm_int_code, signal,
                        "user address fault", regs, &info);
        } else
 #endif
@@ -535,28 +522,22 @@ static void illegal_op(struct pt_regs * regs, long interruption_code)
                info.si_errno = 0;
                info.si_code = ILL_ILLOPC;
                info.si_addr = (void __user *) location;
-               do_trap(interruption_code, signal,
+               do_trap(pgm_int_code, signal,
                        "illegal operation", regs, &info);
        }
 }
 
 
 #ifdef CONFIG_MATHEMU
-asmlinkage void 
-specification_exception(struct pt_regs * regs, long interruption_code)
+asmlinkage void specification_exception(struct pt_regs *regs,
+                                       long pgm_int_code,
+                                       unsigned long trans_exc_code)
 {
         __u8 opcode[6];
        __u16 __user *location = NULL;
        int signal = 0;
 
-       location = (__u16 __user *) get_check_address(regs);
-
-       /*
-        * We got all needed information from the lowcore and can
-        * now safely switch on interrupts.
-        */
-        if (regs->psw.mask & PSW_MASK_PSTATE)
-               local_irq_enable();
+       location = (__u16 __user *) get_psw_address(regs, pgm_int_code);
 
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                get_user(*((__u16 *) opcode), location);
@@ -592,35 +573,29 @@ specification_exception(struct pt_regs * regs, long interruption_code)
 
         if (signal == SIGFPE)
                do_fp_trap(regs, location,
-                           current->thread.fp_regs.fpc, interruption_code);
+                          current->thread.fp_regs.fpc, pgm_int_code);
         else if (signal) {
                siginfo_t info;
                info.si_signo = signal;
                info.si_errno = 0;
                info.si_code = ILL_ILLOPN;
                info.si_addr = location;
-               do_trap(interruption_code, signal, 
+               do_trap(pgm_int_code, signal,
                        "specification exception", regs, &info);
        }
 }
 #else
-DO_ERROR_INFO(SIGILL, "specification exception", specification_exception,
-             ILL_ILLOPN, get_check_address(regs));
+DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
+             "specification exception");
 #endif
 
-static void data_exception(struct pt_regs * regs, long interruption_code)
+static void data_exception(struct pt_regs *regs, long pgm_int_code,
+                          unsigned long trans_exc_code)
 {
        __u16 __user *location;
        int signal = 0;
 
-       location = get_check_address(regs);
-
-       /*
-        * We got all needed information from the lowcore and can
-        * now safely switch on interrupts.
-        */
-       if (regs->psw.mask & PSW_MASK_PSTATE)
-               local_irq_enable();
+       location = get_psw_address(regs, pgm_int_code);
 
        if (MACHINE_HAS_IEEE)
                asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -686,19 +661,19 @@ static void data_exception(struct pt_regs * regs, long interruption_code)
                signal = SIGILL;
         if (signal == SIGFPE)
                do_fp_trap(regs, location,
-                           current->thread.fp_regs.fpc, interruption_code);
+                          current->thread.fp_regs.fpc, pgm_int_code);
         else if (signal) {
                siginfo_t info;
                info.si_signo = signal;
                info.si_errno = 0;
                info.si_code = ILL_ILLOPN;
                info.si_addr = location;
-               do_trap(interruption_code, signal, 
-                       "data exception", regs, &info);
+               do_trap(pgm_int_code, signal, "data exception", regs, &info);
        }
 }
 
-static void space_switch_exception(struct pt_regs * regs, long int_code)
+static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
+                                  unsigned long trans_exc_code)
 {
         siginfo_t info;
 
@@ -709,8 +684,8 @@ static void space_switch_exception(struct pt_regs * regs, long int_code)
         info.si_signo = SIGILL;
         info.si_errno = 0;
         info.si_code = ILL_PRVOPC;
-        info.si_addr = get_check_address(regs);
-        do_trap(int_code, SIGILL, "space switch event", regs, &info);
+       info.si_addr = get_psw_address(regs, pgm_int_code);
+       do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
 }
 
 asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
index 6b83870..e3150dd 100644 (file)
@@ -84,11 +84,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
  */
 static void vdso_init_data(struct vdso_data *vd)
 {
-       unsigned int facility_list;
-
-       facility_list = stfl();
-       vd->ectg_available =
-               user_mode != HOME_SPACE_MODE && (facility_list & 1);
+       vd->ectg_available = user_mode != HOME_SPACE_MODE && test_facility(31);
 }
 
 #ifdef CONFIG_64BIT
index 3479f1b..56c8687 100644 (file)
@@ -314,7 +314,8 @@ static void do_callbacks(struct list_head *cb_list)
 /*
  * Handler for the virtual CPU timer.
  */
-static void do_cpu_timer_interrupt(__u16 error_code)
+static void do_cpu_timer_interrupt(unsigned int ext_int_code,
+                                  unsigned int param32, unsigned long param64)
 {
        struct vtimer_queue *vq;
        struct vtimer_list *event, *tmp;
index 4fe6865..985d825 100644 (file)
@@ -740,8 +740,8 @@ static int __init kvm_s390_init(void)
                kvm_exit();
                return -ENOMEM;
        }
-       stfle(facilities, 1);
-       facilities[0] &= 0xff00fff3f0700000ULL;
+       memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
+       facilities[0] &= 0xff00fff3f47c0000ULL;
        return 0;
 }
 
index 4420550..9194a4b 100644 (file)
@@ -154,12 +154,12 @@ static int handle_chsc(struct kvm_vcpu *vcpu)
 
 static int handle_stfl(struct kvm_vcpu *vcpu)
 {
-       unsigned int facility_list = stfl();
+       unsigned int facility_list;
        int rc;
 
        vcpu->stat.instruction_stfl++;
        /* only pass the facility bits, which we can handle */
-       facility_list &= 0xff00fff3;
+       facility_list = S390_lowcore.stfl_fac_list & 0xff00fff3;
 
        rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
                           &facility_list, sizeof(facility_list));
index eec0544..6fbc6f3 100644 (file)
@@ -3,6 +3,6 @@
 #
 
 obj-y   := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
-           page-states.o
+           page-states.o gup.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
index a9550dc..c66ffd8 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/diag.h>
 
-static char *sender = "VMRMSVM";
+#ifdef CONFIG_CMM_IUCV
+static char *cmm_default_sender = "VMRMSVM";
+#endif
+static char *sender;
 module_param(sender, charp, 0400);
 MODULE_PARM_DESC(sender,
                 "Guest name that may send SMSG messages (default VMRMSVM)");
@@ -440,6 +443,8 @@ static int __init cmm_init(void)
                int len = strlen(sender);
                while (len--)
                        sender[len] = toupper(sender[len]);
+       } else {
+               sender = cmm_default_sender;
        }
 
        rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
index 2505b2e..fe5701e 100644 (file)
 #define VM_FAULT_BADMAP                0x020000
 #define VM_FAULT_BADACCESS     0x040000
 
+static unsigned long store_indication;
+
+void fault_init(void)
+{
+       if (test_facility(2) && test_facility(75))
+               store_indication = 0xc00;
+}
+
 static inline int notify_page_fault(struct pt_regs *regs)
 {
        int ret = 0;
@@ -199,14 +207,21 @@ static noinline void do_sigbus(struct pt_regs *regs, long int_code,
                               unsigned long trans_exc_code)
 {
        struct task_struct *tsk = current;
+       unsigned long address;
+       struct siginfo si;
 
        /*
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
-       tsk->thread.prot_addr = trans_exc_code & __FAIL_ADDR_MASK;
+       address = trans_exc_code & __FAIL_ADDR_MASK;
+       tsk->thread.prot_addr = address;
        tsk->thread.trap_no = int_code;
-       force_sig(SIGBUS, tsk);
+       si.si_signo = SIGBUS;
+       si.si_errno = 0;
+       si.si_code = BUS_ADRERR;
+       si.si_addr = (void __user *) address;
+       force_sig_info(SIGBUS, &si, tsk);
 }
 
 #ifdef CONFIG_S390_EXEC_PROTECT
@@ -266,10 +281,11 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
                if (fault & VM_FAULT_OOM)
                        pagefault_out_of_memory();
                else if (fault & VM_FAULT_SIGBUS) {
-                       do_sigbus(regs, int_code, trans_exc_code);
                        /* Kernel mode? Handle exceptions or die */
                        if (!(regs->psw.mask & PSW_MASK_PSTATE))
                                do_no_context(regs, int_code, trans_exc_code);
+                       else
+                               do_sigbus(regs, int_code, trans_exc_code);
                } else
                        BUG();
                break;
@@ -294,7 +310,7 @@ static inline int do_exception(struct pt_regs *regs, int access,
        struct mm_struct *mm;
        struct vm_area_struct *vma;
        unsigned long address;
-       int fault;
+       int fault, write;
 
        if (notify_page_fault(regs))
                return 0;
@@ -312,12 +328,6 @@ static inline int do_exception(struct pt_regs *regs, int access,
                goto out;
 
        address = trans_exc_code & __FAIL_ADDR_MASK;
-       /*
-        * When we get here, the fault happened in the current
-        * task's user address space, so we can switch on the
-        * interrupts again and then search the VMAs
-        */
-       local_irq_enable();
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
        down_read(&mm->mmap_sem);
 
@@ -348,8 +358,10 @@ static inline int do_exception(struct pt_regs *regs, int access,
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       fault = handle_mm_fault(mm, vma, address,
-                               (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0);
+       write = (access == VM_WRITE ||
+                (trans_exc_code & store_indication) == 0x400) ?
+               FAULT_FLAG_WRITE : 0;
+       fault = handle_mm_fault(mm, vma, address, write);
        if (unlikely(fault & VM_FAULT_ERROR))
                goto out_up;
 
@@ -374,20 +386,20 @@ out:
        return fault;
 }
 
-void __kprobes do_protection_exception(struct pt_regs *regs, long int_code)
+void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code,
+                                      unsigned long trans_exc_code)
 {
-       unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
        int fault;
 
        /* Protection exception is supressing, decrement psw address. */
-       regs->psw.addr -= (int_code >> 16);
+       regs->psw.addr -= (pgm_int_code >> 16);
        /*
         * Check for low-address protection.  This needs to be treated
         * as a special case because the translation exception code
         * field is not guaranteed to contain valid data in this case.
         */
        if (unlikely(!(trans_exc_code & 4))) {
-               do_low_address(regs, int_code, trans_exc_code);
+               do_low_address(regs, pgm_int_code, trans_exc_code);
                return;
        }
        fault = do_exception(regs, VM_WRITE, trans_exc_code);
@@ -395,9 +407,9 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code)
                do_fault_error(regs, 4, trans_exc_code, fault);
 }
 
-void __kprobes do_dat_exception(struct pt_regs *regs, long int_code)
+void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code,
+                               unsigned long trans_exc_code)
 {
-       unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
        int access, fault;
 
        access = VM_READ | VM_EXEC | VM_WRITE;
@@ -408,21 +420,19 @@ void __kprobes do_dat_exception(struct pt_regs *regs, long int_code)
 #endif
        fault = do_exception(regs, access, trans_exc_code);
        if (unlikely(fault))
-               do_fault_error(regs, int_code & 255, trans_exc_code, fault);
+               do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault);
 }
 
 #ifdef CONFIG_64BIT
-void __kprobes do_asce_exception(struct pt_regs *regs, long int_code)
+void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code,
+                                unsigned long trans_exc_code)
 {
-       unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
 
        if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
                goto no_context;
 
-       local_irq_enable();
-
        down_read(&mm->mmap_sem);
        vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK);
        up_read(&mm->mmap_sem);
@@ -434,16 +444,16 @@ void __kprobes do_asce_exception(struct pt_regs *regs, long int_code)
 
        /* User mode accesses just cause a SIGSEGV */
        if (regs->psw.mask & PSW_MASK_PSTATE) {
-               do_sigsegv(regs, int_code, SEGV_MAPERR, trans_exc_code);
+               do_sigsegv(regs, pgm_int_code, SEGV_MAPERR, trans_exc_code);
                return;
        }
 
 no_context:
-       do_no_context(regs, int_code, trans_exc_code);
+       do_no_context(regs, pgm_int_code, trans_exc_code);
 }
 #endif
 
-int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user)
+int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
 {
        struct pt_regs regs;
        int access, fault;
@@ -454,14 +464,14 @@ int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user)
        regs.psw.addr = (unsigned long) __builtin_return_address(0);
        regs.psw.addr |= PSW_ADDR_AMODE;
        uaddr &= PAGE_MASK;
-       access = write_user ? VM_WRITE : VM_READ;
+       access = write ? VM_WRITE : VM_READ;
        fault = do_exception(&regs, access, uaddr | 2);
        if (unlikely(fault)) {
                if (fault & VM_FAULT_OOM) {
                        pagefault_out_of_memory();
                        fault = 0;
                } else if (fault & VM_FAULT_SIGBUS)
-                       do_sigbus(&regs, int_code, uaddr);
+                       do_sigbus(&regs, pgm_int_code, uaddr);
        }
        return fault ? -EFAULT : 0;
 }
@@ -527,7 +537,8 @@ void pfault_fini(void)
                : : "a" (&refbk), "m" (refbk) : "cc");
 }
 
-static void pfault_interrupt(__u16 int_code)
+static void pfault_interrupt(unsigned int ext_int_code,
+                            unsigned int param32, unsigned long param64)
 {
        struct task_struct *tsk;
        __u16 subcode;
@@ -538,14 +549,18 @@ static void pfault_interrupt(__u16 int_code)
         * in the 'cpu address' field associated with the
          * external interrupt. 
         */
-       subcode = S390_lowcore.cpu_addr;
+       subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != __SUBCODE_MASK)
                return;
 
        /*
         * Get the token (= address of the task structure of the affected task).
         */
-       tsk = *(struct task_struct **) __LC_PFAULT_INTPARM;
+#ifdef CONFIG_64BIT
+       tsk = *(struct task_struct **) param64;
+#else
+       tsk = *(struct task_struct **) param32;
+#endif
 
        if (subcode & 0x0080) {
                /* signal bit is set -> a page has been swapped in by VM */
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
new file mode 100644 (file)
index 0000000..38e641c
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *  Lockless get_user_pages_fast for s390
+ *
+ *  Copyright IBM Corp. 2010
+ *  Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/vmstat.h>
+#include <linux/pagemap.h>
+#include <linux/rwsem.h>
+#include <asm/pgtable.h>
+
+/*
+ * The performance critical leaf functions are made noinline otherwise gcc
+ * inlines everything into a single function which results in too much
+ * register pressure.
+ */
+static inline int gup_pte_range(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long mask, result;
+       pte_t *ptep, pte;
+       struct page *page;
+
+       result = write ? 0 : _PAGE_RO;
+       mask = result | _PAGE_INVALID | _PAGE_SPECIAL;
+
+       ptep = ((pte_t *) pmd_deref(pmd)) + pte_index(addr);
+       do {
+               pte = *ptep;
+               barrier();
+               if ((pte_val(pte) & mask) != result)
+                       return 0;
+               VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
+               page = pte_page(pte);
+               if (!page_cache_get_speculative(page))
+                       return 0;
+               if (unlikely(pte_val(pte) != pte_val(*ptep))) {
+                       put_page(page);
+                       return 0;
+               }
+               pages[*nr] = page;
+               (*nr)++;
+
+       } while (ptep++, addr += PAGE_SIZE, addr != end);
+
+       return 1;
+}
+
+static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long mask, result;
+       struct page *head, *page;
+       int refs;
+
+       result = write ? 0 : _SEGMENT_ENTRY_RO;
+       mask = result | _SEGMENT_ENTRY_INV;
+       if ((pmd_val(pmd) & mask) != result)
+               return 0;
+       VM_BUG_ON(!pfn_valid(pmd_val(pmd) >> PAGE_SHIFT));
+
+       refs = 0;
+       head = pmd_page(pmd);
+       page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
+       do {
+               VM_BUG_ON(compound_head(page) != head);
+               pages[*nr] = page;
+               (*nr)++;
+               page++;
+               refs++;
+       } while (addr += PAGE_SIZE, addr != end);
+
+       if (!page_cache_add_speculative(head, refs)) {
+               *nr -= refs;
+               return 0;
+       }
+
+       if (unlikely(pmd_val(pmd) != pmd_val(*pmdp))) {
+               *nr -= refs;
+               while (refs--)
+                       put_page(head);
+       }
+
+       return 1;
+}
+
+
+static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long next;
+       pmd_t *pmdp, pmd;
+
+       pmdp = (pmd_t *) pudp;
+#ifdef CONFIG_64BIT
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
+               pmdp = (pmd_t *) pud_deref(pud);
+       pmdp += pmd_index(addr);
+#endif
+       do {
+               pmd = *pmdp;
+               barrier();
+               next = pmd_addr_end(addr, end);
+               if (pmd_none(pmd))
+                       return 0;
+               if (unlikely(pmd_huge(pmd))) {
+                       if (!gup_huge_pmd(pmdp, pmd, addr, next,
+                                         write, pages, nr))
+                               return 0;
+               } else if (!gup_pte_range(pmdp, pmd, addr, next,
+                                         write, pages, nr))
+                       return 0;
+       } while (pmdp++, addr = next, addr != end);
+
+       return 1;
+}
+
+static inline int gup_pud_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr,
+               unsigned long end, int write, struct page **pages, int *nr)
+{
+       unsigned long next;
+       pud_t *pudp, pud;
+
+       pudp = (pud_t *) pgdp;
+#ifdef CONFIG_64BIT
+       if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2)
+               pudp = (pud_t *) pgd_deref(pgd);
+       pudp += pud_index(addr);
+#endif
+       do {
+               pud = *pudp;
+               barrier();
+               next = pud_addr_end(addr, end);
+               if (pud_none(pud))
+                       return 0;
+               if (!gup_pmd_range(pudp, pud, addr, next, write, pages, nr))
+                       return 0;
+       } while (pudp++, addr = next, addr != end);
+
+       return 1;
+}
+
+/**
+ * get_user_pages_fast() - pin user pages in memory
+ * @start:     starting user address
+ * @nr_pages:  number of pages from start to pin
+ * @write:     whether pages will be written to
+ * @pages:     array that receives pointers to the pages pinned.
+ *             Should be at least nr_pages long.
+ *
+ * Attempt to pin user pages in memory without taking mm->mmap_sem.
+ * If not successful, it will fall back to taking the lock and
+ * calling get_user_pages().
+ *
+ * Returns number of pages pinned. This may be fewer than the number
+ * requested. If nr_pages is 0 or negative, returns 0. If no pages
+ * were pinned, returns -errno.
+ */
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+                       struct page **pages)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr, len, end;
+       unsigned long next;
+       pgd_t *pgdp, pgd;
+       int nr = 0;
+
+       start &= PAGE_MASK;
+       addr = start;
+       len = (unsigned long) nr_pages << PAGE_SHIFT;
+       end = start + len;
+       if (end < start)
+               goto slow_irqon;
+
+       /*
+        * local_irq_disable() doesn't prevent pagetable teardown, but does
+        * prevent the pagetables from being freed on s390.
+        *
+        * So long as we atomically load page table pointers versus teardown,
+        * we can follow the address down to the the page and take a ref on it.
+        */
+       local_irq_disable();
+       pgdp = pgd_offset(mm, addr);
+       do {
+               pgd = *pgdp;
+               barrier();
+               next = pgd_addr_end(addr, end);
+               if (pgd_none(pgd))
+                       goto slow;
+               if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr))
+                       goto slow;
+       } while (pgdp++, addr = next, addr != end);
+       local_irq_enable();
+
+       VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
+       return nr;
+
+       {
+               int ret;
+slow:
+               local_irq_enable();
+slow_irqon:
+               /* Try to get the remaining pages with get_user_pages */
+               start += nr << PAGE_SHIFT;
+               pages += nr;
+
+               down_read(&mm->mmap_sem);
+               ret = get_user_pages(current, mm, start,
+                       (end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
+               up_read(&mm->mmap_sem);
+
+               /* Have to be a bit careful with return values */
+               if (nr > 0) {
+                       if (ret < 0)
+                               ret = nr;
+                       else
+                               ret += nr;
+               }
+
+               return ret;
+       }
+}
index f28c43d..639cd21 100644 (file)
@@ -68,7 +68,7 @@ void arch_release_hugepage(struct page *page)
        ptep = (pte_t *) page[1].index;
        if (!ptep)
                return;
-       pte_free(&init_mm, ptep);
+       page_table_free(&init_mm, (unsigned long *) ptep);
        page[1].index = 0;
 }
 
index 94b8ba2..bb40933 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 
-char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+unsigned long empty_zero_page, zero_page_mask;
 EXPORT_SYMBOL(empty_zero_page);
 
+static unsigned long setup_zero_pages(void)
+{
+       struct cpuid cpu_id;
+       unsigned int order;
+       unsigned long size;
+       struct page *page;
+       int i;
+
+       get_cpu_id(&cpu_id);
+       switch (cpu_id.machine) {
+       case 0x9672:    /* g5 */
+       case 0x2064:    /* z900 */
+       case 0x2066:    /* z900 */
+       case 0x2084:    /* z990 */
+       case 0x2086:    /* z990 */
+       case 0x2094:    /* z9-109 */
+       case 0x2096:    /* z9-109 */
+               order = 0;
+               break;
+       case 0x2097:    /* z10 */
+       case 0x2098:    /* z10 */
+       default:
+               order = 2;
+               break;
+       }
+
+       empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+       if (!empty_zero_page)
+               panic("Out of memory in setup_zero_pages");
+
+       page = virt_to_page((void *) empty_zero_page);
+       split_page(page, order);
+       for (i = 1 << order; i > 0; i--) {
+               SetPageReserved(page);
+               page++;
+       }
+
+       size = PAGE_SIZE << order;
+       zero_page_mask = (size - 1) & PAGE_MASK;
+
+       return 1UL << order;
+}
+
 /*
  * paging_init() sets up the page tables
  */
@@ -83,6 +124,7 @@ void __init paging_init(void)
 #endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(max_zone_pfns);
+       fault_init();
 }
 
 void __init mem_init(void)
@@ -92,14 +134,12 @@ void __init mem_init(void)
         max_mapnr = num_physpages = max_low_pfn;
         high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
-        /* clear the zero-page */
-        memset(empty_zero_page, 0, PAGE_SIZE);
-
        /* Setup guest page hinting */
        cmma_init();
 
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem();
+       totalram_pages -= setup_zero_pages();   /* Setup zeroed pages. */
 
        reservedpages = 0;
 
index 8d99924..0c719c6 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <linux/quicklist.h>
+#include <linux/rcupdate.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
+struct rcu_table_freelist {
+       struct rcu_head rcu;
+       struct mm_struct *mm;
+       unsigned int pgt_index;
+       unsigned int crst_index;
+       unsigned long *table[0];
+};
+
+#define RCU_FREELIST_SIZE \
+       ((PAGE_SIZE - sizeof(struct rcu_table_freelist)) \
+         / sizeof(unsigned long))
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+static DEFINE_PER_CPU(struct rcu_table_freelist *, rcu_table_freelist);
+
+static void __page_table_free(struct mm_struct *mm, unsigned long *table);
+static void __crst_table_free(struct mm_struct *mm, unsigned long *table);
+
+static struct rcu_table_freelist *rcu_table_freelist_get(struct mm_struct *mm)
+{
+       struct rcu_table_freelist **batchp = &__get_cpu_var(rcu_table_freelist);
+       struct rcu_table_freelist *batch = *batchp;
+
+       if (batch)
+               return batch;
+       batch = (struct rcu_table_freelist *) __get_free_page(GFP_ATOMIC);
+       if (batch) {
+               batch->mm = mm;
+               batch->pgt_index = 0;
+               batch->crst_index = RCU_FREELIST_SIZE;
+               *batchp = batch;
+       }
+       return batch;
+}
+
+static void rcu_table_freelist_callback(struct rcu_head *head)
+{
+       struct rcu_table_freelist *batch =
+               container_of(head, struct rcu_table_freelist, rcu);
+
+       while (batch->pgt_index > 0)
+               __page_table_free(batch->mm, batch->table[--batch->pgt_index]);
+       while (batch->crst_index < RCU_FREELIST_SIZE)
+               __crst_table_free(batch->mm, batch->table[batch->crst_index++]);
+       free_page((unsigned long) batch);
+}
+
+void rcu_table_freelist_finish(void)
+{
+       struct rcu_table_freelist *batch = __get_cpu_var(rcu_table_freelist);
+
+       if (!batch)
+               return;
+       call_rcu(&batch->rcu, rcu_table_freelist_callback);
+       __get_cpu_var(rcu_table_freelist) = NULL;
+}
+
+static void smp_sync(void *arg)
+{
+}
+
 #ifndef CONFIG_64BIT
 #define ALLOC_ORDER    1
 #define TABLES_PER_PAGE        4
@@ -78,25 +140,55 @@ unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
                }
                page->index = page_to_phys(shadow);
        }
-       spin_lock(&mm->context.list_lock);
+       spin_lock_bh(&mm->context.list_lock);
        list_add(&page->lru, &mm->context.crst_list);
-       spin_unlock(&mm->context.list_lock);
+       spin_unlock_bh(&mm->context.list_lock);
        return (unsigned long *) page_to_phys(page);
 }
 
-void crst_table_free(struct mm_struct *mm, unsigned long *table)
+static void __crst_table_free(struct mm_struct *mm, unsigned long *table)
 {
        unsigned long *shadow = get_shadow_table(table);
-       struct page *page = virt_to_page(table);
 
-       spin_lock(&mm->context.list_lock);
-       list_del(&page->lru);
-       spin_unlock(&mm->context.list_lock);
        if (shadow)
                free_pages((unsigned long) shadow, ALLOC_ORDER);
        free_pages((unsigned long) table, ALLOC_ORDER);
 }
 
+void crst_table_free(struct mm_struct *mm, unsigned long *table)
+{
+       struct page *page = virt_to_page(table);
+
+       spin_lock_bh(&mm->context.list_lock);
+       list_del(&page->lru);
+       spin_unlock_bh(&mm->context.list_lock);
+       __crst_table_free(mm, table);
+}
+
+void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table)
+{
+       struct rcu_table_freelist *batch;
+       struct page *page = virt_to_page(table);
+
+       spin_lock_bh(&mm->context.list_lock);
+       list_del(&page->lru);
+       spin_unlock_bh(&mm->context.list_lock);
+       if (atomic_read(&mm->mm_users) < 2 &&
+           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
+               __crst_table_free(mm, table);
+               return;
+       }
+       batch = rcu_table_freelist_get(mm);
+       if (!batch) {
+               smp_call_function(smp_sync, NULL, 1);
+               __crst_table_free(mm, table);
+               return;
+       }
+       batch->table[--batch->crst_index] = table;
+       if (batch->pgt_index >= batch->crst_index)
+               rcu_table_freelist_finish();
+}
+
 #ifdef CONFIG_64BIT
 int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
 {
@@ -108,7 +200,7 @@ repeat:
        table = crst_table_alloc(mm, mm->context.noexec);
        if (!table)
                return -ENOMEM;
-       spin_lock(&mm->page_table_lock);
+       spin_lock_bh(&mm->page_table_lock);
        if (mm->context.asce_limit < limit) {
                pgd = (unsigned long *) mm->pgd;
                if (mm->context.asce_limit <= (1UL << 31)) {
@@ -130,7 +222,7 @@ repeat:
                mm->task_size = mm->context.asce_limit;
                table = NULL;
        }
-       spin_unlock(&mm->page_table_lock);
+       spin_unlock_bh(&mm->page_table_lock);
        if (table)
                crst_table_free(mm, table);
        if (mm->context.asce_limit < limit)
@@ -182,7 +274,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
        unsigned long bits;
 
        bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
-       spin_lock(&mm->context.list_lock);
+       spin_lock_bh(&mm->context.list_lock);
        page = NULL;
        if (!list_empty(&mm->context.pgtable_list)) {
                page = list_first_entry(&mm->context.pgtable_list,
@@ -191,7 +283,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
                        page = NULL;
        }
        if (!page) {
-               spin_unlock(&mm->context.list_lock);
+               spin_unlock_bh(&mm->context.list_lock);
                page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
                if (!page)
                        return NULL;
@@ -202,7 +294,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
                        clear_table_pgstes(table);
                else
                        clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
-               spin_lock(&mm->context.list_lock);
+               spin_lock_bh(&mm->context.list_lock);
                list_add(&page->lru, &mm->context.pgtable_list);
        }
        table = (unsigned long *) page_to_phys(page);
@@ -213,10 +305,25 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
        page->flags |= bits;
        if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
                list_move_tail(&page->lru, &mm->context.pgtable_list);
-       spin_unlock(&mm->context.list_lock);
+       spin_unlock_bh(&mm->context.list_lock);
        return table;
 }
 
+static void __page_table_free(struct mm_struct *mm, unsigned long *table)
+{
+       struct page *page;
+       unsigned long bits;
+
+       bits = ((unsigned long) table) & 15;
+       table = (unsigned long *)(((unsigned long) table) ^ bits);
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       page->flags ^= bits;
+       if (!(page->flags & FRAG_MASK)) {
+               pgtable_page_dtor(page);
+               __free_page(page);
+       }
+}
+
 void page_table_free(struct mm_struct *mm, unsigned long *table)
 {
        struct page *page;
@@ -225,7 +332,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
        bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       spin_lock(&mm->context.list_lock);
+       spin_lock_bh(&mm->context.list_lock);
        page->flags ^= bits;
        if (page->flags & FRAG_MASK) {
                /* Page now has some free pgtable fragments. */
@@ -234,18 +341,48 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        } else
                /* All fragments of the 4K page have been freed. */
                list_del(&page->lru);
-       spin_unlock(&mm->context.list_lock);
+       spin_unlock_bh(&mm->context.list_lock);
        if (page) {
                pgtable_page_dtor(page);
                __free_page(page);
        }
 }
 
+void page_table_free_rcu(struct mm_struct *mm, unsigned long *table)
+{
+       struct rcu_table_freelist *batch;
+       struct page *page;
+       unsigned long bits;
+
+       if (atomic_read(&mm->mm_users) < 2 &&
+           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
+               page_table_free(mm, table);
+               return;
+       }
+       batch = rcu_table_freelist_get(mm);
+       if (!batch) {
+               smp_call_function(smp_sync, NULL, 1);
+               page_table_free(mm, table);
+               return;
+       }
+       bits = (mm->context.noexec || mm->context.has_pgste) ? 3UL : 1UL;
+       bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       spin_lock_bh(&mm->context.list_lock);
+       /* Delayed freeing with rcu prevents reuse of pgtable fragments */
+       list_del_init(&page->lru);
+       spin_unlock_bh(&mm->context.list_lock);
+       table = (unsigned long *)(((unsigned long) table) | bits);
+       batch->table[batch->pgt_index++] = table;
+       if (batch->pgt_index >= batch->crst_index)
+               rcu_table_freelist_finish();
+}
+
 void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
 {
        struct page *page;
 
-       spin_lock(&mm->context.list_lock);
+       spin_lock_bh(&mm->context.list_lock);
        /* Free shadow region and segment tables. */
        list_for_each_entry(page, &mm->context.crst_list, lru)
                if (page->index) {
@@ -255,7 +392,7 @@ void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
        /* "Free" second halves of page tables. */
        list_for_each_entry(page, &mm->context.pgtable_list, lru)
                page->flags &= ~SECOND_HALVES;
-       spin_unlock(&mm->context.list_lock);
+       spin_unlock_bh(&mm->context.list_lock);
        mm->context.noexec = 0;
        update_mm(mm, tsk);
 }
@@ -312,6 +449,8 @@ int s390_enable_sie(void)
        tsk->mm = tsk->active_mm = mm;
        preempt_disable();
        update_mm(mm, tsk);
+       atomic_inc(&mm->context.attach_count);
+       atomic_dec(&old_mm->context.attach_count);
        cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
        preempt_enable();
        task_unlock(tsk);
index 35b6879..0f40fc3 100644 (file)
@@ -24,6 +24,7 @@ config SUPERH
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
        select HAVE_SYSCALL_TRACEPOINTS
+       select HAVE_REGS_AND_STACK_ACCESS_API
        select RTC_LIB
        select GENERIC_ATOMIC64
        help
@@ -46,7 +47,7 @@ config SUPERH32
        select HAVE_ARCH_KGDB
        select HAVE_HW_BREAKPOINT
        select HAVE_MIXED_BREAKPOINTS_REGS
-       select PERF_EVENTS if HAVE_HW_BREAKPOINT
+       select PERF_EVENTS
        select ARCH_HIBERNATION_POSSIBLE if MMU
 
 config SUPERH64
@@ -471,6 +472,7 @@ config CPU_SUBTYPE_SHX3
        select CPU_SH4A
        select CPU_SHX3
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+       select ARCH_REQUIRE_GPIOLIB
 
 # SH4AL-DSP Processor Support
 
@@ -575,7 +577,7 @@ config SH_CLK_CPG
 config SH_CLK_CPG_LEGACY
        depends on SH_CLK_CPG
        def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
-                     !CPU_SUBTYPE_SH7786
+                     !CPU_SHX3 && !CPU_SUBTYPE_SH7757
 
 config SH_CLK_MD
        int "CPU Mode Pin Setting"
index 07b35ca..9c94711 100644 (file)
@@ -155,6 +155,8 @@ config SH_SDK7786
        depends on CPU_SUBTYPE_SH7786
        select SYS_SUPPORTS_PCI
        select NO_IOPORT if !PCI
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select HAVE_SRAM_POOL
        help
          Select SDK7786 if configuring for a Renesas Technology Europe
          SH7786-65nm board.
@@ -165,6 +167,11 @@ config SH_HIGHLANDER
        select SYS_SUPPORTS_PCI
        select IO_TRAPPED if MMU
 
+config SH_SH7757LCR
+       bool "SH7757LCR"
+       depends on CPU_SUBTYPE_SH7757
+       select ARCH_REQUIRE_GPIOLIB
+
 config SH_SH7785LCR
        bool "SH7785LCR"
        depends on CPU_SUBTYPE_SH7785
@@ -309,6 +316,17 @@ config SH_POLARIS
        help
          Select if configuring for an SMSC Polaris development board
 
+config SH_SH2007
+       bool "SH-2007 board"
+       select NO_IOPORT
+       depends on CPU_SUBTYPE_SH7780
+       help
+         SH-2007 is a single-board computer based around SH7780 chip
+         intended for embedded applications.
+         It has an Ethernet interface (SMC9118), direct connected
+         Compact Flash socket, two serial ports and PC-104 bus.
+         More information at <http://sh2000.sh-linux.org>.
+
 endmenu
 
 source "arch/sh/boards/mach-r2d/Kconfig"
index 4f90f9b..38ef655 100644 (file)
@@ -2,6 +2,7 @@
 # Specific board support, not covered by a mach group.
 #
 obj-$(CONFIG_SH_MAGIC_PANEL_R2)        += board-magicpanelr2.o
+obj-$(CONFIG_SH_SH2007)                += board-sh2007.o
 obj-$(CONFIG_SH_SH7785LCR)     += board-sh7785lcr.o
 obj-$(CONFIG_SH_URQUELL)       += board-urquell.o
 obj-$(CONFIG_SH_SHMIN)         += board-shmin.o
@@ -9,3 +10,4 @@ obj-$(CONFIG_SH_EDOSK7760)     += board-edosk7760.o
 obj-$(CONFIG_SH_ESPT)          += board-espt.o
 obj-$(CONFIG_SH_POLARIS)       += board-polaris.o
 obj-$(CONFIG_SH_TITAN)         += board-titan.o
+obj-$(CONFIG_SH_SH7757LCR)     += board-sh7757lcr.o
diff --git a/arch/sh/boards/board-sh2007.c b/arch/sh/boards/board-sh2007.c
new file mode 100644 (file)
index 0000000..b90b78f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * SH-2007 board support.
+ *
+ * Copyright (C) 2003, 2004  SUGIOKA Toshinobu
+ * Copyright (C) 2010  Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smsc911x.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/io.h>
+#include <asm/machvec.h>
+#include <mach/sh2007.h>
+
+struct smsc911x_platform_config smc911x_info = {
+       .flags          = SMSC911X_USE_32BIT,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct resource smsc9118_0_resources[] = {
+       [0] = {
+               .start  = SMC0_BASE,
+               .end    = SMC0_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x240),
+               .end    = evt2irq(0x240),
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource smsc9118_1_resources[] = {
+       [0] = {
+               .start  = SMC1_BASE,
+               .end    = SMC1_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x280),
+               .end    = evt2irq(0x280),
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smsc9118_0_device = {
+       .name           = "smsc911x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smsc9118_0_resources),
+       .resource       = smsc9118_0_resources,
+       .dev = {
+               .platform_data = &smc911x_info,
+       },
+};
+
+static struct platform_device smsc9118_1_device = {
+       .name           = "smsc911x",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(smsc9118_1_resources),
+       .resource       = smsc9118_1_resources,
+       .dev = {
+               .platform_data = &smc911x_info,
+       },
+};
+
+static struct resource cf_resources[] = {
+       [0] = {
+               .start  = CF_BASE + CF_OFFSET,
+               .end    = CF_BASE + CF_OFFSET + 0x0f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = CF_BASE + CF_OFFSET + 0x206,
+               .end    = CF_BASE + CF_OFFSET + 0x20f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = evt2irq(0x2c0),
+               .end    = evt2irq(0x2c0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_device  = {
+       .name           = "pata_platform",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(cf_resources),
+       .resource       = cf_resources,
+};
+
+static struct platform_device *sh2007_devices[] __initdata = {
+       &smsc9118_0_device,
+       &smsc9118_1_device,
+       &cf_device,
+};
+
+static int __init sh2007_io_init(void)
+{
+       platform_add_devices(sh2007_devices, ARRAY_SIZE(sh2007_devices));
+       return 0;
+}
+subsys_initcall(sh2007_io_init);
+
+static void __init sh2007_init_irq(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ);
+}
+
+/*
+ * Initialize the board
+ */
+static void __init sh2007_setup(char **cmdline_p)
+{
+       printk(KERN_INFO "SH-2007 Setup...");
+
+       /* setup wait control registers for area 5 */
+       __raw_writel(CS5BCR_D, CS5BCR);
+       __raw_writel(CS5WCR_D, CS5WCR);
+       __raw_writel(CS5PCR_D, CS5PCR);
+
+       printk(KERN_INFO " done.\n");
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh2007 __initmv = {
+       .mv_setup               = sh2007_setup,
+       .mv_name                = "sh2007",
+       .mv_init_irq            = sh2007_init_irq,
+};
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
new file mode 100644 (file)
index 0000000..c475f10
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Renesas R0P7757LC0012RL Support.
+ *
+ * Copyright (C) 2009 - 2010  Renesas Solutions Corp.
+ *
+ * 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 <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/io.h>
+#include <cpu/sh7757.h>
+#include <asm/sh_eth.h>
+#include <asm/heartbeat.h>
+
+static struct resource heartbeat_resource = {
+       .start  = 0xffec005c,   /* PUDR */
+       .end    = 0xffec005c,
+       .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+};
+
+static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 };
+
+static struct heartbeat_data heartbeat_data = {
+       .bit_pos        = heartbeat_bit_pos,
+       .nr_bits        = ARRAY_SIZE(heartbeat_bit_pos),
+       .flags          = HEARTBEAT_INVERTED,
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = &heartbeat_data,
+       },
+       .num_resources  = 1,
+       .resource       = &heartbeat_resource,
+};
+
+/* Fast Ethernet */
+static struct resource sh_eth0_resources[] = {
+       {
+               .start  = 0xfef00000,
+               .end    = 0xfef001ff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 84,
+               .end    = 84,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sh_eth_plat_data sh7757_eth0_pdata = {
+       .phy = 1,
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh7757_eth0_device = {
+       .name           = "sh-eth",
+       .resource       = sh_eth0_resources,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(sh_eth0_resources),
+       .dev            = {
+               .platform_data = &sh7757_eth0_pdata,
+       },
+};
+
+static struct resource sh_eth1_resources[] = {
+       {
+               .start  = 0xfef00800,
+               .end    = 0xfef009ff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 84,
+               .end    = 84,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sh_eth_plat_data sh7757_eth1_pdata = {
+       .phy = 1,
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh7757_eth1_device = {
+       .name           = "sh-eth",
+       .resource       = sh_eth1_resources,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(sh_eth1_resources),
+       .dev            = {
+               .platform_data = &sh7757_eth1_pdata,
+       },
+};
+
+static struct platform_device *sh7757lcr_devices[] __initdata = {
+       &heartbeat_device,
+       &sh7757_eth0_device,
+       &sh7757_eth1_device,
+};
+
+static int __init sh7757lcr_devices_setup(void)
+{
+       /* RGMII (PTA) */
+       gpio_request(GPIO_FN_ET0_MDC, NULL);
+       gpio_request(GPIO_FN_ET0_MDIO, NULL);
+       gpio_request(GPIO_FN_ET1_MDC, NULL);
+       gpio_request(GPIO_FN_ET1_MDIO, NULL);
+
+       /* ONFI (PTB, PTZ) */
+       gpio_request(GPIO_FN_ON_NRE, NULL);
+       gpio_request(GPIO_FN_ON_NWE, NULL);
+       gpio_request(GPIO_FN_ON_NWP, NULL);
+       gpio_request(GPIO_FN_ON_NCE0, NULL);
+       gpio_request(GPIO_FN_ON_R_B0, NULL);
+       gpio_request(GPIO_FN_ON_ALE, NULL);
+       gpio_request(GPIO_FN_ON_CLE, NULL);
+
+       gpio_request(GPIO_FN_ON_DQ7, NULL);
+       gpio_request(GPIO_FN_ON_DQ6, NULL);
+       gpio_request(GPIO_FN_ON_DQ5, NULL);
+       gpio_request(GPIO_FN_ON_DQ4, NULL);
+       gpio_request(GPIO_FN_ON_DQ3, NULL);
+       gpio_request(GPIO_FN_ON_DQ2, NULL);
+       gpio_request(GPIO_FN_ON_DQ1, NULL);
+       gpio_request(GPIO_FN_ON_DQ0, NULL);
+
+       /* IRQ8 to 0 (PTB, PTC) */
+       gpio_request(GPIO_FN_IRQ8, NULL);
+       gpio_request(GPIO_FN_IRQ7, NULL);
+       gpio_request(GPIO_FN_IRQ6, NULL);
+       gpio_request(GPIO_FN_IRQ5, NULL);
+       gpio_request(GPIO_FN_IRQ4, NULL);
+       gpio_request(GPIO_FN_IRQ3, NULL);
+       gpio_request(GPIO_FN_IRQ2, NULL);
+       gpio_request(GPIO_FN_IRQ1, NULL);
+       gpio_request(GPIO_FN_IRQ0, NULL);
+
+       /* SPI0 (PTD) */
+       gpio_request(GPIO_FN_SP0_MOSI, NULL);
+       gpio_request(GPIO_FN_SP0_MISO, NULL);
+       gpio_request(GPIO_FN_SP0_SCK, NULL);
+       gpio_request(GPIO_FN_SP0_SCK_FB, NULL);
+       gpio_request(GPIO_FN_SP0_SS0, NULL);
+       gpio_request(GPIO_FN_SP0_SS1, NULL);
+       gpio_request(GPIO_FN_SP0_SS2, NULL);
+       gpio_request(GPIO_FN_SP0_SS3, NULL);
+
+       /* RMII 0/1 (PTE, PTF) */
+       gpio_request(GPIO_FN_RMII0_CRS_DV, NULL);
+       gpio_request(GPIO_FN_RMII0_TXD1, NULL);
+       gpio_request(GPIO_FN_RMII0_TXD0, NULL);
+       gpio_request(GPIO_FN_RMII0_TXEN, NULL);
+       gpio_request(GPIO_FN_RMII0_REFCLK, NULL);
+       gpio_request(GPIO_FN_RMII0_RXD1, NULL);
+       gpio_request(GPIO_FN_RMII0_RXD0, NULL);
+       gpio_request(GPIO_FN_RMII0_RX_ER, NULL);
+       gpio_request(GPIO_FN_RMII1_CRS_DV, NULL);
+       gpio_request(GPIO_FN_RMII1_TXD1, NULL);
+       gpio_request(GPIO_FN_RMII1_TXD0, NULL);
+       gpio_request(GPIO_FN_RMII1_TXEN, NULL);
+       gpio_request(GPIO_FN_RMII1_REFCLK, NULL);
+       gpio_request(GPIO_FN_RMII1_RXD1, NULL);
+       gpio_request(GPIO_FN_RMII1_RXD0, NULL);
+       gpio_request(GPIO_FN_RMII1_RX_ER, NULL);
+
+       /* eMMC (PTG) */
+       gpio_request(GPIO_FN_MMCCLK, NULL);
+       gpio_request(GPIO_FN_MMCCMD, NULL);
+       gpio_request(GPIO_FN_MMCDAT7, NULL);
+       gpio_request(GPIO_FN_MMCDAT6, NULL);
+       gpio_request(GPIO_FN_MMCDAT5, NULL);
+       gpio_request(GPIO_FN_MMCDAT4, NULL);
+       gpio_request(GPIO_FN_MMCDAT3, NULL);
+       gpio_request(GPIO_FN_MMCDAT2, NULL);
+       gpio_request(GPIO_FN_MMCDAT1, NULL);
+       gpio_request(GPIO_FN_MMCDAT0, NULL);
+
+       /* LPC (PTG, PTH, PTQ, PTU) */
+       gpio_request(GPIO_FN_SERIRQ, NULL);
+       gpio_request(GPIO_FN_LPCPD, NULL);
+       gpio_request(GPIO_FN_LDRQ, NULL);
+       gpio_request(GPIO_FN_WP, NULL);
+       gpio_request(GPIO_FN_FMS0, NULL);
+       gpio_request(GPIO_FN_LAD3, NULL);
+       gpio_request(GPIO_FN_LAD2, NULL);
+       gpio_request(GPIO_FN_LAD1, NULL);
+       gpio_request(GPIO_FN_LAD0, NULL);
+       gpio_request(GPIO_FN_LFRAME, NULL);
+       gpio_request(GPIO_FN_LRESET, NULL);
+       gpio_request(GPIO_FN_LCLK, NULL);
+       gpio_request(GPIO_FN_LGPIO7, NULL);
+       gpio_request(GPIO_FN_LGPIO6, NULL);
+       gpio_request(GPIO_FN_LGPIO5, NULL);
+       gpio_request(GPIO_FN_LGPIO4, NULL);
+
+       /* SPI1 (PTH) */
+       gpio_request(GPIO_FN_SP1_MOSI, NULL);
+       gpio_request(GPIO_FN_SP1_MISO, NULL);
+       gpio_request(GPIO_FN_SP1_SCK, NULL);
+       gpio_request(GPIO_FN_SP1_SCK_FB, NULL);
+       gpio_request(GPIO_FN_SP1_SS0, NULL);
+       gpio_request(GPIO_FN_SP1_SS1, NULL);
+
+       /* SDHI (PTI) */
+       gpio_request(GPIO_FN_SD_WP, NULL);
+       gpio_request(GPIO_FN_SD_CD, NULL);
+       gpio_request(GPIO_FN_SD_CLK, NULL);
+       gpio_request(GPIO_FN_SD_CMD, NULL);
+       gpio_request(GPIO_FN_SD_D3, NULL);
+       gpio_request(GPIO_FN_SD_D2, NULL);
+       gpio_request(GPIO_FN_SD_D1, NULL);
+       gpio_request(GPIO_FN_SD_D0, NULL);
+
+       /* SCIF3/4 (PTJ, PTW) */
+       gpio_request(GPIO_FN_RTS3, NULL);
+       gpio_request(GPIO_FN_CTS3, NULL);
+       gpio_request(GPIO_FN_TXD3, NULL);
+       gpio_request(GPIO_FN_RXD3, NULL);
+       gpio_request(GPIO_FN_RTS4, NULL);
+       gpio_request(GPIO_FN_RXD4, NULL);
+       gpio_request(GPIO_FN_TXD4, NULL);
+       gpio_request(GPIO_FN_CTS4, NULL);
+
+       /* SERMUX (PTK, PTL, PTO, PTV) */
+       gpio_request(GPIO_FN_COM2_TXD, NULL);
+       gpio_request(GPIO_FN_COM2_RXD, NULL);
+       gpio_request(GPIO_FN_COM2_RTS, NULL);
+       gpio_request(GPIO_FN_COM2_CTS, NULL);
+       gpio_request(GPIO_FN_COM2_DTR, NULL);
+       gpio_request(GPIO_FN_COM2_DSR, NULL);
+       gpio_request(GPIO_FN_COM2_DCD, NULL);
+       gpio_request(GPIO_FN_COM2_RI, NULL);
+       gpio_request(GPIO_FN_RAC_RXD, NULL);
+       gpio_request(GPIO_FN_RAC_RTS, NULL);
+       gpio_request(GPIO_FN_RAC_CTS, NULL);
+       gpio_request(GPIO_FN_RAC_DTR, NULL);
+       gpio_request(GPIO_FN_RAC_DSR, NULL);
+       gpio_request(GPIO_FN_RAC_DCD, NULL);
+       gpio_request(GPIO_FN_RAC_TXD, NULL);
+       gpio_request(GPIO_FN_COM1_TXD, NULL);
+       gpio_request(GPIO_FN_COM1_RXD, NULL);
+       gpio_request(GPIO_FN_COM1_RTS, NULL);
+       gpio_request(GPIO_FN_COM1_CTS, NULL);
+
+       writeb(0x10, 0xfe470000);       /* SMR0: SerMux mode 0 */
+
+       /* IIC (PTM, PTR, PTS) */
+       gpio_request(GPIO_FN_SDA7, NULL);
+       gpio_request(GPIO_FN_SCL7, NULL);
+       gpio_request(GPIO_FN_SDA6, NULL);
+       gpio_request(GPIO_FN_SCL6, NULL);
+       gpio_request(GPIO_FN_SDA5, NULL);
+       gpio_request(GPIO_FN_SCL5, NULL);
+       gpio_request(GPIO_FN_SDA4, NULL);
+       gpio_request(GPIO_FN_SCL4, NULL);
+       gpio_request(GPIO_FN_SDA3, NULL);
+       gpio_request(GPIO_FN_SCL3, NULL);
+       gpio_request(GPIO_FN_SDA2, NULL);
+       gpio_request(GPIO_FN_SCL2, NULL);
+       gpio_request(GPIO_FN_SDA1, NULL);
+       gpio_request(GPIO_FN_SCL1, NULL);
+       gpio_request(GPIO_FN_SDA0, NULL);
+       gpio_request(GPIO_FN_SCL0, NULL);
+
+       /* USB (PTN) */
+       gpio_request(GPIO_FN_VBUS_EN, NULL);
+       gpio_request(GPIO_FN_VBUS_OC, NULL);
+
+       /* SGPIO1/0 (PTN, PTO) */
+       gpio_request(GPIO_FN_SGPIO1_CLK, NULL);
+       gpio_request(GPIO_FN_SGPIO1_LOAD, NULL);
+       gpio_request(GPIO_FN_SGPIO1_DI, NULL);
+       gpio_request(GPIO_FN_SGPIO1_DO, NULL);
+       gpio_request(GPIO_FN_SGPIO0_CLK, NULL);
+       gpio_request(GPIO_FN_SGPIO0_LOAD, NULL);
+       gpio_request(GPIO_FN_SGPIO0_DI, NULL);
+       gpio_request(GPIO_FN_SGPIO0_DO, NULL);
+
+       /* WDT (PTN) */
+       gpio_request(GPIO_FN_SUB_CLKIN, NULL);
+
+       /* System (PTT) */
+       gpio_request(GPIO_FN_STATUS1, NULL);
+       gpio_request(GPIO_FN_STATUS0, NULL);
+
+       /* PWMX (PTT) */
+       gpio_request(GPIO_FN_PWMX1, NULL);
+       gpio_request(GPIO_FN_PWMX0, NULL);
+
+       /* R-SPI (PTV) */
+       gpio_request(GPIO_FN_R_SPI_MOSI, NULL);
+       gpio_request(GPIO_FN_R_SPI_MISO, NULL);
+       gpio_request(GPIO_FN_R_SPI_RSPCK, NULL);
+       gpio_request(GPIO_FN_R_SPI_SSL0, NULL);
+       gpio_request(GPIO_FN_R_SPI_SSL1, NULL);
+
+       /* EVC (PTV, PTW) */
+       gpio_request(GPIO_FN_EVENT7, NULL);
+       gpio_request(GPIO_FN_EVENT6, NULL);
+       gpio_request(GPIO_FN_EVENT5, NULL);
+       gpio_request(GPIO_FN_EVENT4, NULL);
+       gpio_request(GPIO_FN_EVENT3, NULL);
+       gpio_request(GPIO_FN_EVENT2, NULL);
+       gpio_request(GPIO_FN_EVENT1, NULL);
+       gpio_request(GPIO_FN_EVENT0, NULL);
+
+       /* LED for heartbeat */
+       gpio_request(GPIO_PTU3, NULL);
+       gpio_direction_output(GPIO_PTU3, 1);
+       gpio_request(GPIO_PTU2, NULL);
+       gpio_direction_output(GPIO_PTU2, 1);
+       gpio_request(GPIO_PTU1, NULL);
+       gpio_direction_output(GPIO_PTU1, 1);
+       gpio_request(GPIO_PTU0, NULL);
+       gpio_direction_output(GPIO_PTU0, 1);
+
+       /* control for MDIO of Gigabit Ethernet */
+       gpio_request(GPIO_PTT4, NULL);
+       gpio_direction_output(GPIO_PTT4, 1);
+
+       /* control for eMMC */
+       gpio_request(GPIO_PTT7, NULL);          /* eMMC_RST# */
+       gpio_direction_output(GPIO_PTT7, 0);
+       gpio_request(GPIO_PTT6, NULL);          /* eMMC_INDEX# */
+       gpio_direction_output(GPIO_PTT6, 0);
+       gpio_request(GPIO_PTT5, NULL);          /* eMMC_PRST# */
+       gpio_direction_output(GPIO_PTT5, 1);
+
+       /* General platform */
+       return platform_add_devices(sh7757lcr_devices,
+                                   ARRAY_SIZE(sh7757lcr_devices));
+}
+arch_initcall(sh7757lcr_devices_setup);
+
+/* Initialize IRQ setting */
+void __init init_sh7757lcr_IRQ(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ7654);
+       plat_irq_setup_pins(IRQ_MODE_IRQ3210);
+}
+
+/* Initialize the board */
+static void __init sh7757lcr_setup(char **cmdline_p)
+{
+       printk(KERN_INFO "Renesas R0P7757LC0012RL support.\n");
+}
+
+static int sh7757lcr_mode_pins(void)
+{
+       int value = 0;
+
+       /* These are the factory default settings of S3 (Low active).
+        * If you change these dip switches then you will need to
+        * adjust the values below as well.
+        */
+       value |= MODE_PIN0;     /* Clock Mode: 1 */
+
+       return value;
+}
+
+/* The Machine Vector */
+static struct sh_machine_vector mv_sh7757lcr __initmv = {
+       .mv_name                = "SH7757LCR",
+       .mv_setup               = sh7757lcr_setup,
+       .mv_init_irq            = init_sh7757lcr_IRQ,
+       .mv_mode_pins           = sh7757lcr_mode_pins,
+};
+
index 1d7b495..71a3368 100644 (file)
@@ -1248,14 +1248,14 @@ static int __init arch_setup(void)
 
        /* set SPU2 clock to 83.4 MHz */
        clk = clk_get(NULL, "spu_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 83333333));
                clk_put(clk);
        }
 
        /* change parent of FSI B */
        clk = clk_get(NULL, "fsib_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_register(&fsimckb_clk);
                clk_set_parent(clk, &fsimckb_clk);
                clk_set_rate(clk, 11000);
@@ -1273,7 +1273,7 @@ static int __init arch_setup(void)
 
        /* set VPU clock to 166 MHz */
        clk = clk_get(NULL, "vpu_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 166000000));
                clk_put(clk);
        }
index a29f19e..23ff7d4 100644 (file)
@@ -1 +1,4 @@
-obj-y  := setup.o fpga.o irq.o
+obj-y  := fpga.o irq.o setup.o
+
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
+obj-$(CONFIG_HAVE_SRAM_POOL)   += sram.o
diff --git a/arch/sh/boards/mach-sdk7786/gpio.c b/arch/sh/boards/mach-sdk7786/gpio.c
new file mode 100644 (file)
index 0000000..f71ce09
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SDK7786 FPGA USRGPIR Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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 <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/fpga.h>
+
+#define NR_FPGA_GPIOS  8
+
+static const char *usrgpir_gpio_names[NR_FPGA_GPIOS] = {
+       "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7",
+};
+
+static int usrgpir_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       /* always in */
+       return 0;
+}
+
+static int usrgpir_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+       return !!(fpga_read_reg(USRGPIR) & (1 << gpio));
+}
+
+static struct gpio_chip usrgpir_gpio_chip = {
+       .label                  = "sdk7786-fpga",
+       .names                  = usrgpir_gpio_names,
+       .direction_input        = usrgpir_gpio_direction_input,
+       .get                    = usrgpir_gpio_get,
+       .base                   = -1, /* don't care */
+       .ngpio                  = NR_FPGA_GPIOS,
+};
+
+static int __init usrgpir_gpio_setup(void)
+{
+       return gpiochip_add(&usrgpir_gpio_chip);
+}
+device_initcall(usrgpir_gpio_setup);
index 2ec1ea5..7e0c4e3 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/machvec.h>
 #include <asm/heartbeat.h>
 #include <asm/sizes.h>
+#include <asm/clock.h>
+#include <asm/clkdev.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
 
@@ -140,6 +142,45 @@ static int sdk7786_mode_pins(void)
        return fpga_read_reg(MODSWR);
 }
 
+/*
+ * FPGA-driven PCIe clocks
+ *
+ * Historically these include the oscillator, clock B (slots 2/3/4) and
+ * clock A (slot 1 and the CPU clock). Newer revs of the PCB shove
+ * everything under a single PCIe clocks enable bit that happens to map
+ * to the same bit position as the oscillator bit for earlier FPGA
+ * versions.
+ *
+ * Given that the legacy clocks have the side-effect of shutting the CPU
+ * off through the FPGA along with the PCI slots, we simply leave them in
+ * their initial state and don't bother registering them with the clock
+ * framework.
+ */
+static int sdk7786_pcie_clk_enable(struct clk *clk)
+{
+       fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR);
+       return 0;
+}
+
+static void sdk7786_pcie_clk_disable(struct clk *clk)
+{
+       fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR);
+}
+
+static struct clk_ops sdk7786_pcie_clk_ops = {
+       .enable         = sdk7786_pcie_clk_enable,
+       .disable        = sdk7786_pcie_clk_disable,
+};
+
+static struct clk sdk7786_pcie_clk = {
+       .ops            = &sdk7786_pcie_clk_ops,
+};
+
+static struct clk_lookup sdk7786_pcie_cl = {
+       .con_id         = "pcie_plat_clk",
+       .clk            = &sdk7786_pcie_clk,
+};
+
 static int sdk7786_clk_init(void)
 {
        struct clk *clk;
@@ -158,7 +199,18 @@ static int sdk7786_clk_init(void)
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
 
-       return ret;
+       /*
+        * Setup the FPGA clocks.
+        */
+       ret = clk_register(&sdk7786_pcie_clk);
+       if (unlikely(ret)) {
+               pr_err("FPGA clock registration failed\n");
+               return ret;
+       }
+
+       clkdev_add(&sdk7786_pcie_cl);
+
+       return 0;
 }
 
 static void sdk7786_restart(char *cmd)
diff --git a/arch/sh/boards/mach-sdk7786/sram.c b/arch/sh/boards/mach-sdk7786/sram.c
new file mode 100644 (file)
index 0000000..c81c3ab
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SDK7786 FPGA SRAM Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <mach/fpga.h>
+#include <asm/sram.h>
+#include <asm/sizes.h>
+
+static int __init fpga_sram_init(void)
+{
+       unsigned long phys;
+       unsigned int area;
+       void __iomem *vaddr;
+       int ret;
+       u16 data;
+
+       /* Enable FPGA SRAM */
+       data = fpga_read_reg(LCLASR);
+       data |= LCLASR_FRAMEN;
+       fpga_write_reg(data, LCLASR);
+
+       /*
+        * FPGA_SEL determines the area mapping
+        */
+       area = (data & LCLASR_FPGA_SEL_MASK) >> LCLASR_FPGA_SEL_SHIFT;
+       if (unlikely(area == LCLASR_AREA_MASK)) {
+               pr_err("FPGA memory unmapped.\n");
+               return -ENXIO;
+       }
+
+       /*
+        * The memory itself occupies a 2KiB range at the top of the area
+        * immediately below the system registers.
+        */
+       phys = (area << 26) + SZ_64M - SZ_4K;
+
+       /*
+        * The FPGA SRAM resides in translatable physical space, so set
+        * up a mapping prior to inserting it in to the pool.
+        */
+       vaddr = ioremap(phys, SZ_2K);
+       if (unlikely(!vaddr)) {
+               pr_err("Failed remapping FPGA memory.\n");
+               return -ENXIO;
+       }
+
+       pr_info("Adding %dKiB of FPGA memory at 0x%08lx-0x%08lx "
+               "(area %d) to pool.\n",
+               SZ_2K >> 10, phys, phys + SZ_2K - 1, area);
+
+       ret = gen_pool_add(sram_pool, (unsigned long)vaddr, SZ_2K, -1);
+       if (unlikely(ret < 0)) {
+               pr_err("Failed adding memory\n");
+               iounmap(vaddr);
+               return ret;
+       }
+
+       return 0;
+}
+postcore_initcall(fpga_sram_init);
index 983e455..708c21c 100644 (file)
@@ -1 +1,3 @@
 obj-y += setup.o ilsel.o
+
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c
new file mode 100644 (file)
index 0000000..594adf7
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * arch/sh/boards/mach-x3proto/gpio.c
+ *
+ * Renesas SH-X3 Prototype Baseboard GPIO Support.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/ilsel.h>
+#include <mach/hardware.h>
+
+#define KEYCTLR        0xb81c0000
+#define KEYOUTR        0xb81c0002
+#define KEYDETR 0xb81c0004
+
+static DEFINE_SPINLOCK(x3proto_gpio_lock);
+static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, };
+
+static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       unsigned long flags;
+       unsigned int data;
+
+       spin_lock_irqsave(&x3proto_gpio_lock, flags);
+       data = __raw_readw(KEYCTLR);
+       data |= (1 << gpio);
+       __raw_writew(data, KEYCTLR);
+       spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
+
+       return 0;
+}
+
+static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+       return !!(__raw_readw(KEYDETR) & (1 << gpio));
+}
+
+static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+       return x3proto_gpio_irq_map[gpio];
+}
+
+static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = get_irq_desc_chip(desc);
+       unsigned long mask;
+       int pin;
+
+       chip->mask_ack(irq);
+
+       mask = __raw_readw(KEYDETR);
+
+       for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
+               generic_handle_irq(x3proto_gpio_to_irq(NULL, pin));
+
+       chip->unmask(irq);
+}
+
+struct gpio_chip x3proto_gpio_chip = {
+       .label                  = "x3proto-gpio",
+       .direction_input        = x3proto_gpio_direction_input,
+       .get                    = x3proto_gpio_get,
+       .to_irq                 = x3proto_gpio_to_irq,
+       .base                   = -1,
+       .ngpio                  = NR_BASEBOARD_GPIOS,
+};
+
+int __init x3proto_gpio_setup(void)
+{
+       int ilsel;
+       int ret, i;
+
+       ilsel = ilsel_enable(ILSEL_KEY);
+       if (unlikely(ilsel < 0))
+               return ilsel;
+
+       ret = gpiochip_add(&x3proto_gpio_chip);
+       if (unlikely(ret))
+               goto err_gpio;
+
+       for (i = 0; i < NR_BASEBOARD_GPIOS; i++) {
+               unsigned long flags;
+               int irq = create_irq();
+
+               if (unlikely(irq < 0)) {
+                       ret = -EINVAL;
+                       goto err_irq;
+               }
+
+               spin_lock_irqsave(&x3proto_gpio_lock, flags);
+               x3proto_gpio_irq_map[i] = irq;
+               set_irq_chip_and_handler_name(irq, &dummy_irq_chip,
+                                       handle_simple_irq, "gpio");
+               spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
+       }
+
+       pr_info("registering '%s' support, handling GPIOs %u -> %u, "
+               "bound to IRQ %u\n",
+               x3proto_gpio_chip.label, x3proto_gpio_chip.base,
+               x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
+               ilsel);
+
+       set_irq_chained_handler(ilsel, x3proto_gpio_irq_handler);
+       set_irq_wake(ilsel, 1);
+
+       return 0;
+
+err_irq:
+       for (; i >= 0; --i)
+               if (x3proto_gpio_irq_map[i])
+                       destroy_irq(x3proto_gpio_irq_map[i]);
+
+       ret = gpiochip_remove(&x3proto_gpio_chip);
+       if (unlikely(ret))
+               pr_err("Failed deregistering GPIO\n");
+
+err_gpio:
+       synchronize_irq(ilsel);
+
+       ilsel_disable(ILSEL_KEY);
+
+       return ret;
+}
index 5c98427..95e3461 100644 (file)
@@ -1,20 +1,22 @@
 /*
- * arch/sh/boards/renesas/x3proto/ilsel.c
+ * arch/sh/boards/mach-x3proto/ilsel.c
  *
  * Helper routines for SH-X3 proto board ILSEL.
  *
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2010  Paul Mundt
  *
  * 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.
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/bitmap.h>
 #include <linux/io.h>
-#include <asm/ilsel.h>
+#include <mach/ilsel.h>
 
 /*
  * ILSEL is split across:
@@ -64,6 +66,8 @@ static void __ilsel_enable(ilsel_source_t set, unsigned int bit)
        unsigned int tmp, shift;
        unsigned long addr;
 
+       pr_notice("enabling ILSEL set %d\n", set);
+
        addr = mk_ilsel_addr(bit);
        shift = mk_ilsel_shift(bit);
 
@@ -92,8 +96,10 @@ int ilsel_enable(ilsel_source_t set)
 {
        unsigned int bit;
 
-       /* Aliased sources must use ilsel_enable_fixed() */
-       BUG_ON(set > ILSEL_KEY);
+       if (unlikely(set > ILSEL_KEY)) {
+               pr_err("Aliased sources must use ilsel_enable_fixed()\n");
+               return -EINVAL;
+       }
 
        do {
                bit = find_first_zero_bit(&ilsel_level_map, ILSEL_LEVELS);
@@ -140,6 +146,8 @@ void ilsel_disable(unsigned int irq)
        unsigned long addr;
        unsigned int tmp;
 
+       pr_notice("disabling ILSEL set %d\n", irq);
+
        addr = mk_ilsel_addr(irq);
 
        tmp = __raw_readw(addr);
index 102bf56..d682e2b 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * arch/sh/boards/renesas/x3proto/setup.c
+ * arch/sh/boards/mach-x3proto/setup.c
  *
  * Renesas SH-X3 Prototype Board Support.
  *
- * Copyright (C) 2007 - 2008 Paul Mundt
+ * Copyright (C) 2007 - 2010  Paul Mundt
  *
  * 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
 #include <linux/smc91x.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/input.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/m66592.h>
-#include <asm/ilsel.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <mach/ilsel.h>
+#include <mach/hardware.h>
 #include <asm/smp-ops.h>
 
 static struct resource heartbeat_resources[] = {
@@ -122,15 +126,128 @@ static struct platform_device m66592_usb_peripheral_device = {
        .resource       = m66592_usb_peripheral_resources,
 };
 
+static struct gpio_keys_button baseboard_buttons[NR_BASEBOARD_GPIOS] = {
+       {
+               .desc           = "key44",
+               .code           = KEY_POWER,
+               .active_low     = 1,
+               .wakeup         = 1,
+       }, {
+               .desc           = "key43",
+               .code           = KEY_SUSPEND,
+               .active_low     = 1,
+               .wakeup         = 1,
+       }, {
+               .desc           = "key42",
+               .code           = KEY_KATAKANAHIRAGANA,
+               .active_low     = 1,
+       }, {
+               .desc           = "key41",
+               .code           = KEY_SWITCHVIDEOMODE,
+               .active_low     = 1,
+       }, {
+               .desc           = "key34",
+               .code           = KEY_F12,
+               .active_low     = 1,
+       }, {
+               .desc           = "key33",
+               .code           = KEY_F11,
+               .active_low     = 1,
+       }, {
+               .desc           = "key32",
+               .code           = KEY_F10,
+               .active_low     = 1,
+       }, {
+               .desc           = "key31",
+               .code           = KEY_F9,
+               .active_low     = 1,
+       }, {
+               .desc           = "key24",
+               .code           = KEY_F8,
+               .active_low     = 1,
+       }, {
+               .desc           = "key23",
+               .code           = KEY_F7,
+               .active_low     = 1,
+       }, {
+               .desc           = "key22",
+               .code           = KEY_F6,
+               .active_low     = 1,
+       }, {
+               .desc           = "key21",
+               .code           = KEY_F5,
+               .active_low     = 1,
+       }, {
+               .desc           = "key14",
+               .code           = KEY_F4,
+               .active_low     = 1,
+       }, {
+               .desc           = "key13",
+               .code           = KEY_F3,
+               .active_low     = 1,
+       }, {
+               .desc           = "key12",
+               .code           = KEY_F2,
+               .active_low     = 1,
+       }, {
+               .desc           = "key11",
+               .code           = KEY_F1,
+               .active_low     = 1,
+       },
+};
+
+static struct gpio_keys_platform_data baseboard_buttons_data = {
+       .buttons        = baseboard_buttons,
+       .nbuttons       = ARRAY_SIZE(baseboard_buttons),
+};
+
+static struct platform_device baseboard_buttons_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &baseboard_buttons_data,
+       },
+};
+
 static struct platform_device *x3proto_devices[] __initdata = {
        &heartbeat_device,
        &smc91x_device,
        &r8a66597_usb_host_device,
        &m66592_usb_peripheral_device,
+       &baseboard_buttons_device,
 };
 
+static void __init x3proto_init_irq(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRL3210);
+
+       /* Set ICR0.LVLMODE */
+       __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000);
+}
+
 static int __init x3proto_devices_setup(void)
 {
+       int ret, i;
+
+       /*
+        * IRLs are only needed for ILSEL mappings, so flip over the INTC
+        * pins at a later point to enable the GPIOs to settle.
+        */
+       x3proto_init_irq();
+
+       /*
+        * Now that ILSELs are available, set up the baseboard GPIOs.
+        */
+       ret = x3proto_gpio_setup();
+       if (unlikely(ret))
+               return ret;
+
+       /*
+        * Propagate dynamic GPIOs for the baseboard button device.
+        */
+       for (i = 0; i < ARRAY_SIZE(baseboard_buttons); i++)
+               baseboard_buttons[i].gpio = x3proto_gpio_chip.base + i;
+
        r8a66597_usb_host_resources[1].start =
                r8a66597_usb_host_resources[1].end = ilsel_enable(ILSEL_USBH_I);
 
@@ -145,14 +262,6 @@ static int __init x3proto_devices_setup(void)
 }
 device_initcall(x3proto_devices_setup);
 
-static void __init x3proto_init_irq(void)
-{
-       plat_irq_setup_pins(IRQ_MODE_IRL3210);
-
-       /* Set ICR0.LVLMODE */
-       __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000);
-}
-
 static void __init x3proto_setup(char **cmdline_p)
 {
        register_smp_ops(&shx3_smp_ops);
@@ -161,5 +270,4 @@ static void __init x3proto_setup(char **cmdline_p)
 static struct sh_machine_vector mv_x3proto __initmv = {
        .mv_name                = "x3proto",
        .mv_setup               = x3proto_setup,
-       .mv_init_irq            = x3proto_init_irq,
 };
index 200c1d4..3e15032 100644 (file)
@@ -91,7 +91,9 @@ bss_start_addr:
 end_addr:
        .long   _end
 init_sr:
-       .long   0x400000F0      /* Privileged mode, Bank=0, Block=0, IMASK=0xF */
+       .long   0x500000F0      /* Privileged mode, Bank=0, Block=1, IMASK=0xF */
+kexec_magic:
+       .long   0x400000F0      /* magic used by kexec to parse zImage format */
 init_stack_addr:
        .long   stack_start
 decompress_kernel_addr:
index 9682e3a..59c3483 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_HD64461)  += hd64461.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index 238d683..e533512 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index b3bf11b..67e1506 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index 3cdee4f..ec243ca 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
index 021633b..5fcb17b 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index 365f231..e1077a0 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
index ca7fc1b..67cb109 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
 CONFIG_IPC_NS=y
index 45c18a3..496edcd 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index d4268b1..029a506 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index ad5d296..fac13de 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index 14e658e..3670e93 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
index 6be7eaa..e3c0894 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
index 4d61b77..9479872 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_AUDIT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
index 0e32a24..f1d2e1b 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index c19fcdf..9ad904a 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 984e3fe..f3d5d9f 100644 (file)
@@ -7,7 +7,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_AUDIT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index e8b5472..920b847 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
index fd88480..c77da6b 100644 (file)
@@ -8,7 +8,6 @@ CONFIG_RCU_TRACE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
index a42f7c2..a3d0810 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index 742aa61..b1a04f3 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index aed394d..ae11158 100644 (file)
@@ -6,7 +6,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
index 7a7e138..be9c474 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
index 3620a7f..1248635 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_BUG is not set
index fe22f59..c3ba6e8 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_BUG is not set
index b9b64c3..ae998c7 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index 03e7367..ed35093 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index 1a686b6..912c985 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
index 7e03451..75c92fc 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 4cfc4de..c8c5e7f 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
index b95dc76..2051821 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig
new file mode 100644 (file)
index 0000000..0d2f414
--- /dev/null
@@ -0,0 +1,212 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_IKCONFIG=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+CONFIG_MEMORY_SIZE=0x08000000
+# CONFIG_VSYSCALL is not set
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_SH_SH2007=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SH_DMA=y
+CONFIG_SH_DMA_API=y
+CONFIG_NR_DMA_CHANNELS_BOOL=y
+CONFIG_HZ_100=y
+CONFIG_CMDLINE_OVERWRITE=y
+CONFIG_CMDLINE="console=ttySC1,115200 ip=dhcp root=/dev/nfs rw nfsroot=/nfs/rootfs,rsize=1024,wsize=1024 earlyprintk=sh-sci.1"
+CONFIG_PCCARD=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPIP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NET_PKTGEN=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_RAID_ATTRS=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_EQUALIZER=y
+CONFIG_TUN=y
+CONFIG_VETH=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SH_WDT=y
+CONFIG_SSB=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_DMADEVICES=y
+CONFIG_TIMB_DMA=y
+CONFIG_EXT3_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=932
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_LIBCRC32C=y
index b804641..f92ad17 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig
new file mode 100644 (file)
index 0000000..273f3fa
--- /dev/null
@@ -0,0 +1,85 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CPU_SUBTYPE_SH7757=y
+CONFIG_MEMORY_START=0x40000000
+CONFIG_MEMORY_SIZE=0x0f000000
+CONFIG_PMB=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_SH_SH7757LCR=y
+CONFIG_HEARTBEAT=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE_OVERWRITE=y
+CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/nfs ip=dhcp"
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_PHYLIB=y
+CONFIG_VITESSE_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_INOTIFY=y
+CONFIG_ISO9660_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_SQUASHFS=y
+CONFIG_MINIX_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 3618767..4795364 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
 CONFIG_IPC_NS=y
index ee6b81f..51561f5 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index bb4f60c..3f92d37 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEM_RES_CTLR=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
index f38c983..7eae4e5 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
index 7007d00..b58dfc5 100644 (file)
@@ -1,6 +1,5 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 45c309f..0f55891 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index e107d42..2d288b8 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index 4a27722..f46848f 100644 (file)
@@ -412,8 +412,8 @@ EXPORT_SYMBOL(unregister_dmac);
 static int __init dma_api_init(void)
 {
        printk(KERN_NOTICE "DMA: Registering DMA API.\n");
-       create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
-       return 0;
+       return create_proc_read_entry("dma", 0, 0, dma_read_proc, 0)
+                   ? 0 : -ENOMEM;
 }
 subsys_initcall(dma_api_init);
 
index 4a59e68..82f0a33 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_SH_RTS7751R2D)           += fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)                  += fixups-sh03.o
 obj-$(CONFIG_SH_HIGHLANDER)            += fixups-r7780rp.o
 obj-$(CONFIG_SH_SH7785LCR)             += fixups-r7780rp.o
+obj-$(CONFIG_SH_SDK7786)               += fixups-sdk7786.o
 obj-$(CONFIG_SH_SDK7780)               += fixups-sdk7780.o
 obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)  += fixups-sdk7780.o
 obj-$(CONFIG_SH_TITAN)                 += fixups-titan.o
diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c
new file mode 100644 (file)
index 0000000..0e18ee3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SDK7786 FPGA PCIe mux handling
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "PCI: " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <mach/fpga.h>
+
+/*
+ * The SDK7786 FPGA supports mangling of most of the slots in some way or
+ * another. Slots 3/4 are special in that only one can be supported at a
+ * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4
+ * (the horizontal edge connector) will disable slot 3 entirely.
+ *
+ * Misconfigurations can be detected through the FPGA via the slot
+ * resistors to determine card presence. Hotplug remains unsupported.
+ */
+static unsigned int slot4en __devinitdata;
+
+char *__devinit pcibios_setup(char *str)
+{
+       if (strcmp(str, "slot4en") == 0) {
+               slot4en = 1;
+               return NULL;
+       }
+
+       return str;
+}
+
+static int __init sdk7786_pci_init(void)
+{
+       u16 data = fpga_read_reg(PCIECR);
+
+       /*
+        * Enable slot #4 if it's been specified on the command line.
+        *
+        * Optionally reroute if slot #4 has a card present while slot #3
+        * does not, regardless of command line value.
+        *
+        * Card presence is logically inverted.
+        */
+       slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3));
+       if (slot4en) {
+               pr_info("Activating PCIe slot#4 (disabling slot#3)\n");
+
+               data &= ~PCIECR_PCIEMUX1;
+               fpga_write_reg(data, PCIECR);
+
+               /* Warn about forced rerouting if slot#3 is occupied */
+               if ((data & PCIECR_PRST3) == 0) {
+                       pr_warning("Unreachable card detected in slot#3\n");
+                       return -EBUSY;
+               }
+       } else
+               pr_info("PCIe slot#4 disabled\n");
+
+       return 0;
+}
+postcore_initcall(sdk7786_pci_init);
index 0b81999..b623420 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/pci.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
 #include <asm/addrspace.h>
 #include "pci-sh4.h"
 
@@ -18,8 +19,6 @@
 #define CONFIG_CMD(bus, devfn, where) \
        (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
 
-static DEFINE_SPINLOCK(sh4_pci_lock);
-
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
@@ -34,10 +33,10 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
         * PCIPDR may only be accessed as 32 bit words,
         * so we must do byte alignment by hand
         */
-       spin_lock_irqsave(&sh4_pci_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
        data = pci_read_reg(chan, SH4_PCIPDR);
-       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 
        switch (size) {
        case 1:
@@ -69,10 +68,10 @@ static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
        int shift;
        u32 data;
 
-       spin_lock_irqsave(&sh4_pci_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
        data = pci_read_reg(chan, SH4_PCIPDR);
-       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 
        switch (size) {
        case 1:
index 48f594b..1284210 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Generic SH7786 PCI-Express operations.
  *
- *  Copyright (C) 2009  Paul Mundt
+ *  Copyright (C) 2009 - 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License v2. See the file "COPYING" in the main directory of this archive
@@ -19,37 +19,72 @@ enum {
        PCI_ACCESS_WRITE,
 };
 
-static DEFINE_SPINLOCK(sh7786_pcie_lock);
-
 static int sh7786_pcie_config_access(unsigned char access_type,
                struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
 {
        struct pci_channel *chan = bus->sysdata;
-       int dev, func;
+       int dev, func, type, reg;
 
        dev = PCI_SLOT(devfn);
        func = PCI_FUNC(devfn);
+       type = !!bus->parent;
+       reg = where & ~3;
 
        if (bus->number > 255 || dev > 31 || func > 7)
                return PCIBIOS_FUNC_NOT_SUPPORTED;
-       if (devfn)
-               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * While each channel has its own memory-mapped extended config
+        * space, it's generally only accessible when in endpoint mode.
+        * When in root complex mode, the controller is unable to target
+        * itself with either type 0 or type 1 accesses, and indeed, any
+        * controller initiated target transfer to its own config space
+        * result in a completer abort.
+        *
+        * Each channel effectively only supports a single device, but as
+        * the same channel <-> device access works for any PCI_SLOT()
+        * value, we cheat a bit here and bind the controller's config
+        * space to devfn 0 in order to enable self-enumeration. In this
+        * case the regular PAR/PDR path is sidelined and the mangled
+        * config access itself is initiated as a SuperHyway transaction.
+        */
+       if (pci_is_root_bus(bus)) {
+               if (dev == 0) {
+                       if (access_type == PCI_ACCESS_READ)
+                               *data = pci_read_reg(chan, PCI_REG(reg));
+                       else
+                               pci_write_reg(chan, *data, PCI_REG(reg));
+
+                       return PCIBIOS_SUCCESSFUL;
+               } else if (dev > 1)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       /* Clear errors */
+       pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
 
        /* Set the PIO address */
        pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
-                               (func << 16) | (where & ~3), SH4A_PCIEPAR);
+                               (func << 16) | reg, SH4A_PCIEPAR);
 
        /* Enable the configuration access */
-       pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR);
+       pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
+
+       /* Check for errors */
+       if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* Check for master and target aborts */
+       if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
+               return PCIBIOS_DEVICE_NOT_FOUND;
 
        if (access_type == PCI_ACCESS_READ)
                *data = pci_read_reg(chan, SH4A_PCIEPDR);
        else
                pci_write_reg(chan, *data, SH4A_PCIEPDR);
 
-       /* Check for master and target aborts */
-       if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
-               return PCIBIOS_DEVICE_NOT_FOUND;
+       /* Disable the configuration access */
+       pci_write_reg(chan, 0, SH4A_PCIEPCTLR);
 
        return PCIBIOS_SUCCESSFUL;
 }
@@ -66,11 +101,13 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
        else if ((size == 4) && (where & 3))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       spin_lock_irqsave(&sh7786_pcie_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
                                        devfn, where, &data);
-       if (ret != PCIBIOS_SUCCESSFUL)
+       if (ret != PCIBIOS_SUCCESSFUL) {
+               *val = 0xffffffff;
                goto out;
+       }
 
        if (size == 1)
                *val = (data >> ((where & 3) << 3)) & 0xff;
@@ -84,7 +121,7 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
                devfn, where, size, (unsigned long)*val);
 
 out:
-       spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
        return ret;
 }
 
@@ -100,7 +137,7 @@ static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
        else if ((size == 4) && (where & 3))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       spin_lock_irqsave(&sh7786_pcie_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
                                        devfn, where, &data);
        if (ret != PCIBIOS_SUCCESSFUL)
@@ -124,7 +161,7 @@ static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
        ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
                                        devfn, where, &data);
 out:
-       spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
        return ret;
 }
 
index f98141b..86adb1e 100644 (file)
@@ -81,7 +81,7 @@ static int __init sh7751_pci_init(void)
        unsigned int id;
        u32 word, reg;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        chan->reg_base = 0xfe200000;
 
index ffdcbf1..edb7cca 100644 (file)
@@ -246,7 +246,7 @@ static int __init sh7780_pci_init(void)
        const char *type;
        int ret, i;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        chan->reg_base = 0xfe040000;
 
index 205dcbe..1742e2c 100644 (file)
 #ifndef _PCI_SH7780_H_
 #define _PCI_SH7780_H_
 
-#define PCI_VENDOR_ID_RENESAS          0x1912
-#define PCI_DEVICE_ID_RENESAS_SH7781   0x0001
-#define PCI_DEVICE_ID_RENESAS_SH7780   0x0002
-#define PCI_DEVICE_ID_RENESAS_SH7763   0x0004
-#define PCI_DEVICE_ID_RENESAS_SH7785   0x0007
-
 /* SH7780 Control Registers */
 #define        PCIECR                  0xFE000008
 #define PCIECR_ENBL            0x01
index 1e9598d..60ee09a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/dma-debug.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 
 unsigned long PCIBIOS_MIN_IO = 0x0000;
 unsigned long PCIBIOS_MIN_MEM = 0;
@@ -56,6 +57,11 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
        }
 }
 
+/*
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
+ */
+DEFINE_RAW_SPINLOCK(pci_config_lock);
 static DEFINE_MUTEX(pci_scan_mutex);
 
 int __devinit register_pci_controller(struct pci_channel *hose)
@@ -233,40 +239,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1<<idx)))
-                       continue;
-
-               r = &dev->resource[idx];
-               if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-                       continue;
-               if ((idx == PCI_ROM_RESOURCE) &&
-                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
-                       continue;
-               if (!r->start && r->end) {
-                       printk(KERN_ERR "PCI: Device %s not available "
-                              "because of resource collisions\n",
-                              pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n",
-                      pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
+       return pci_enable_resources(dev, mask);
 }
 
 /*
@@ -295,7 +268,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-char * __devinit pcibios_setup(char *str)
+char * __devinit __weak pcibios_setup(char *str)
 {
        return str;
 }
index 68cb9b0..96e9b05 100644 (file)
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
 #include "pcie-sh7786.h"
 #include <asm/sizes.h>
 
 struct sh7786_pcie_port {
        struct pci_channel      *hose;
+       struct clk              *fclk, phy_clk;
        unsigned int            index;
        int                     endpoint;
        int                     link;
@@ -51,6 +54,7 @@ static struct resource sh7786_pci0_resources[] = {
                .name   = "PCIe0 MEM 2",
                .start  = 0xfe100000,
                .end    = 0xfe100000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -74,6 +78,7 @@ static struct resource sh7786_pci1_resources[] = {
                .name   = "PCIe1 MEM 2",
                .start  = 0xfe300000,
                .end    = 0xfe300000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -82,6 +87,7 @@ static struct resource sh7786_pci2_resources[] = {
                .name   = "PCIe2 IO",
                .start  = 0xfc800000,
                .end    = 0xfc800000 + SZ_4M - 1,
+               .flags  = IORESOURCE_IO,
        }, {
                .name   = "PCIe2 MEM 0",
                .start  = 0x80000000,
@@ -96,6 +102,7 @@ static struct resource sh7786_pci2_resources[] = {
                .name   = "PCIe2 MEM 2",
                .start  = 0xfcd00000,
                .end    = 0xfcd00000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -117,7 +124,29 @@ static struct pci_channel sh7786_pci_channels[] = {
        DEFINE_CONTROLLER(0xfcc00000, 2),
 };
 
-static int phy_wait_for_ack(struct pci_channel *chan)
+static struct clk fixed_pciexclkp = {
+       .rate = 100000000,      /* 100 MHz reference clock */
+};
+
+static void __devinit sh7786_pci_fixup(struct pci_dev *dev)
+{
+       /*
+        * Prevent enumeration of root complex resources.
+        */
+       if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
+               int i;
+
+               for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+                       dev->resource[i].start  = 0;
+                       dev->resource[i].end    = 0;
+                       dev->resource[i].flags  = 0;
+               }
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
+                        sh7786_pci_fixup);
+
+static int __init phy_wait_for_ack(struct pci_channel *chan)
 {
        unsigned int timeout = 100;
 
@@ -131,7 +160,7 @@ static int phy_wait_for_ack(struct pci_channel *chan)
        return -ETIMEDOUT;
 }
 
-static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
+static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
 {
        unsigned int timeout = 100;
 
@@ -145,19 +174,14 @@ static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
        return -ETIMEDOUT;
 }
 
-static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
-                         unsigned int lane, unsigned int data)
+static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr,
+                                unsigned int lane, unsigned int data)
 {
-       unsigned long phyaddr, ctrl;
+       unsigned long phyaddr;
 
        phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) +
                        ((addr & 0xff) << BITS_ADR);
 
-       /* Enable clock */
-       ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-       ctrl |= (1 << BITS_CKE);
-       pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
-
        /* Set write data */
        pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR);
        pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR);
@@ -165,20 +189,74 @@ static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
        phy_wait_for_ack(chan);
 
        /* Clear command */
+       pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR);
        pci_write_reg(chan, 0, SH4A_PCIEPHYADRR);
 
        phy_wait_for_ack(chan);
+}
 
-       /* Disable clock */
-       ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-       ctrl &= ~(1 << BITS_CKE);
-       pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+static int __init pcie_clk_init(struct sh7786_pcie_port *port)
+{
+       struct pci_channel *chan = port->hose;
+       struct clk *clk;
+       char fclk_name[16];
+       int ret;
+
+       /*
+        * First register the fixed clock
+        */
+       ret = clk_register(&fixed_pciexclkp);
+       if (unlikely(ret != 0))
+               return ret;
+
+       /*
+        * Grab the port's function clock, which the PHY clock depends
+        * on. clock lookups don't help us much at this point, since no
+        * dev_id is available this early. Lame.
+        */
+       snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index);
+
+       port->fclk = clk_get(NULL, fclk_name);
+       if (IS_ERR(port->fclk)) {
+               ret = PTR_ERR(port->fclk);
+               goto err_fclk;
+       }
+
+       clk_enable(port->fclk);
+
+       /*
+        * And now, set up the PHY clock
+        */
+       clk = &port->phy_clk;
+
+       memset(clk, 0, sizeof(struct clk));
+
+       clk->parent = &fixed_pciexclkp;
+       clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR);
+       clk->enable_bit = BITS_CKE;
+
+       ret = sh_clk_mstp32_register(clk, 1);
+       if (unlikely(ret < 0))
+               goto err_phy;
+
+       return 0;
+
+err_phy:
+       clk_disable(port->fclk);
+       clk_put(port->fclk);
+err_fclk:
+       clk_unregister(&fixed_pciexclkp);
+
+       return ret;
 }
 
-static int phy_init(struct pci_channel *chan)
+static int __init phy_init(struct sh7786_pcie_port *port)
 {
+       struct pci_channel *chan = port->hose;
        unsigned int timeout = 100;
 
+       clk_enable(&port->phy_clk);
+
        /* Initialize the phy */
        phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
        phy_write_reg(chan, 0x61, 0xf, 0x00007b41);
@@ -187,9 +265,13 @@ static int phy_init(struct pci_channel *chan)
        phy_write_reg(chan, 0x66, 0xf, 0x00000010);
        phy_write_reg(chan, 0x74, 0xf, 0x0007001c);
        phy_write_reg(chan, 0x79, 0xf, 0x01fc000d);
+       phy_write_reg(chan, 0xb0, 0xf, 0x00000610);
 
        /* Deassert Standby */
-       phy_write_reg(chan, 0x67, 0xf, 0x00000400);
+       phy_write_reg(chan, 0x67, 0x1, 0x00000400);
+
+       /* Disable clock */
+       clk_disable(&port->phy_clk);
 
        while (timeout--) {
                if (pci_read_reg(chan, SH4A_PCIEPHYSR))
@@ -201,22 +283,33 @@ static int phy_init(struct pci_channel *chan)
        return -ETIMEDOUT;
 }
 
-static int pcie_init(struct sh7786_pcie_port *port)
+static void __init pcie_reset(struct sh7786_pcie_port *port)
+{
+       struct pci_channel *chan = port->hose;
+
+       pci_write_reg(chan, 1, SH4A_PCIESRSTR);
+       pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+       pci_write_reg(chan, 0, SH4A_PCIESRSTR);
+       pci_write_reg(chan, 0, SH4A_PCIETXVC0SR);
+}
+
+static int __init pcie_init(struct sh7786_pcie_port *port)
 {
        struct pci_channel *chan = port->hose;
        unsigned int data;
        phys_addr_t memphys;
        size_t memsize;
-       int ret, i;
+       int ret, i, win;
 
        /* Begin initialization */
-       pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+       pcie_reset(port);
 
-       /* Initialize as type1. */
-       data = pci_read_reg(chan, SH4A_PCIEPCICONF3);
-       data &= ~(0x7f << 16);
-       data |= PCI_HEADER_TYPE_BRIDGE << 16;
-       pci_write_reg(chan, data, SH4A_PCIEPCICONF3);
+       /*
+        * Initial header for port config space is type 1, set the device
+        * class to match. Hardware takes care of propagating the IDSETR
+        * settings, so there is no need to bother with a quirk.
+        */
+       pci_write_reg(chan, PCI_CLASS_BRIDGE_PCI << 16, SH4A_PCIEIDSETR1);
 
        /* Initialize default capabilities. */
        data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);
@@ -268,30 +361,33 @@ static int pcie_init(struct sh7786_pcie_port *port)
         * LAR1/LAMR1.
         */
        if (memsize > SZ_512M) {
-               __raw_writel(memphys + SZ_512M, chan->reg_base + SH4A_PCIELAR1);
-               __raw_writel(((memsize - SZ_512M) - SZ_256) | 1,
-                            chan->reg_base + SH4A_PCIELAMR1);
+               pci_write_reg(chan, memphys + SZ_512M, SH4A_PCIELAR1);
+               pci_write_reg(chan, ((memsize - SZ_512M) - SZ_256) | 1,
+                             SH4A_PCIELAMR1);
                memsize = SZ_512M;
        } else {
                /*
                 * Otherwise just zero it out and disable it.
                 */
-               __raw_writel(0, chan->reg_base + SH4A_PCIELAR1);
-               __raw_writel(0, chan->reg_base + SH4A_PCIELAMR1);
+               pci_write_reg(chan, 0, SH4A_PCIELAR1);
+               pci_write_reg(chan, 0, SH4A_PCIELAMR1);
        }
 
        /*
         * LAR0/LAMR0 covers up to the first 512MB, which is enough to
         * cover all of lowmem on most platforms.
         */
-       __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0);
-       __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0);
+       pci_write_reg(chan, memphys, SH4A_PCIELAR0);
+       pci_write_reg(chan, (memsize - SZ_256) | 1, SH4A_PCIELAMR0);
 
        /* Finish initialization */
        data = pci_read_reg(chan, SH4A_PCIETCTLR);
        data |= 0x1;
        pci_write_reg(chan, data, SH4A_PCIETCTLR);
 
+       /* Let things settle down a bit.. */
+       mdelay(100);
+
        /* Enable DL_Active Interrupt generation */
        data = pci_read_reg(chan, SH4A_PCIEDLINTENR);
        data |= PCIEDLINTENR_DLL_ACT_ENABLE;
@@ -302,9 +398,12 @@ static int pcie_init(struct sh7786_pcie_port *port)
        data |= PCIEMACCTLR_SCR_DIS | (0xff << 16);
        pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
 
+       /*
+        * This will timeout if we don't have a link, but we permit the
+        * port to register anyways in order to support hotplug on future
+        * hardware.
+        */
        ret = pci_wait_for_irq(chan, MASK_INT_TX_CTRL);
-       if (unlikely(ret != 0))
-               return -ENODEV;
 
        data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
        data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
@@ -317,35 +416,48 @@ static int pcie_init(struct sh7786_pcie_port *port)
 
        wmb();
 
-       data = pci_read_reg(chan, SH4A_PCIEMACSR);
-       printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n",
-              port->index, (data >> 20) & 0x3f);
-
+       if (ret == 0) {
+               data = pci_read_reg(chan, SH4A_PCIEMACSR);
+               printk(KERN_NOTICE "PCI: PCIe#%d x%d link detected\n",
+                      port->index, (data >> 20) & 0x3f);
+       } else
+               printk(KERN_NOTICE "PCI: PCIe#%d link down\n",
+                      port->index);
 
-       for (i = 0; i < chan->nr_resources; i++) {
+       for (i = win = 0; i < chan->nr_resources; i++) {
                struct resource *res = chan->resources + i;
                resource_size_t size;
-               u32 enable_mask;
+               u32 mask;
 
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(i));
+               /*
+                * We can't use the 32-bit mode windows in legacy 29-bit
+                * mode, so just skip them entirely.
+                */
+               if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode())
+                       continue;
 
-               size = resource_size(res);
+               pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(win));
 
                /*
                 * The PAMR mask is calculated in units of 256kB, which
                 * keeps things pretty simple.
                 */
-               __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
-                            chan->reg_base + SH4A_PCIEPAMR(i));
+               size = resource_size(res);
+               mask = (roundup_pow_of_two(size) / SZ_256K) - 1;
+               pci_write_reg(chan, mask << 18, SH4A_PCIEPAMR(win));
 
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i));
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL(i));
+               pci_write_reg(chan, upper_32_bits(res->start),
+                             SH4A_PCIEPARH(win));
+               pci_write_reg(chan, lower_32_bits(res->start),
+                             SH4A_PCIEPARL(win));
 
-               enable_mask = MASK_PARE;
+               mask = MASK_PARE;
                if (res->flags & IORESOURCE_IO)
-                       enable_mask |= MASK_SPC;
+                       mask |= MASK_SPC;
+
+               pci_write_reg(chan, mask, SH4A_PCIEPTCTLR(win));
 
-               pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(i));
+               win++;
        }
 
        return 0;
@@ -356,26 +468,33 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
         return 71;
 }
 
-static int sh7786_pcie_core_init(void)
+static int __init sh7786_pcie_core_init(void)
 {
        /* Return the number of ports */
        return test_mode_pin(MODE_PIN12) ? 3 : 2;
 }
 
-static int __devinit sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
 {
        int ret;
 
-       ret = phy_init(port->hose);
-       if (unlikely(ret < 0))
-               return ret;
-
        /*
         * Check if we are configured in endpoint or root complex mode,
         * this is a fixed pin setting that applies to all PCIe ports.
         */
        port->endpoint = test_mode_pin(MODE_PIN11);
 
+       /*
+        * Setup clocks, needed both for PHY and PCIe registers.
+        */
+       ret = pcie_clk_init(port);
+       if (unlikely(ret < 0))
+               return ret;
+
+       ret = phy_init(port);
+       if (unlikely(ret < 0))
+               return ret;
+
        ret = pcie_init(port);
        if (unlikely(ret < 0))
                return ret;
@@ -390,9 +509,10 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
 
 static int __init sh7786_pcie_init(void)
 {
+       struct clk *platclk;
        int ret = 0, i;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops;
 
@@ -407,6 +527,22 @@ static int __init sh7786_pcie_init(void)
        if (unlikely(!sh7786_pcie_ports))
                return -ENOMEM;
 
+       /*
+        * Fetch any optional platform clock associated with this block.
+        *
+        * This is a rather nasty hack for boards with spec-mocking FPGAs
+        * that have a secondary set of clocks outside of the on-chip
+        * ones that need to be accounted for before there is any chance
+        * of touching the existing MSTP bits or CPG clocks.
+        */
+       platclk = clk_get(NULL, "pcie_plat_clk");
+       if (IS_ERR(platclk)) {
+               /* Sane hardware should probably get a WARN_ON.. */
+               platclk = NULL;
+       }
+
+       clk_enable(platclk);
+
        printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports);
 
        for (i = 0; i < nr_ports; i++) {
@@ -419,8 +555,11 @@ static int __init sh7786_pcie_init(void)
                ret |= sh7786_pcie_hwops->port_init_hw(port);
        }
 
-       if (unlikely(ret))
+       if (unlikely(ret)) {
+               clk_disable(platclk);
+               clk_put(platclk);
                return ret;
+       }
 
        return 0;
 }
index 90a6992..1ee054e 100644 (file)
 #define                BITS_ERRRCV     (0)             /* 0 ERRRCV 0 */
 #define                MASK_ERRRCV     (1<<BITS_ERRRCV)
 
+/*     PCIEENBLR        */
+#define        SH4A_PCIEENBLR          (0x000008)      /* R/W - 0x0000 0001 32 */
+
 /*     PCIEECR         */
-#define        SH4A_PCIEECR            (0x000008)      /* R/W - 0x0000 0000 32 */
+#define        SH4A_PCIEECR            (0x00000C)      /* R/W - 0x0000 0000 32 */
 #define                BITS_ENBL       (0)     /* 0 ENBL 0 R/W */
 #define                MASK_ENBL       (1<<BITS_ENBL)
 
 #define                BITS_MDATA      (0)
 #define                MASK_MDATA      (0xffffffff<<BITS_MDATA)
 
+/*     PCIEUNLOCKCR    */
+#define        SH4A_PCIEUNLOCKCR       (0x000048)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIEIDR         */
+#define        SH4A_PCIEIDR            (0x000060)      /* R/W - 0x0101 1101 32 */
+
+/*     PCIEDBGCTLR     */
+#define        SH4A_PCIEDBGCTLR        (0x000100)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIEINTXR       */
+#define        SH4A_PCIEINTXR          (0x004000)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIERMSGR       */
+#define        SH4A_PCIERMSGR          (0x004010)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIERSTR        */
+#define SH4A_PCIERSTR(x)       (0x008000 + ((x) * 0x4)) /* R/W - 0x0000 0000 32 */
+
+/*     PCIESRSTR        */
+#define SH4A_PCIESRSTR         (0x008040)      /* R/W - 0x0000 0000 32 */
+
 /*     PCIEPHYCTLR     */
 #define        SH4A_PCIEPHYCTLR        (0x010000)      /* R/W - 0x0000 0000 32 */
 #define                BITS_CKE        (0)
 /*     PCIERMSGIER     */
 #define        SH4A_PCIERMSGIER        (0x004040)      /* R/W - 0x0000 0000 32 */
 
+/*     PCIEPHYCTLR     */
+#define SH4A_PCIEPHYCTLR       (0x010000)      /* R/W - 0x0000 0000 32 */
+
 /*     PCIEPHYADRR     */
 #define        SH4A_PCIEPHYADRR        (0x010004)      /* R/W - 0x0000 0000 32 */
 #define                BITS_ACK        (24)                    // Rev1.171
 #define                MASK_CFINT      (1<<BITS_CFINT)
 
 /*     PCIETSTR        */
-#define        SH4A_PCIETSTR           (0x020004)      /* R/W R/W 0x0000 0000 32  */
+#define        SH4A_PCIETSTR           (0x020004)      /* R 0x0000 0000 32  */
 
 /*     PCIEINTR        */
 #define        SH4A_PCIEINTR           (0x020008)      /* R/W R/W 0x0000 0000 32  */
 #define                BITS_INTPM                      (8)
 #define                MASK_INTPM                      (1<<BITS_INTPM)
 
+/*     PCIEEH0R        */
+#define SH4A_PCIEEHR(x)                (0x020010 + ((x) * 0x4)) /* R - 0x0000 0000 32 */
+
 /*     PCIEAIR  */
 #define        SH4A_PCIEAIR            (SH4A_PCIE_BASE + 0x020010)     /* R/W R/W 0xxxxx xxxx 32 */
 
 
 /*      PCIEERRFR       */                                                             // Rev1.18
 #define        SH4A_PCIEERRFR          (0x020020)              /* R/W R/W 0xxxxx xxxx 32 */    // Rev1.18
+
+/*     PCIEERRFER      */
+#define SH4A_PCIEERRFER                (0x020024)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEERRFR2      */
+#define SH4A_PCIEERRFR2                (0x020028)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEMSIR        */
+#define SH4A_PCIEMSIR          (0x020040)              /* R/W - 0x0000 0000 32 */
+
+/*     PCIEMSIFR       */
+#define SH4A_PCIEMSIFR         (0x020044)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEPWRCTLR     */
+#define SH4A_PCIEPWRCTLR       (0x020100)              /* R/W - 0x0000 0000 32 */
+
+/*     PCIEPCCTLR      */
+#define SH4A_PCIEPCCTLR                (0x020180)              /* R/W - 0x0000 0000 32 */
+
                                                                                        // Rev1.18
 /*     PCIELAR0        */
 #define        SH4A_PCIELAR0           (0x020200)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR0         (0x021120)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R0        (0x021124)      /* R/W R/W 0x0000 0000 - */
 #define        SH4A_PCIEDMCCCR0        (0x021128)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR0       (0x02112C)      /* R/W - 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAR1         (0x021140)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAHR1        (0x021144)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMDAR1         (0x021148)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR1         (0x021160)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R1        (0x021164)      /* R/W R/W 0x0000 0000 - */
 #define        SH4A_PCIEDMCCCR1        (0x021168)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR1       (0x02116C)      /* R/W - 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAR2         (0x021180)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAHR2        (0x021184)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMDAR2         (0x021188)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR3         (0x0211E0)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R3        (0x0211E4)      /* R/W R/W 0x0000 0000 -  */
 #define        SH4A_PCIEDMCCCR3        (0x0211E8)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR3       (0x0211EC)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEPCICONF0       (0x040000)      /* R R - 8/16/32 */
 #define        SH4A_PCIEPCICONF1       (0x040004)      /* R/W R/W 0x0008 0000 8/16/32 */
 #define        SH4A_PCIEPCICONF2       (0x040008)      /* R/W R/W 0xFF00 0000 8/16/32 */
index 0eed47b..7beb423 100644 (file)
@@ -5,5 +5,7 @@ header-y += cpu-features.h
 header-y += hw_breakpoint.h
 header-y += posix_types_32.h
 header-y += posix_types_64.h
+header-y += ptrace_32.h
+header-y += ptrace_64.h
 header-y += unistd_32.h
 header-y += unistd_64.h
index ce830fa..f38112b 100644 (file)
 #define        R_SH_GOTPC              167
 
 /* FDPIC relocs */
-#define R_SH_GOT20             70
-#define R_SH_GOTOFF20          71
-#define R_SH_GOTFUNCDESC       72
-#define R_SH_GOTFUNCDESC20     73
-#define R_SH_GOTOFFFUNCDESC    74
-#define R_SH_GOTOFFFUNCDESC20  75
-#define R_SH_FUNCDESC          76
-#define R_SH_FUNCDESC_VALUE    77
-
-#if 0 /* XXX - later .. */
-#define R_SH_GOT20             198
-#define R_SH_GOTOFF20          199
-#define R_SH_GOTFUNCDESC       200
-#define R_SH_GOTFUNCDESC20     201
-#define R_SH_GOTOFFFUNCDESC    202
-#define R_SH_GOTOFFFUNCDESC20  203
-#define R_SH_FUNCDESC          204
-#define R_SH_FUNCDESC_VALUE    205
-#endif
+#define R_SH_GOT20             201
+#define R_SH_GOTOFF20          202
+#define R_SH_GOTFUNCDESC       203
+#define R_SH_GOTFUNCDESC20     204
+#define R_SH_GOTOFFFUNCDESC    205
+#define R_SH_GOTOFFFUNCDESC20  206
+#define R_SH_FUNCDESC          207
+#define R_SH_FUNCDESC_VALUE    208
 
 /* SHmedia relocs */
 #define R_SH_IMM_LOW16         246
index 6e7cea4..bd7e79a 100644 (file)
@@ -58,7 +58,7 @@ enum fixed_addresses {
 
 #ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
-       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+       FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
 #endif
 
 #ifdef CONFIG_IOREMAP_FIXED
@@ -69,7 +69,7 @@ enum fixed_addresses {
         */
 #define FIX_N_IOREMAPS 32
        FIX_IOREMAP_BEGIN,
-       FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS,
+       FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
 #endif
 
        __end_of_fixed_addresses
index f8d9a73..04f53d3 100644 (file)
@@ -41,14 +41,12 @@ static inline int gpio_cansleep(unsigned gpio)
 
 static inline int gpio_to_irq(unsigned gpio)
 {
-       WARN_ON(1);
-       return -ENOSYS;
+       return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
 {
-       WARN_ON(1);
-       return -EINVAL;
+       return -ENOSYS;
 }
 
 #endif /* CONFIG_GPIOLIB */
index 02c2f01..45d08b6 100644 (file)
@@ -9,7 +9,7 @@
  * advised to cap this at the hard limit that they're interested in
  * through the machvec.
  */
-#define NR_IRQS                        256
+#define NR_IRQS                        512
 #define NR_IRQS_LEGACY         8       /* Legacy external IRQ0-7 */
 
 /*
index 036c331..134f398 100644 (file)
@@ -16,7 +16,6 @@ typedef insn_size_t kprobe_opcode_t;
        ? (MAX_STACK_SIZE) \
        : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
 
-#define regs_return_value(_regs)               ((_regs)->regs[0])
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
 
index 8bd952f..f0efe97 100644 (file)
@@ -37,6 +37,8 @@ struct pci_channel {
 };
 
 /* arch/sh/drivers/pci/pci.c */
+extern raw_spinlock_t pci_config_lock;
+
 extern int register_pci_controller(struct pci_channel *hose);
 extern void pcibios_report_status(unsigned int status_mask, int warn);
 
index 61a445d..46d5179 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/ptrace.h>
 #include <asm/hw_breakpoint.h>
 
 /*
@@ -194,8 +193,6 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
 
-#define user_stack_pointer(_regs)      ((_regs)->regs[15])
-
 #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
 #define PREFETCH_STRIDE                L1_CACHE_BYTES
 #define ARCH_HAS_PREFETCH
index 621bc46..2a541dd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/ptrace.h>
 #include <cpu/registers.h>
 
 /*
@@ -231,7 +230,5 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 
-#define user_stack_pointer(_regs)      ((_regs)->regs[15])
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_SH_PROCESSOR_64_H */
index 2168fde..f6edc10 100644 (file)
@@ -3,90 +3,7 @@
 
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
- *
- */
-#if defined(__SH5__)
-struct pt_regs {
-       unsigned long long pc;
-       unsigned long long sr;
-       long long syscall_nr;
-       unsigned long long regs[63];
-       unsigned long long tregs[8];
-       unsigned long long pad[2];
-};
-#else
-/*
- * GCC defines register number like this:
- * -----------------------------
- *      0 - 15 are integer registers
- *     17 - 22 are control/special registers
- *     24 - 39 fp registers
- *     40 - 47 xd registers
- *     48 -    fpscr register
- * -----------------------------
- *
- * We follows above, except:
- *     16 --- program counter (PC)
- *     22 --- syscall #
- *     23 --- floating point communication register
  */
-#define REG_REG0        0
-#define REG_REG15      15
-
-#define REG_PC         16
-
-#define REG_PR         17
-#define REG_SR         18
-#define REG_GBR                19
-#define REG_MACH       20
-#define REG_MACL       21
-
-#define REG_SYSCALL    22
-
-#define REG_FPREG0     23
-#define REG_FPREG15    38
-#define REG_XFREG0     39
-#define REG_XFREG15    54
-
-#define REG_FPSCR      55
-#define REG_FPUL       56
-
-/*
- * This struct defines the way the registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_regs {
-       unsigned long regs[16];
-       unsigned long pc;
-       unsigned long pr;
-       unsigned long sr;
-       unsigned long gbr;
-       unsigned long mach;
-       unsigned long macl;
-       long tra;
-};
-
-/*
- * This struct defines the way the DSP registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_dspregs {
-       unsigned long   a1;
-       unsigned long   a0g;
-       unsigned long   a1g;
-       unsigned long   m0;
-       unsigned long   m1;
-       unsigned long   a0;
-       unsigned long   x0;
-       unsigned long   x1;
-       unsigned long   y0;
-       unsigned long   y1;
-       unsigned long   dsr;
-       unsigned long   rs;
-       unsigned long   re;
-       unsigned long   mod;
-};
-#endif
 
 #define PTRACE_GETREGS         12      /* General registers */
 #define PTRACE_SETREGS         13
@@ -107,22 +24,102 @@ struct pt_dspregs {
 #define PT_DATA_ADDR           248     /* &(struct user)->start_data */
 #define PT_TEXT_LEN            252
 
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+#include "ptrace_64.h"
+#else
+#include "ptrace_32.h"
+#endif
+
 #ifdef __KERNEL__
+
+#include <linux/stringify.h>
+#include <linux/stddef.h>
+#include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
 #include <asm/system.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
+#define user_stack_pointer(regs)       ((unsigned long)(regs)->regs[15])
+#define kernel_stack_pointer(regs)     ((unsigned long)(regs)->regs[15])
 #define instruction_pointer(regs)      ((unsigned long)(regs)->pc)
 
 extern void show_regs(struct pt_regs *);
 
+#define arch_has_single_step() (1)
+
 /*
- * These are defined as per linux/ptrace.h.
+ * kprobe-based event tracer support
  */
-struct task_struct;
+struct pt_regs_offset {
+       const char *name;
+       int offset;
+};
 
-#define arch_has_single_step() (1)
+#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
+#define REGS_OFFSET_NAME(num)  \
+       {.name = __stringify(r##num), .offset = offsetof(struct pt_regs, regs[num])}
+#define TREGS_OFFSET_NAME(num) \
+       {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])}
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+/* Query offset/name of register from its name/offset */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+extern const struct pt_regs_offset regoffset_table[];
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs:      pt_regs from which register value is gotten.
+ * @offset:    offset number of the register.
+ *
+ * regs_get_register returns the value of a register. The @offset is the
+ * offset of the register in struct pt_regs address which specified by @regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+                                             unsigned int offset)
+{
+       if (unlikely(offset > MAX_REG_OFFSET))
+               return 0;
+       return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs:      pt_regs which contains kernel stack pointer.
+ * @addr:      address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+static inline int regs_within_kernel_stack(struct pt_regs *regs,
+                                          unsigned long addr)
+{
+       return ((addr & ~(THREAD_SIZE - 1))  ==
+               (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs:      pt_regs which contains kernel stack pointer.
+ * @n:         stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+                                                     unsigned int n)
+{
+       unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+       addr += n;
+       if (regs_within_kernel_stack(regs, (unsigned long)addr))
+               return *addr;
+       else
+               return 0;
+}
 
 struct perf_event;
 struct perf_sample_data;
diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h
new file mode 100644 (file)
index 0000000..35d9e25
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __ASM_SH_PTRACE_32_H
+#define __ASM_SH_PTRACE_32_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *      0 - 15 are integer registers
+ *     17 - 22 are control/special registers
+ *     24 - 39 fp registers
+ *     40 - 47 xd registers
+ *     48 -    fpscr register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *     16 --- program counter (PC)
+ *     22 --- syscall #
+ *     23 --- floating point communication register
+ */
+#define REG_REG0        0
+#define REG_REG15      15
+
+#define REG_PC         16
+
+#define REG_PR         17
+#define REG_SR         18
+#define REG_GBR                19
+#define REG_MACH       20
+#define REG_MACL       21
+
+#define REG_SYSCALL    22
+
+#define REG_FPREG0     23
+#define REG_FPREG15    38
+#define REG_XFREG0     39
+#define REG_XFREG15    54
+
+#define REG_FPSCR      55
+#define REG_FPUL       56
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+       unsigned long regs[16];
+       unsigned long pc;
+       unsigned long pr;
+       unsigned long sr;
+       unsigned long gbr;
+       unsigned long mach;
+       unsigned long macl;
+       long tra;
+};
+
+/*
+ * This struct defines the way the DSP registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_dspregs {
+       unsigned long   a1;
+       unsigned long   a0g;
+       unsigned long   a1g;
+       unsigned long   m0;
+       unsigned long   m1;
+       unsigned long   a0;
+       unsigned long   x0;
+       unsigned long   x1;
+       unsigned long   y0;
+       unsigned long   y1;
+       unsigned long   dsr;
+       unsigned long   rs;
+       unsigned long   re;
+       unsigned long   mod;
+};
+
+#ifdef __KERNEL__
+
+#define MAX_REG_OFFSET         offsetof(struct pt_regs, tra)
+#define regs_return_value(regs)        ((regs)->regs[0])
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_PTRACE_32_H */
diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h
new file mode 100644 (file)
index 0000000..d43c1cb
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SH_PTRACE_64_H
+#define __ASM_SH_PTRACE_64_H
+
+struct pt_regs {
+       unsigned long long pc;
+       unsigned long long sr;
+       long long syscall_nr;
+       unsigned long long regs[63];
+       unsigned long long tregs[8];
+       unsigned long long pad[2];
+};
+
+#ifdef __KERNEL__
+
+#define MAX_REG_OFFSET         offsetof(struct pt_regs, tregs[7])
+#define regs_return_value(regs)        ((regs)->regs[3])
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_PTRACE_64_H */
index 3a1fb97..0b9fe2d 100644 (file)
@@ -32,6 +32,7 @@
 #define SZ_512                         0x00000200
 
 #define SZ_1K                           0x00000400
+#define SZ_2K                           0x00000800
 #define SZ_4K                           0x00001000
 #define SZ_8K                           0x00002000
 #define SZ_16K                          0x00004000
diff --git a/arch/sh/include/asm/sram.h b/arch/sh/include/asm/sram.h
new file mode 100644 (file)
index 0000000..a2808ce
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __ASM_SRAM_H
+#define __ASM_SRAM_H
+
+#ifdef CONFIG_HAVE_SRAM_POOL
+
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+/* arch/sh/mm/sram.c */
+extern struct gen_pool *sram_pool;
+
+static inline unsigned long sram_alloc(size_t len)
+{
+       if (!sram_pool)
+               return 0UL;
+
+       return gen_pool_alloc(sram_pool, len);
+}
+
+static inline void sram_free(unsigned long addr, size_t len)
+{
+       return gen_pool_free(sram_pool, addr, len);
+}
+
+#else
+
+static inline unsigned long sram_alloc(size_t len)
+{
+       return 0;
+}
+
+static inline void sram_free(unsigned long addr, size_t len)
+{
+}
+
+#endif /* CONFIG_HAVE_SRAM_POOL */
+
+#endif /* __ASM_SRAM_H */
index 0bd7a17..1f1af5a 100644 (file)
@@ -140,8 +140,6 @@ extern unsigned int instruction_size(unsigned int insn);
 extern unsigned long cached_to_uncached;
 extern unsigned long uncached_size;
 
-extern struct dentry *sh_debugfs_root;
-
 void per_cpu_trap_init(void);
 void default_idle(void);
 void cpu_idle_wait(void);
index 51296b3..c941b27 100644 (file)
@@ -212,17 +212,16 @@ static inline reg_size_t register_align(void *val)
 }
 
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int);
+                           struct mem_access *ma, int, unsigned long address);
 
 static inline void trigger_address_error(void)
 {
-       if (__in_29bit_mode())
-               __asm__ __volatile__ (
-                       "ldc %0, sr\n\t"
-                       "mov.l @%1, %0"
-                       :
-                       : "r" (0x10000000), "r" (0x80000001)
-               );
+       __asm__ __volatile__ (
+               "ldc %0, sr\n\t"
+               "mov.l @%1, %0"
+               :
+               : "r" (0x10000000), "r" (0x80000001)
+       );
 }
 
 asmlinkage void do_address_error(struct pt_regs *regs,
index e0ac972..0df66f0 100644 (file)
@@ -21,6 +21,8 @@ extern void local_flush_tlb_kernel_range(unsigned long start,
                                         unsigned long end);
 extern void local_flush_tlb_one(unsigned long asid, unsigned long page);
 
+extern void __flush_tlb_global(void);
+
 #ifdef CONFIG_SMP
 
 extern void flush_tlb_all(void);
index 0e7f0fc..903cd61 100644 (file)
 #define __NR_pwritev           334
 #define __NR_rt_tgsigqueueinfo 335
 #define __NR_perf_event_open   336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
 
-#define NR_syscalls 337
+/* Non-multiplexed socket family */
+#define __NR_socket            340
+#define __NR_bind              341
+#define __NR_connect           342
+#define __NR_listen            343
+#define __NR_accept            344
+#define __NR_getsockname       345
+#define __NR_getpeername       346
+#define __NR_socketpair                347
+#define __NR_send              348
+#define __NR_sendto            349
+#define __NR_recv              350
+#define __NR_recvfrom          351
+#define __NR_shutdown          352
+#define __NR_setsockopt                353
+#define __NR_getsockopt                354
+#define __NR_sendmsg           355
+#define __NR_recvmsg           356
+#define __NR_recvmmsg          357
 
-#ifdef __KERNEL__
+#define NR_syscalls 358
 
-#define __IGNORE_recvmmsg
+#ifdef __KERNEL__
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 0580c33..09aa93f 100644 (file)
 #define __NR_perf_event_open   364
 #define __NR_recvmmsg          365
 #define __NR_accept4           366
+#define __NR_fanotify_init     367
+#define __NR_fanotify_mark     368
+#define __NR_prlimit64         369
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 367
+#define NR_syscalls 370
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index ab09da7..0c7c735 100644 (file)
@@ -16,6 +16,7 @@
 #define MMU_TEA                0xFFFFFFFC      /* TLB Exception Address */
 
 #define MMUCR          0xFFFFFFE0      /* MMU Control Register */
+#define MMUCR_TI       (1 << 2)        /* TLB flush bit */
 
 #define MMU_TLB_ADDRESS_ARRAY  0xF2000000
 #define MMU_PAGE_ASSOC_BIT     0x80
index e1e9096..cffd25e 100644 (file)
@@ -56,7 +56,9 @@
 #define FRQCR1                 0xffc40004
 #define FRQMR1                 0xffc40014
 #elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-#define FRQCR                  0xffc00014
+#define FRQCR0                 0xffc00000
+#define FRQCR1                 0xffc00004
+#define FRQMR1                 0xffc00014
 #else
 #define FRQCR                  0xffc00000
 #define FRQCR_PSTBY            0x0200
index f4d267e..15f3de1 100644 (file)
 
 enum {
        /* PTA */
-       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
-       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+       GPIO_PTA0, GPIO_PTA1, GPIO_PTA2, GPIO_PTA3,
+       GPIO_PTA4, GPIO_PTA5, GPIO_PTA6, GPIO_PTA7,
 
        /* PTB */
-       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
-       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+       GPIO_PTB0, GPIO_PTB1, GPIO_PTB2, GPIO_PTB3,
+       GPIO_PTB4, GPIO_PTB5, GPIO_PTB6, GPIO_PTB7,
 
        /* PTC */
-       GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
-       GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+       GPIO_PTC0, GPIO_PTC1, GPIO_PTC2, GPIO_PTC3,
+       GPIO_PTC4, GPIO_PTC5, GPIO_PTC6, GPIO_PTC7,
 
        /* PTD */
-       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
-       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+       GPIO_PTD0, GPIO_PTD1, GPIO_PTD2, GPIO_PTD3,
+       GPIO_PTD4, GPIO_PTD5, GPIO_PTD6, GPIO_PTD7,
 
        /* PTE */
-       GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
-       GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+       GPIO_PTE0, GPIO_PTE1, GPIO_PTE2, GPIO_PTE3,
+       GPIO_PTE4, GPIO_PTE5, GPIO_PTE6, GPIO_PTE7,
 
        /* PTF */
-       GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
-       GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+       GPIO_PTF0, GPIO_PTF1, GPIO_PTF2, GPIO_PTF3,
+       GPIO_PTF4, GPIO_PTF5, GPIO_PTF6, GPIO_PTF7,
 
        /* PTG */
-       GPIO_PTG7, GPIO_PTG6, GPIO_PTG5, GPIO_PTG4,
-       GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+       GPIO_PTG0, GPIO_PTG1, GPIO_PTG2, GPIO_PTG3,
+       GPIO_PTG4, GPIO_PTG5, GPIO_PTG6, GPIO_PTG7,
 
        /* PTH */
-       GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
-       GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+       GPIO_PTH0, GPIO_PTH1, GPIO_PTH2, GPIO_PTH3,
+       GPIO_PTH4, GPIO_PTH5, GPIO_PTH6, GPIO_PTH7,
 
        /* PTI */
-       GPIO_PTI7, GPIO_PTI6, GPIO_PTI5, GPIO_PTI4,
-       GPIO_PTI3, GPIO_PTI2, GPIO_PTI1, GPIO_PTI0,
+       GPIO_PTI0, GPIO_PTI1, GPIO_PTI2, GPIO_PTI3,
+       GPIO_PTI4, GPIO_PTI5, GPIO_PTI6, GPIO_PTI7,
 
        /* PTJ */
-       GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ4,
-       GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+       GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3,
+       GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV,
 
        /* PTK */
-       GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
-       GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+       GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3,
+       GPIO_PTK4, GPIO_PTK5, GPIO_PTK6, GPIO_PTK7,
 
        /* PTL */
-       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
-       GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+       GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3,
+       GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV,
 
        /* PTM */
-                  GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
-       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+       GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3,
+       GPIO_PTM4, GPIO_PTM5, GPIO_PTM6, GPIO_PTM7,
 
        /* PTN */
-       GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
-       GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+       GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3,
+       GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV,
 
        /* PTO */
-       GPIO_PTO7, GPIO_PTO6, GPIO_PTO5, GPIO_PTO4,
-       GPIO_PTO3, GPIO_PTO2, GPIO_PTO1, GPIO_PTO0,
+       GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3,
+       GPIO_PTO4, GPIO_PTO5, GPIO_PTO6, GPIO_PTO7,
 
        /* PTP */
-                  GPIO_PTP6, GPIO_PTP5, GPIO_PTP4,
-       GPIO_PTP3, GPIO_PTP2, GPIO_PTP1, GPIO_PTP0,
+       GPIO_PTP0, GPIO_PTP1, GPIO_PTP2, GPIO_PTP3,
+       GPIO_PTP4, GPIO_PTP5, GPIO_PTP6, GPIO_PTP7,
 
        /* PTQ */
-                  GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
-       GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+       GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3,
+       GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV,
 
        /* PTR */
-       GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
-       GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+       GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3,
+       GPIO_PTR4, GPIO_PTR5, GPIO_PTR6, GPIO_PTR7,
 
        /* PTS */
-       GPIO_PTS7, GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
-       GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+       GPIO_PTS0, GPIO_PTS1, GPIO_PTS2, GPIO_PTS3,
+       GPIO_PTS4, GPIO_PTS5, GPIO_PTS6, GPIO_PTS7,
 
        /* PTT */
-                             GPIO_PTT5, GPIO_PTT4,
-       GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+       GPIO_PTT0, GPIO_PTT1, GPIO_PTT2, GPIO_PTT3,
+       GPIO_PTT4, GPIO_PTT5, GPIO_PTT6, GPIO_PTT7,
 
        /* PTU */
-       GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4,
-       GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+       GPIO_PTU0, GPIO_PTU1, GPIO_PTU2, GPIO_PTU3,
+       GPIO_PTU4, GPIO_PTU5, GPIO_PTU6, GPIO_PTU7,
 
        /* PTV */
-       GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
-       GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+       GPIO_PTV0, GPIO_PTV1, GPIO_PTV2, GPIO_PTV3,
+       GPIO_PTV4, GPIO_PTV5, GPIO_PTV6, GPIO_PTV7,
 
        /* PTW */
-       GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
-       GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+       GPIO_PTW0, GPIO_PTW1, GPIO_PTW2, GPIO_PTW3,
+       GPIO_PTW4, GPIO_PTW5, GPIO_PTW6, GPIO_PTW7,
 
        /* PTX */
-       GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
-       GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+       GPIO_PTX0, GPIO_PTX1, GPIO_PTX2, GPIO_PTX3,
+       GPIO_PTX4, GPIO_PTX5, GPIO_PTX6, GPIO_PTX7,
 
        /* PTY */
-       GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
-       GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+       GPIO_PTY0, GPIO_PTY1, GPIO_PTY2, GPIO_PTY3,
+       GPIO_PTY4, GPIO_PTY5, GPIO_PTY6, GPIO_PTY7,
 
        /* PTZ */
-       GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
-       GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+       GPIO_PTZ0, GPIO_PTZ1, GPIO_PTZ2, GPIO_PTZ3,
+       GPIO_PTZ4, GPIO_PTZ5, GPIO_PTZ6, GPIO_PTZ7,
 
 
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        GPIO_FN_BS,     GPIO_FN_RDWR,   GPIO_FN_WE1,    GPIO_FN_RDY,
-       GPIO_FN_MD10,   GPIO_FN_MD9,    GPIO_FN_MD8,
-       GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4,
-       GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0,
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       GPIO_FN_D15,    GPIO_FN_D14,    GPIO_FN_D13,    GPIO_FN_D12,
-       GPIO_FN_D11,    GPIO_FN_D10,    GPIO_FN_D9,     GPIO_FN_D8,
-       GPIO_FN_ET0_MDC,                GPIO_FN_ET0_MDIO,
-       GPIO_FN_ET1_MDC,                GPIO_FN_ET1_MDIO,
-       GPIO_FN_SIM_D,  GPIO_FN_SIM_CLK,                GPIO_FN_SIM_RST,
-       GPIO_FN_WPSZ1,  GPIO_FN_WPSZ0,  GPIO_FN_FWID,   GPIO_FN_FLSHSZ,
-       GPIO_FN_LPC_SPIEN,              GPIO_FN_BASEL,
+       GPIO_FN_ET0_MDC,        GPIO_FN_ET0_MDIO,
+       GPIO_FN_ET1_MDC,        GPIO_FN_ET1_MDIO,
 
-       /* PTC (mobule: SD) */
-       GPIO_FN_SD_WP,  GPIO_FN_SD_CD,  GPIO_FN_SD_CLK, GPIO_FN_SD_CMD,
-       GPIO_FN_SD_D3,  GPIO_FN_SD_D2,  GPIO_FN_SD_D1,  GPIO_FN_SD_D0,
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       GPIO_FN_IRQ15,  GPIO_FN_IRQ14,  GPIO_FN_IRQ13,  GPIO_FN_IRQ12,
+       GPIO_FN_IRQ11,  GPIO_FN_IRQ10,  GPIO_FN_IRQ9,   GPIO_FN_IRQ8,
+       GPIO_FN_ON_NRE, GPIO_FN_ON_NWE, GPIO_FN_ON_NWP, GPIO_FN_ON_NCE0,
+       GPIO_FN_ON_R_B0,        GPIO_FN_ON_ALE, GPIO_FN_ON_CLE,
+       GPIO_FN_TCLK,
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTC (mobule: IRQ, PWMU) */
        GPIO_FN_IRQ7,   GPIO_FN_IRQ6,   GPIO_FN_IRQ5,   GPIO_FN_IRQ4,
        GPIO_FN_IRQ3,   GPIO_FN_IRQ2,   GPIO_FN_IRQ1,   GPIO_FN_IRQ0,
-       GPIO_FN_MD6,    GPIO_FN_MD5,    GPIO_FN_MD3,    GPIO_FN_MD2,
-       GPIO_FN_MD1,    GPIO_FN_MD0,    GPIO_FN_ADTRG1, GPIO_FN_ADTRG0,
-
-       /* PTE (mobule: EtherC) */
-       GPIO_FN_ET0_CRS_DV,             GPIO_FN_ET0_TXD1,
-       GPIO_FN_ET0_TXD0,               GPIO_FN_ET0_TX_EN,
-       GPIO_FN_ET0_REF_CLK,            GPIO_FN_ET0_RXD1,
-       GPIO_FN_ET0_RXD0,               GPIO_FN_ET0_RX_ER,
-
-       /* PTF (mobule: EtherC) */
-       GPIO_FN_ET1_CRS_DV,             GPIO_FN_ET1_TXD1,
-       GPIO_FN_ET1_TXD0,               GPIO_FN_ET1_TX_EN,
-       GPIO_FN_ET1_REF_CLK,            GPIO_FN_ET1_RXD1,
-       GPIO_FN_ET1_RXD0,               GPIO_FN_ET1_RX_ER,
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       GPIO_FN_STATUS0,                GPIO_FN_STATUS1,
-       GPIO_FN_PWX0,   GPIO_FN_PWX1,   GPIO_FN_PWX2,   GPIO_FN_PWX3,
-       GPIO_FN_SERIRQ, GPIO_FN_CLKRUN, GPIO_FN_LPCPD,  GPIO_FN_LDRQ,
-
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       GPIO_FN_TCLK,   GPIO_FN_RXD4,   GPIO_FN_TXD4,
+       GPIO_FN_PWMU0,  GPIO_FN_PWMU1,  GPIO_FN_PWMU2,  GPIO_FN_PWMU3,
+       GPIO_FN_PWMU4,  GPIO_FN_PWMU5,
+
+       /* PTD (mobule: SPI0, DMAC) */
+       GPIO_FN_SP0_MOSI,       GPIO_FN_SP0_MISO,       GPIO_FN_SP0_SCK,
+       GPIO_FN_SP0_SCK_FB,     GPIO_FN_SP0_SS0,        GPIO_FN_SP0_SS1,
+       GPIO_FN_SP0_SS2,        GPIO_FN_SP0_SS3,        GPIO_FN_DREQ0,
+       GPIO_FN_DACK0,          GPIO_FN_TEND0,
+
+       /* PTE (mobule: RMII) */
+       GPIO_FN_RMII0_CRS_DV,   GPIO_FN_RMII0_TXD1,     GPIO_FN_RMII0_TXD0,
+       GPIO_FN_RMII0_TXEN,     GPIO_FN_RMII0_REFCLK,   GPIO_FN_RMII0_RXD1,
+       GPIO_FN_RMII0_RXD0,     GPIO_FN_RMII0_RX_ER,
+
+       /* PTF (mobule: RMII, SerMux) */
+       GPIO_FN_RMII1_CRS_DV,   GPIO_FN_RMII1_TXD1,     GPIO_FN_RMII1_TXD0,
+       GPIO_FN_RMII1_TXEN,     GPIO_FN_RMII1_REFCLK,   GPIO_FN_RMII1_RXD1,
+       GPIO_FN_RMII1_RXD0,     GPIO_FN_RMII1_RX_ER,    GPIO_FN_RAC_RI,
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       GPIO_FN_BOOTFMS,                GPIO_FN_BOOTWP,
+       GPIO_FN_A25,    GPIO_FN_A24,    GPIO_FN_SERIRQ, GPIO_FN_WDTOVF,
+       GPIO_FN_LPCPD,  GPIO_FN_LDRQ,   GPIO_FN_MMCCLK, GPIO_FN_MMCCMD,
+
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        GPIO_FN_SP1_MOSI,               GPIO_FN_SP1_MISO,
        GPIO_FN_SP1_SCK,                GPIO_FN_SP1_SCK_FB,
        GPIO_FN_SP1_SS0,                GPIO_FN_SP1_SS1,
-       GPIO_FN_SP0_SS1,
-
-       /* PTI (mobule: INTC) */
-       GPIO_FN_IRQ15,  GPIO_FN_IRQ14,  GPIO_FN_IRQ13,  GPIO_FN_IRQ12,
-       GPIO_FN_IRQ11,  GPIO_FN_IRQ10,  GPIO_FN_IRQ9,   GPIO_FN_IRQ8,
-
-       /* PTJ (mobule: SCIF234, SERMUX) */
-       GPIO_FN_RXD3,   GPIO_FN_TXD3,   GPIO_FN_RXD2,   GPIO_FN_TXD2,
-       GPIO_FN_COM1_TXD,               GPIO_FN_COM1_RXD,
-       GPIO_FN_COM1_RTS,               GPIO_FN_COM1_CTS,
-
-       /* PTK (mobule: SERMUX) */
-       GPIO_FN_COM2_TXD,               GPIO_FN_COM2_RXD,
-       GPIO_FN_COM2_RTS,               GPIO_FN_COM2_CTS,
-       GPIO_FN_COM2_DTR,               GPIO_FN_COM2_DSR,
-       GPIO_FN_COM2_DCD,               GPIO_FN_COM2_RI,
+       GPIO_FN_WP,     GPIO_FN_FMS0,   GPIO_FN_TEND1,  GPIO_FN_DREQ1,
+       GPIO_FN_DACK1,  GPIO_FN_ADTRG1, GPIO_FN_ADTRG0,
 
-       /* PTL (mobule: SERMUX) */
-       GPIO_FN_RAC_TXD,                GPIO_FN_RAC_RXD,
-       GPIO_FN_RAC_RTS,                GPIO_FN_RAC_CTS,
-       GPIO_FN_RAC_DTR,                GPIO_FN_RAC_DSR,
-       GPIO_FN_RAC_DCD,                GPIO_FN_RAC_RI,
+       /* PTI (mobule: LBSC, SDHI) */
+       GPIO_FN_D15,    GPIO_FN_D14,    GPIO_FN_D13,    GPIO_FN_D12,
+       GPIO_FN_D11,    GPIO_FN_D10,    GPIO_FN_D9,     GPIO_FN_D8,
+       GPIO_FN_SD_WP,  GPIO_FN_SD_CD,  GPIO_FN_SD_CLK, GPIO_FN_SD_CMD,
+       GPIO_FN_SD_D3,  GPIO_FN_SD_D2,  GPIO_FN_SD_D1,  GPIO_FN_SD_D0,
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTJ (mobule: SCIF234) */
+       GPIO_FN_RTS3,   GPIO_FN_CTS3,   GPIO_FN_TXD3,   GPIO_FN_RXD3,
+       GPIO_FN_RTS4,   GPIO_FN_RXD4,   GPIO_FN_TXD4,
+
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
+       GPIO_FN_COM2_TXD,       GPIO_FN_COM2_RXD,       GPIO_FN_COM2_RTS,
+       GPIO_FN_COM2_CTS,       GPIO_FN_COM2_DTR,       GPIO_FN_COM2_DSR,
+       GPIO_FN_COM2_DCD,       GPIO_FN_CLKOUT,
+       GPIO_FN_SCK2,           GPIO_FN_SCK4,   GPIO_FN_SCK3,
+
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
+       GPIO_FN_RAC_RXD,        GPIO_FN_RAC_RTS,        GPIO_FN_RAC_CTS,
+       GPIO_FN_RAC_DTR,        GPIO_FN_RAC_DSR,        GPIO_FN_RAC_DCD,
+       GPIO_FN_RAC_TXD,        GPIO_FN_RXD2,           GPIO_FN_CS5,
+       GPIO_FN_CS6,            GPIO_FN_AUDSYNC,        GPIO_FN_AUDCK,
+       GPIO_FN_TXD2,
+
+       /* PTM (mobule: LBSC, IIC) */
+       GPIO_FN_CS4,    GPIO_FN_RD,     GPIO_FN_WE0,    GPIO_FN_CS0,
        GPIO_FN_SDA6,   GPIO_FN_SCL6,   GPIO_FN_SDA7,   GPIO_FN_SCL7,
-       GPIO_FN_WP,     GPIO_FN_FMS0,   GPIO_FN_FMS1,
-
-       /* PTN (mobule: SCIF234, EVC) */
-       GPIO_FN_SCK2,   GPIO_FN_RTS4,   GPIO_FN_RTS3,   GPIO_FN_RTS2,
-       GPIO_FN_CTS4,   GPIO_FN_CTS3,   GPIO_FN_CTS2,
-       GPIO_FN_EVENT7, GPIO_FN_EVENT6, GPIO_FN_EVENT5, GPIO_FN_EVENT4,
-       GPIO_FN_EVENT3, GPIO_FN_EVENT2, GPIO_FN_EVENT1, GPIO_FN_EVENT0,
 
-       /* PTO (mobule: SGPIO) */
-       GPIO_FN_SGPIO0_CLK,             GPIO_FN_SGPIO0_LOAD,
-       GPIO_FN_SGPIO0_DI,              GPIO_FN_SGPIO0_DO,
-       GPIO_FN_SGPIO1_CLK,             GPIO_FN_SGPIO1_LOAD,
-       GPIO_FN_SGPIO1_DI,              GPIO_FN_SGPIO1_DO,
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       GPIO_FN_VBUS_EN,        GPIO_FN_VBUS_OC,        GPIO_FN_JMCTCK,
+       GPIO_FN_JMCTMS,         GPIO_FN_JMCTDO,         GPIO_FN_JMCTDI,
+       GPIO_FN_JMCTRST,
+       GPIO_FN_SGPIO1_CLK,     GPIO_FN_SGPIO1_LOAD,    GPIO_FN_SGPIO1_DI,
+       GPIO_FN_SGPIO1_DO,      GPIO_FN_SUB_CLKIN,
 
-       /* PTP (mobule: JMC, SCIF234) */
-       GPIO_FN_JMCTCK, GPIO_FN_JMCTMS, GPIO_FN_JMCTDO, GPIO_FN_JMCTDI,
-       GPIO_FN_JMCRST, GPIO_FN_SCK4,   GPIO_FN_SCK3,
+       /* PTO (mobule: SGPIO, SerMux) */
+       GPIO_FN_SGPIO0_CLK,     GPIO_FN_SGPIO0_LOAD,    GPIO_FN_SGPIO0_DI,
+       GPIO_FN_SGPIO0_DO,      GPIO_FN_SGPIO2_CLK,     GPIO_FN_SGPIO2_LOAD,
+       GPIO_FN_SGPIO2_DI,      GPIO_FN_SGPIO2_DO,      GPIO_FN_COM1_TXD,
+       GPIO_FN_COM1_RXD,       GPIO_FN_COM1_RTS,       GPIO_FN_COM1_CTS,
 
        /* PTQ (mobule: LPC) */
        GPIO_FN_LAD3,   GPIO_FN_LAD2,   GPIO_FN_LAD1,   GPIO_FN_LAD0,
        GPIO_FN_LFRAME, GPIO_FN_LRESET, GPIO_FN_LCLK,
 
        /* PTR (mobule: GRA, IIC) */
-       GPIO_FN_DDC3,   GPIO_FN_DDC2,
-       GPIO_FN_SDA8,   GPIO_FN_SCL8,   GPIO_FN_SDA2,   GPIO_FN_SCL2,
+       GPIO_FN_DDC3,   GPIO_FN_DDC2,   GPIO_FN_SDA2,   GPIO_FN_SCL2,
        GPIO_FN_SDA1,   GPIO_FN_SCL1,   GPIO_FN_SDA0,   GPIO_FN_SCL0,
+       GPIO_FN_SDA8,   GPIO_FN_SCL8,
 
        /* PTS (mobule: GRA, IIC) */
-       GPIO_FN_DDC1,   GPIO_FN_DDC0,
-       GPIO_FN_SDA9,   GPIO_FN_SCL9,   GPIO_FN_SDA5,   GPIO_FN_SCL5,
+       GPIO_FN_DDC1,   GPIO_FN_DDC0,   GPIO_FN_SDA5,   GPIO_FN_SCL5,
        GPIO_FN_SDA4,   GPIO_FN_SCL4,   GPIO_FN_SDA3,   GPIO_FN_SCL3,
+       GPIO_FN_SDA9,   GPIO_FN_SCL9,
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       GPIO_FN_AUDSYNC,                GPIO_FN_AUDCK,
-       GPIO_FN_AUDATA3,                GPIO_FN_AUDATA2,
-       GPIO_FN_AUDATA1,                GPIO_FN_AUDATA0,
-       GPIO_FN_PWX7,   GPIO_FN_PWX6,   GPIO_FN_PWX5,   GPIO_FN_PWX4,
+       /* PTT (mobule: PWMX, AUD) */
+       GPIO_FN_PWMX7,  GPIO_FN_PWMX6,  GPIO_FN_PWMX5,  GPIO_FN_PWMX4,
+       GPIO_FN_PWMX3,  GPIO_FN_PWMX2,  GPIO_FN_PWMX1,  GPIO_FN_PWMX0,
+       GPIO_FN_AUDATA3,        GPIO_FN_AUDATA2,        GPIO_FN_AUDATA1,
+       GPIO_FN_AUDATA0,        GPIO_FN_STATUS1,        GPIO_FN_STATUS0,
 
-       /* PTU (mobule: LBSC, DMAC) */
-       GPIO_FN_CS6,    GPIO_FN_CS5,    GPIO_FN_CS4,    GPIO_FN_CS0,
-       GPIO_FN_RD,     GPIO_FN_WE0,    GPIO_FN_A25,    GPIO_FN_A24,
-       GPIO_FN_DREQ0,  GPIO_FN_DACK0,
+       /* PTU (mobule: LPC, APM) */
+       GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4,
+       GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0,
+       GPIO_FN_APMONCTL_O,     GPIO_FN_APMPWBTOUT_O,   GPIO_FN_APMSCI_O,
+       GPIO_FN_APMVDDON,       GPIO_FN_APMSLPBTN,      GPIO_FN_APMPWRBTN,
+       GPIO_FN_APMS5N,         GPIO_FN_APMS3N,
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        GPIO_FN_A23,    GPIO_FN_A22,    GPIO_FN_A21,    GPIO_FN_A20,
        GPIO_FN_A19,    GPIO_FN_A18,    GPIO_FN_A17,    GPIO_FN_A16,
-       GPIO_FN_TEND0,  GPIO_FN_DREQ1,  GPIO_FN_DACK1,  GPIO_FN_TEND1,
+       GPIO_FN_COM2_RI,        GPIO_FN_R_SPI_MOSI,     GPIO_FN_R_SPI_MISO,
+       GPIO_FN_R_SPI_RSPCK,    GPIO_FN_R_SPI_SSL0,     GPIO_FN_R_SPI_SSL1,
+       GPIO_FN_EVENT7,         GPIO_FN_EVENT6,         GPIO_FN_VBIOS_DI,
+       GPIO_FN_VBIOS_DO,       GPIO_FN_VBIOS_CLK,      GPIO_FN_VBIOS_CS,
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        GPIO_FN_A15,    GPIO_FN_A14,    GPIO_FN_A13,    GPIO_FN_A12,
        GPIO_FN_A11,    GPIO_FN_A10,    GPIO_FN_A9,     GPIO_FN_A8,
+       GPIO_FN_EVENT5, GPIO_FN_EVENT4, GPIO_FN_EVENT3, GPIO_FN_EVENT2,
+       GPIO_FN_EVENT1, GPIO_FN_EVENT0, GPIO_FN_CTS4,   GPIO_FN_CTS2,
 
-       /* PTX (mobule: LBSC) */
+       /* PTX (mobule: LBSC, SCIF, SIM) */
        GPIO_FN_A7,     GPIO_FN_A6,     GPIO_FN_A5,     GPIO_FN_A4,
        GPIO_FN_A3,     GPIO_FN_A2,     GPIO_FN_A1,     GPIO_FN_A0,
+       GPIO_FN_RTS2,   GPIO_FN_SIM_D,  GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST,
 
        /* PTY (mobule: LBSC) */
        GPIO_FN_D7,     GPIO_FN_D6,     GPIO_FN_D5,     GPIO_FN_D4,
        GPIO_FN_D3,     GPIO_FN_D2,     GPIO_FN_D1,     GPIO_FN_D0,
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       GPIO_FN_MMCDAT7,        GPIO_FN_MMCDAT6,        GPIO_FN_MMCDAT5,
+       GPIO_FN_MMCDAT4,        GPIO_FN_MMCDAT3,        GPIO_FN_MMCDAT2,
+       GPIO_FN_MMCDAT1,        GPIO_FN_MMCDAT0,
+       GPIO_FN_ON_DQ7, GPIO_FN_ON_DQ6, GPIO_FN_ON_DQ5, GPIO_FN_ON_DQ4,
+       GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0,
 };
 
 #endif /* __ASM_SH7757_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/shx3.h b/arch/sh/include/cpu-sh4/cpu/shx3.h
new file mode 100644 (file)
index 0000000..68d9080
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __CPU_SHX3_H
+#define __CPU_SHX3_H
+
+enum {
+       /* PA */
+       GPIO_PA7, GPIO_PA6, GPIO_PA5, GPIO_PA4,
+       GPIO_PA3, GPIO_PA2, GPIO_PA1, GPIO_PA0,
+
+       /* PB */
+       GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+       GPIO_PB3, GPIO_PB2, GPIO_PB1, GPIO_PB0,
+
+       /* PC */
+       GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+       GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+       /* PD */
+       GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+       GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+       /* PE */
+       GPIO_PE7, GPIO_PE6, GPIO_PE5, GPIO_PE4,
+       GPIO_PE3, GPIO_PE2, GPIO_PE1, GPIO_PE0,
+
+       /* PF */
+       GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+       GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+       /* PG */
+       GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
+       GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
+
+       /* PH */
+       GPIO_PH5, GPIO_PH4,
+       GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+
+       /* SCIF */
+       GPIO_FN_SCK3, GPIO_FN_TXD3, GPIO_FN_RXD3,
+       GPIO_FN_SCK2, GPIO_FN_TXD2, GPIO_FN_RXD2,
+       GPIO_FN_SCK1, GPIO_FN_TXD1, GPIO_FN_RXD1,
+       GPIO_FN_SCK0, GPIO_FN_TXD0, GPIO_FN_RXD0,
+
+       /* LBSC */
+       GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+       GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+       GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+       GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+       GPIO_FN_WE3, GPIO_FN_WE2, GPIO_FN_CS6, GPIO_FN_CS5,
+       GPIO_FN_CS4, GPIO_FN_CLKOUTENB, GPIO_FN_BREQ,
+       GPIO_FN_IOIS16, GPIO_FN_CE2B, GPIO_FN_CE2A, GPIO_FN_BACK,
+
+       /* DMAC */
+       GPIO_FN_DACK0, GPIO_FN_DREQ0, GPIO_FN_DRAK0,
+       GPIO_FN_DACK1, GPIO_FN_DREQ1, GPIO_FN_DRAK1,
+       GPIO_FN_DACK2, GPIO_FN_DREQ2, GPIO_FN_DRAK2,
+       GPIO_FN_DACK3, GPIO_FN_DREQ3, GPIO_FN_DRAK3,
+
+       /* INTC */
+       GPIO_FN_IRQ3, GPIO_FN_IRQ2, GPIO_FN_IRQ1, GPIO_FN_IRQ0,
+       GPIO_FN_IRL3, GPIO_FN_IRL2, GPIO_FN_IRL1, GPIO_FN_IRL0,
+       GPIO_FN_IRQOUT, GPIO_FN_STATUS1, GPIO_FN_STATUS0,
+};
+
+#endif /* __CPU_SHX3_H */
diff --git a/arch/sh/include/mach-common/mach/sh2007.h b/arch/sh/include/mach-common/mach/sh2007.h
new file mode 100644 (file)
index 0000000..48180b9
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __MACH_SH2007_H
+#define __MACH_SH2007_H
+
+#define CS5BCR         0xff802050
+#define CS5WCR         0xff802058
+#define CS5PCR         0xff802070
+
+#define BUS_SZ8                1
+#define BUS_SZ16       2
+#define BUS_SZ32       3
+
+#define PCMCIA_IODYN   1
+#define PCMCIA_ATA     0
+#define PCMCIA_IO8     2
+#define PCMCIA_IO16    3
+#define PCMCIA_COMM8   4
+#define PCMCIA_COMM16  5
+#define PCMCIA_ATTR8   6
+#define PCMCIA_ATTR16  7
+
+#define TYPE_SRAM      0
+#define TYPE_PCMCIA    4
+
+/* write-read/write-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWW5           0
+#define IWW6           3
+/* different area, read-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRWD5         2
+#define IWRWD6         2
+/* same area, read-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRWS5         2
+#define IWRWS6         2
+/* different area, read-read delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRRD5         2
+#define IWRRD6         2
+/* same area, read-read delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRRS5         0
+#define IWRRS6         2
+/* burst count (0-3:4,8,16,32) */
+#define BST5           0
+#define BST6           0
+/* bus size */
+#define SZ5            BUS_SZ16
+#define SZ6            BUS_SZ16
+/* RD hold for SRAM (0-1:0,1) */
+#define RDSPL5         0
+#define RDSPL6         0
+/* Burst pitch (0-7:0,1,2,3,4,5,6,7) */
+#define BW5            0
+#define BW6            0
+/* Multiplex (0-1:0,1) */
+#define MPX5           0
+#define MPX6           0
+/* device type */
+#define TYPE5          TYPE_PCMCIA
+#define TYPE6          TYPE_PCMCIA
+/* address setup before assert CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define ADS5           0
+#define ADS6           0
+/* address hold after negate CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define ADH5           0
+#define ADH6           0
+/* CSn assert to RD assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define RDS5           0
+#define RDS6           0
+/* RD negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define RDH5           0
+#define RDH6           0
+/* CSn assert to WE assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define WTS5           0
+#define WTS6           0
+/* WE negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define WTH5           0
+#define WTH6           0
+/* BS hold (0-1:1,2) */
+#define BSH5           0
+#define BSH6           0
+/* wait cycle (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */
+#define IW5            6       /* 60ns PIO mode 4 */
+#define IW6            15      /* 250ns */
+
+#define SAA5           PCMCIA_IODYN    /* IDE area b4000000-b5ffffff */
+#define SAB5           PCMCIA_IODYN    /* CF  area b6000000-b7ffffff */
+#define PCWA5          0       /* additional wait A (0-3:0,15,30,50) */
+#define PCWB5          0       /* additional wait B (0-3:0,15,30,50) */
+/* wait B (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */
+#define PCIW5          12
+/* Address->OE/WE assert delay A (0-7:0,1,2,3,6,9,12,15) */
+#define TEDA5          2
+/* Address->OE/WE assert delay B (0-7:0,1,2,3,6,9,12,15) */
+#define TEDB5          4
+/* OE/WE negate->Address delay A (0-7:0,1,2,3,6,9,12,15) */
+#define TEHA5          2
+/* OE/WE negate->Address delay B (0-7:0,1,2,3,6,9,12,15) */
+#define TEHB5          3
+
+#define CS5BCR_D       ((IWW5<<28)|(IWRWD5<<24)|(IWRWS5<<20)|          \
+                       (IWRRD5<<16)|(IWRRS5<<12)|(BST5<<10)|           \
+                       (SZ5<<8)|(RDSPL5<<7)|(BW5<<4)|(MPX5<<3)|TYPE5)
+#define CS5WCR_D       ((ADS5<<28)|(ADH5<<24)|(RDS5<<20)|      \
+                       (RDH5<<16)|(WTS5<<12)|(WTH5<<8)|(BSH5<<4)|IW5)
+#define CS5PCR_D       ((SAA5<<28)|(SAB5<<24)|(PCWA5<<22)|             \
+                       (PCWB5<<20)|(PCIW5<<16)|(TEDA5<<12)|            \
+                       (TEDB5<<8)|(TEHA5<<4)|TEHB5)
+
+#define SMC0_BASE       0xb0800000      /* eth0 */
+#define SMC1_BASE       0xb0900000      /* eth1 */
+#define CF_BASE         0xb6100000      /* Compact Flash (I/O area) */
+#define IDE_BASE        0xb4000000      /* IDE */
+#define PC104_IO_BASE   0xb8000000
+#define PC104_MEM_BASE  0xba000000
+#define SMC_IO_SIZE     0x100
+
+#define CF_OFFSET       0x1f0
+#define IDE_OFFSET      0x170
+
+#endif /* __MACH_SH2007_H */
index 416b621..40f0c2d 100644 (file)
 #define EXTASR         0x110
 #define SPCAR          0x120
 #define INTMSR         0x130
+
 #define PCIECR         0x140
+#define  PCIECR_PCIEMUX1       BIT(15)
+#define  PCIECR_PCIEMUX0       BIT(14)
+#define  PCIECR_PRST4          BIT(12) /* slot 4 card present */
+#define  PCIECR_PRST3          BIT(11) /* slot 3 card present */
+#define  PCIECR_PRST2          BIT(10) /* slot 2 card present */
+#define  PCIECR_PRST1          BIT(9)  /* slot 1 card present */
+#define  PCIECR_CLKEN          BIT(4)  /* oscillator enable */
+
 #define FAER           0x150
 #define USRGPIR                0x160
+
 /* 0x170 reserved */
-#define LCLASR         0x180
+
+#define LCLASR                 0x180
+#define  LCLASR_FRAMEN         BIT(15)
+
+#define  LCLASR_FPGA_SEL_SHIFT 12
+#define  LCLASR_NAND_SEL_SHIFT 8
+#define  LCLASR_NORB_SEL_SHIFT 4
+#define  LCLASR_NORA_SEL_SHIFT 0
+
+#define  LCLASR_AREA_MASK      0x7
+
+#define  LCLASR_FPGA_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_FPGA_SEL_SHIFT)
+#define  LCLASR_NAND_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NAND_SEL_SHIFT)
+#define  LCLASR_NORB_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NORB_SEL_SHIFT)
+#define  LCLASR_NORA_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NORA_SEL_SHIFT)
 
 #define SBCR           0x190
 #define  SCBR_I2CMEN   BIT(0)  /* FPGA I2C master enable */
diff --git a/arch/sh/include/mach-x3proto/mach/hardware.h b/arch/sh/include/mach-x3proto/mach/hardware.h
new file mode 100644 (file)
index 0000000..52bca57
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __MACH_X3PROTO_HARDWARE_H
+#define __MACH_X3PROTO_HARDWARE_H
+
+struct gpio_chip;
+
+/* arch/sh/boards/mach-x3proto/gpio.c */
+int x3proto_gpio_setup(void);
+extern struct gpio_chip x3proto_gpio_chip;
+
+#define NR_BASEBOARD_GPIOS     16
+
+#endif /* __MACH_X3PROTO_HARDWARE_H */
index e25f3c6..8eed6a4 100644 (file)
@@ -12,9 +12,9 @@ endif
 CFLAGS_REMOVE_return_address.o = -pg
 
 obj-y  := clkdev.o debugtraps.o dma-nommu.o dumpstack.o                \
-          idle.o io.o irq.o                                            \
-          irq_$(BITS).o machvec.o nmi_debug.o process.o                \
-          process_$(BITS).o ptrace_$(BITS).o                           \
+          idle.o io.o irq.o irq_$(BITS).o kdebugfs.o                   \
+          machvec.o nmi_debug.o process.o                              \
+          process_$(BITS).o ptrace.o ptrace_$(BITS).o                  \
           reboot.o return_address.o                                    \
           setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o            \
           syscalls_$(BITS).o time.o topology.o traps.o                 \
@@ -44,4 +44,4 @@ obj-$(CONFIG_HAS_IOPORT)      += io_generic.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)               += hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index befc255..1f800ef 100644 (file)
@@ -161,9 +161,11 @@ EXPORT_SYMBOL(clk_add_alias);
  */
 void clkdev_drop(struct clk_lookup *cl)
 {
+       struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl);
+
        mutex_lock(&clocks_mutex);
        list_del(&cl->node);
        mutex_unlock(&clocks_mutex);
-       kfree(cl);
+       kfree(cla);
 }
 EXPORT_SYMBOL(clkdev_drop);
index d180f16..b93458f 100644 (file)
@@ -150,7 +150,7 @@ void __cpuinit cpu_probe(void)
                        boot_cpu_data.type = CPU_SH7724;
                        boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
                        break;
-               case 0x50:
+               case 0x10:
                        boot_cpu_data.type = CPU_SH7757;
                        break;
                }
index b144e8a..cc122b1 100644 (file)
@@ -8,13 +8,13 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7763)      += setup-sh7763.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += setup-sh7785.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o intc-shx3.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7723)       += setup-sh7723.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7724)       += setup-sh7724.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7366)       += setup-sh7366.o
-obj-$(CONFIG_CPU_SUBTYPE_SHX3)         += setup-shx3.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3)         += setup-shx3.o intc-shx3.o
 
 # SMP setup
 smp-$(CONFIG_CPU_SHX3)                 := smp-shx3.o
@@ -40,6 +40,7 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7724)   := pinmux-sh7724.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7757)    := pinmux-sh7757.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)    := pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)    := pinmux-sh7786.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SHX3)      := pinmux-shx3.o
 
 obj-y                                  += $(clock-y)
 obj-$(CONFIG_SMP)                      += $(smp-y)
index 0a752bd..ce39a2a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SH7757 support for the clock framework
  *
- *  Copyright (C) 2009  Renesas Solutions Corp.
+ *  Copyright (C) 2009-2010  Renesas Solutions Corp.
  *
  * 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
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-static int ifc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int sfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int bfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int p1fc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                              16, 1, 1, 32, 1, 1, 1, 1 };
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+       .rate           = 48000000,
+};
 
-static void master_clk_init(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
 {
-       clk->rate = CONFIG_SH_PCLK_FREQ * 16;
-}
+       int multiplier;
 
-static struct clk_ops sh7757_master_clk_ops = {
-       .init           = master_clk_init,
-};
+       multiplier = test_mode_pin(MODE_PIN0) ? 24 : 16;
 
-static void module_clk_recalc(struct clk *clk)
-{
-       int idx = __raw_readl(FRQCR) & 0x0000000f;
-       clk->rate = clk->parent->rate / p1fc_divisors[idx];
+       return clk->parent->rate * multiplier;
 }
 
-static struct clk_ops sh7757_module_clk_ops = {
-       .recalc         = module_clk_recalc,
+static struct clk_ops pll_clk_ops = {
+       .recalc         = pll_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 8) & 0x0000000f;
-       clk->rate = clk->parent->rate / bfc_divisors[idx];
-}
+static struct clk pll_clk = {
+       .ops            = &pll_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+};
 
-static struct clk_ops sh7757_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
+static struct clk *clks[] = {
+       &extal_clk,
+       &pll_clk,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 20) & 0x0000000f;
-       clk->rate = clk->parent->rate / ifc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 1, 2, 1, 1, 4, 1, 6,
+                              1, 1, 1, 16, 1, 24, 1, 1 };
 
-static struct clk_ops sh7757_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+       .divisors = div2,
+       .nr_divisors = ARRAY_SIZE(div2),
 };
 
-static struct clk_ops *sh7757_clk_ops[] = {
-       &sh7757_master_clk_ops,
-       &sh7757_module_clk_ops,
-       &sh7757_bus_clk_ops,
-       &sh7757_cpu_clk_ops,
+static struct clk_div4_table div4_table = {
+       .div_mult_table = &div4_div_mult_table,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(sh7757_clk_ops))
-               *ops = sh7757_clk_ops[idx];
-}
+enum { DIV4_I, DIV4_SH, DIV4_P, DIV4_NR };
 
-static void shyway_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 12) & 0x0000000f;
-       clk->rate = clk->parent->rate / sfc_divisors[idx];
-}
-
-static struct clk_ops sh7757_shyway_clk_ops = {
-       .recalc         = shyway_clk_recalc,
-};
+#define DIV4(_bit, _mask, _flags) \
+  SH_CLK_DIV4(&pll_clk, FRQCR, _bit, _mask, _flags)
 
-static struct clk sh7757_shyway_clk = {
-       .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &sh7757_shyway_clk_ops,
+struct clk div4_clks[DIV4_NR] = {
+       /*
+        * P clock is always enable, because some P clock modules is used
+        * by Host PC.
+        */
+       [DIV4_P] = DIV4(0, 0x2800, CLK_ENABLE_ON_INIT),
+       [DIV4_SH] = DIV4(12, 0x00a0, CLK_ENABLE_ON_INIT),
+       [DIV4_I] = DIV4(20, 0x0004, CLK_ENABLE_ON_INIT),
 };
 
-/*
- * Additional sh7757-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *sh7757_onchip_clocks[] = {
-       &sh7757_shyway_clk,
+#define MSTPCR0                0xffc80030
+#define MSTPCR1                0xffc80034
+
+enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
+       MSTP111, MSTP110, MSTP103, MSTP102,
+       MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+       /* MSTPCR0 */
+       [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
+       [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+       /* MSTPCR1 */
+       [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
+       [MSTP113] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 13, 0),
+       [MSTP112] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 12, 0),
+       [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
+       [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
+       [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
+       [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
 
 static struct clk_lookup lookups[] = {
        /* main clocks */
-       CLKDEV_CON_ID("shyway_clk", &sh7757_shyway_clk),
+       CLKDEV_CON_ID("extal", &extal_clk),
+       CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+       CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+       CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+       /* MSTP32 clocks */
+       CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
+       CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
+       {
+               /* TMU0 */
+               .dev_id         = "sh_tmu.0",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP113],
+       }, {
+               /* TMU1 */
+               .dev_id         = "sh_tmu.1",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP114],
+       },
+       {
+               /* SCIF4 (But, ID is 2) */
+               .dev_id         = "sh-sci.2",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP112],
+       }, {
+               /* SCIF3 */
+               .dev_id         = "sh-sci.1",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP111],
+       }, {
+               /* SCIF2 */
+               .dev_id         = "sh-sci.0",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP110],
+       },
+       CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
 };
 
-static int __init sh7757_clk_init(void)
+int __init arch_clk_init(void)
 {
-       struct clk *clk = clk_get(NULL, "master_clk");
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(sh7757_onchip_clocks); i++) {
-               struct clk *clkp = sh7757_onchip_clocks[i];
+       int i, ret = 0;
 
-               clkp->parent = clk;
-               clk_register(clkp);
-               clk_enable(clkp);
-       }
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               ret |= clk_register(clks[i]);
+       for (i = 0; i < ARRAY_SIZE(lookups); i++)
+               clkdev_add(&lookups[i]);
 
-       /*
-        * Now that we have the rest of the clocks registered, we need to
-        * force the parent clock to propagate so that these clocks will
-        * automatically figure out their rate. We cheat by handing the
-        * parent clock its current rate and forcing child propagation.
-        */
-       clk_set_rate(clk, clk_get_rate(clk));
+       if (!ret)
+               ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+                                          &div4_table);
+       if (!ret)
+               ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
-       clk_put(clk);
-
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       return 0;
+       return ret;
 }
 
-arch_initcall(sh7757_clk_init);
-
index 236a628..4f70df6 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2006-2007  Renesas Technology Corp.
  *  Copyright (C) 2006-2007  Renesas Solutions Corp.
- *  Copyright (C) 2006-2007  Paul Mundt
+ *  Copyright (C) 2006-2010  Paul Mundt
  *
  * 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
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-static int ifc_divisors[] = { 1, 2, 4 ,6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
-static int cfc_divisors[] = { 1, 1, 4, 6 };
-
-#define IFC_POS                28
-#define IFC_MSK                0x0003
-#define BFC_MSK                0x000f
-#define PFC_MSK                0x000f
-#define CFC_MSK                0x0003
-#define BFC_POS                16
-#define PFC_POS                0
-#define CFC_POS                20
-
-static void master_clk_init(struct clk *clk)
-{
-       clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK];
-}
-
-static struct clk_ops shx3_master_clk_ops = {
-       .init           = master_clk_init,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+       .rate           = 16666666,
 };
 
-static unsigned long module_clk_recalc(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
 {
-       int idx = ((__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK);
-       return clk->parent->rate / pfc_divisors[idx];
+       /* PLL1 has a fixed x72 multiplier.  */
+       return clk->parent->rate * 72;
 }
 
-static struct clk_ops shx3_module_clk_ops = {
-       .recalc         = module_clk_recalc,
+static struct clk_ops pll_clk_ops = {
+       .recalc         = pll_recalc,
 };
 
-static unsigned long bus_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> BFC_POS) & BFC_MSK);
-       return clk->parent->rate / bfc_divisors[idx];
-}
+static struct clk pll_clk = {
+       .ops            = &pll_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+};
 
-static struct clk_ops shx3_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
+static struct clk *clks[] = {
+       &extal_clk,
+       &pll_clk,
 };
 
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> IFC_POS) & IFC_MSK);
-       return clk->parent->rate / ifc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+                              24, 32, 36, 48 };
 
-static struct clk_ops shx3_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+       .divisors = div2,
+       .nr_divisors = ARRAY_SIZE(div2),
 };
 
-static struct clk_ops *shx3_clk_ops[] = {
-       &shx3_master_clk_ops,
-       &shx3_module_clk_ops,
-       &shx3_bus_clk_ops,
-       &shx3_cpu_clk_ops,
+static struct clk_div4_table div4_table = {
+       .div_mult_table = &div4_div_mult_table,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(shx3_clk_ops))
-               *ops = shx3_clk_ops[idx];
-}
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_SHA, DIV4_P, DIV4_NR };
 
-static unsigned long shyway_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> CFC_POS) & CFC_MSK);
-       return clk->parent->rate / cfc_divisors[idx];
-}
+#define DIV4(_bit, _mask, _flags) \
+  SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
 
-static struct clk_ops shx3_shyway_clk_ops = {
-       .recalc         = shyway_clk_recalc,
+struct clk div4_clks[DIV4_NR] = {
+       [DIV4_P] = DIV4(0, 0x0f80, 0),
+       [DIV4_SHA] = DIV4(4, 0x0ff0, 0),
+       [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
+       [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
+       [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
+       [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
 };
 
-static struct clk shx3_shyway_clk = {
-       .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &shx3_shyway_clk_ops,
-};
-
-/*
- * Additional SHx3-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *shx3_onchip_clocks[] = {
-       &shx3_shyway_clk,
+#define MSTPCR0                0xffc00030
+#define MSTPCR1                0xffc00034
+
+enum { MSTP027, MSTP026, MSTP025, MSTP024,
+       MSTP009, MSTP008, MSTP003, MSTP002,
+       MSTP001, MSTP000, MSTP119, MSTP105,
+       MSTP104, MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+       /* MSTPCR0 */
+       [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
+       [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+       [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+       [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+       [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+       [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+       [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
+       [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+       [MSTP001] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
+       [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+       /* MSTPCR1 */
+       [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
+       [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
+       [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
 
 static struct clk_lookup lookups[] = {
        /* main clocks */
-       CLKDEV_CON_ID("shyway_clk", &shx3_shyway_clk),
+       CLKDEV_CON_ID("extal", &extal_clk),
+       CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+       CLKDEV_CON_ID("shywaya_clk", &div4_clks[DIV4_SHA]),
+       CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
+       CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+       CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+       CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+       /* MSTP32 clocks */
+       {
+               /* SCIF3 */
+               .dev_id         = "sh-sci.3",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP027],
+       }, {
+               /* SCIF2 */
+               .dev_id         = "sh-sci.2",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP026],
+       }, {
+               /* SCIF1 */
+               .dev_id         = "sh-sci.1",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP025],
+       }, {
+               /* SCIF0 */
+               .dev_id         = "sh-sci.0",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP024],
+       },
+       CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
+       CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
+       CLKDEV_CON_ID("fe1_fck", &mstp_clks[MSTP001]),
+       CLKDEV_CON_ID("fe0_fck", &mstp_clks[MSTP000]),
+       {
+               /* TMU0 */
+               .dev_id         = "sh_tmu.0",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU1 */
+               .dev_id         = "sh_tmu.1",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU2 */
+               .dev_id         = "sh_tmu.2",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU3 */
+               .dev_id         = "sh_tmu.3",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       }, {
+               /* TMU4 */
+               .dev_id         = "sh_tmu.4",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       }, {
+               /* TMU5 */
+               .dev_id         = "sh_tmu.5",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       },
+       CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
+       CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
+       CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
 };
 
 int __init arch_clk_init(void)
 {
-       struct clk *clk;
        int i, ret = 0;
 
-       cpg_clk_init();
-
-       clk = clk_get(NULL, "master_clk");
-       for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
-               struct clk *clkp = shx3_onchip_clocks[i];
-
-               clkp->parent = clk;
-               ret |= clk_register(clkp);
-       }
-
-       clk_put(clk);
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               ret |= clk_register(clks[i]);
+       for (i = 0; i < ARRAY_SIZE(lookups); i++)
+               clkdev_add(&lookups[i]);
 
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+       if (!ret)
+               ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+                                          &div4_table);
+       if (!ret)
+               ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
        return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/intc-shx3.c b/arch/sh/kernel/cpu/sh4a/intc-shx3.c
new file mode 100644 (file)
index 0000000..78c9714
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Shared support for SH-X3 interrupt controllers.
+ *
+ *  Copyright (C) 2009 - 2010  Paul Mundt
+ *
+ * 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 <linux/irq.h>
+#include <linux/io.h>
+#include <linux/init.h>
+
+#define INTACK         0xfe4100b8
+#define INTACKCLR      0xfe4100bc
+#define INTC_USERIMASK 0xfe411000
+
+#ifdef CONFIG_INTC_BALANCING
+unsigned int irq_lookup(unsigned int irq)
+{
+       return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE;
+}
+
+void irq_finish(unsigned int irq)
+{
+       __raw_writel(irq2evt(irq), INTACKCLR);
+}
+#endif
+
+static int __init shx3_irq_setup(void)
+{
+       return register_intc_userimask(INTC_USERIMASK);
+}
+arch_initcall(shx3_irq_setup);
index eddc219..b8b873d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Performance events support for SH-4A performance counters
  *
- *  Copyright (C) 2009  Paul Mundt
+ *  Copyright (C) 2009, 2010  Paul Mundt
  *
  * 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
 #define CCBR_CMDS      (1 << 1)
 #define CCBR_PPCE      (1 << 0)
 
+#ifdef CONFIG_CPU_SHX3
+/*
+ * The PMCAT location for SH-X3 CPUs was quietly moved, while the CCBR
+ * and PMCTR locations remains tentatively constant. This change remains
+ * wholly undocumented, and was simply found through trial and error.
+ *
+ * Early cuts of SH-X3 still appear to use the SH-X/SH-X2 locations, and
+ * it's unclear when this ceased to be the case. For now we always use
+ * the new location (if future parts keep up with this trend then
+ * scanning for them at runtime also remains a viable option.)
+ *
+ * The gap in the register space also suggests that there are other
+ * undocumented counters, so this will need to be revisited at a later
+ * point in time.
+ */
+#define PPC_PMCAT      0xfc100240
+#else
 #define PPC_PMCAT      0xfc100080
+#endif
 
 #define PMCAT_OVF3     (1 << 27)
 #define PMCAT_CNN3     (1 << 26)
index ed23b15..4c74bd0 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * SH7757 (A0 step) Pinmux
+ * SH7757 (B0 step) Pinmux
  *
- *  Copyright (C) 2009  Renesas Solutions Corp.
+ *  Copyright (C) 2009-2010  Renesas Solutions Corp.
  *
  *  Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
  *
- * Based on SH7757 Pinmux
+ * Based on SH7723 Pinmux
  *  Copyright (C) 2008  Magnus Damm
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -40,27 +40,27 @@ enum {
        PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
        PTI7_DATA, PTI6_DATA, PTI5_DATA, PTI4_DATA,
        PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA,
-       PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+                  PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
        PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
        PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
        PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
-       PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+                  PTL6_DATA, PTL5_DATA, PTL4_DATA,
        PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
-       PTM6_DATA, PTM5_DATA, PTM4_DATA,
+       PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
        PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
-       PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+                  PTN6_DATA, PTN5_DATA, PTN4_DATA,
        PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
        PTO7_DATA, PTO6_DATA, PTO5_DATA, PTO4_DATA,
        PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA,
-       PTP6_DATA, PTP5_DATA, PTP4_DATA,
+       PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA,
        PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA,
-       PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+                  PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
        PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
        PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
        PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
        PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA,
        PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
-       PTT5_DATA, PTT4_DATA,
+       PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
        PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
        PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
        PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
@@ -95,27 +95,27 @@ enum {
        PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
        PTI7_IN, PTI6_IN, PTI5_IN, PTI4_IN,
        PTI3_IN, PTI2_IN, PTI1_IN, PTI0_IN,
-       PTJ7_IN, PTJ6_IN, PTJ5_IN, PTJ4_IN,
+                PTJ6_IN, PTJ5_IN, PTJ4_IN,
        PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
        PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN,
        PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
-       PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+                PTL6_IN, PTL5_IN, PTL4_IN,
        PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
-       PTM6_IN, PTM5_IN, PTM4_IN,
+       PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
        PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
-       PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+                PTN6_IN, PTN5_IN, PTN4_IN,
        PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
        PTO7_IN, PTO6_IN, PTO5_IN, PTO4_IN,
        PTO3_IN, PTO2_IN, PTO1_IN, PTO0_IN,
-       PTP6_IN, PTP5_IN, PTP4_IN,
+       PTP7_IN, PTP6_IN, PTP5_IN, PTP4_IN,
        PTP3_IN, PTP2_IN, PTP1_IN, PTP0_IN,
-       PTQ6_IN, PTQ5_IN, PTQ4_IN,
+                PTQ6_IN, PTQ5_IN, PTQ4_IN,
        PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN,
        PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
        PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
        PTS7_IN, PTS6_IN, PTS5_IN, PTS4_IN,
        PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
-       PTT5_IN, PTT4_IN,
+       PTT7_IN, PTT6_IN, PTT5_IN, PTT4_IN,
        PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
        PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN,
        PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
@@ -132,16 +132,43 @@ enum {
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
+       PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
+       PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
+       PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+       PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
+       PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
+       PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
+       PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
+       PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
+       PTG7_IN_PU, PTG6_IN_PU,             PTG4_IN_PU,
+       PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
+       PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
+       PTI7_IN_PU, PTI6_IN_PU,             PTI4_IN_PU,
+       PTI3_IN_PU, PTI2_IN_PU, PTI1_IN_PU, PTI0_IN_PU,
+                   PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU,
+       PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
+       PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
+       PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
+                   PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
+       PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
+       PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
+                                           PTN4_IN_PU,
+       PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
+       PTO7_IN_PU, PTO6_IN_PU, PTO5_IN_PU, PTO4_IN_PU,
+       PTO3_IN_PU, PTO2_IN_PU, PTO1_IN_PU, PTO0_IN_PU,
+       PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
+       PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
        PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
        PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
        PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
-       PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
-       PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
-       PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
+       PTV3_IN_PU, PTV2_IN_PU,
+                               PTW1_IN_PU, PTW0_IN_PU,
        PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
        PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
        PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
        PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
+       PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
+       PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_OUTPUT_BEGIN,
@@ -163,27 +190,27 @@ enum {
        PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
        PTI7_OUT, PTI6_OUT, PTI5_OUT, PTI4_OUT,
        PTI3_OUT, PTI2_OUT, PTI1_OUT, PTI0_OUT,
-       PTJ7_OUT, PTJ6_OUT, PTJ5_OUT, PTJ4_OUT,
+                 PTJ6_OUT, PTJ5_OUT, PTJ4_OUT,
        PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
        PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT,
        PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
-       PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+                 PTL6_OUT, PTL5_OUT, PTL4_OUT,
        PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
-       PTM6_OUT, PTM5_OUT, PTM4_OUT,
+       PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
        PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
-       PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+                 PTN6_OUT, PTN5_OUT, PTN4_OUT,
        PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
        PTO7_OUT, PTO6_OUT, PTO5_OUT, PTO4_OUT,
        PTO3_OUT, PTO2_OUT, PTO1_OUT, PTO0_OUT,
-       PTP6_OUT, PTP5_OUT, PTP4_OUT,
+       PTP7_OUT, PTP6_OUT, PTP5_OUT, PTP4_OUT,
        PTP3_OUT, PTP2_OUT, PTP1_OUT, PTP0_OUT,
-       PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+                 PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
        PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
        PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
        PTR3_OUT, PTR2_OUT, PTR1_OUT, PTR0_OUT,
        PTS7_OUT, PTS6_OUT, PTS5_OUT, PTS4_OUT,
        PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
-       PTT5_OUT, PTT4_OUT,
+       PTT7_OUT, PTT6_OUT, PTT5_OUT, PTT4_OUT,
        PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
        PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT,
        PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
@@ -218,27 +245,27 @@ enum {
        PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
        PTI7_FN, PTI6_FN, PTI5_FN, PTI4_FN,
        PTI3_FN, PTI2_FN, PTI1_FN, PTI0_FN,
-       PTJ7_FN, PTJ6_FN, PTJ5_FN, PTJ4_FN,
+                PTJ6_FN, PTJ5_FN, PTJ4_FN,
        PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
        PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN,
        PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
-       PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN,
+                PTL6_FN, PTL5_FN, PTL4_FN,
        PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
-       PTM6_FN, PTM5_FN, PTM4_FN,
+       PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN,
        PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
-       PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN,
+                PTN6_FN, PTN5_FN, PTN4_FN,
        PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
        PTO7_FN, PTO6_FN, PTO5_FN, PTO4_FN,
        PTO3_FN, PTO2_FN, PTO1_FN, PTO0_FN,
-       PTP6_FN, PTP5_FN, PTP4_FN,
+       PTP7_FN, PTP6_FN, PTP5_FN, PTP4_FN,
        PTP3_FN, PTP2_FN, PTP1_FN, PTP0_FN,
-       PTQ6_FN, PTQ5_FN, PTQ4_FN,
+                PTQ6_FN, PTQ5_FN, PTQ4_FN,
        PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN,
        PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
        PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
        PTS7_FN, PTS6_FN, PTS5_FN, PTS4_FN,
        PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
-       PTT5_FN, PTT4_FN,
+       PTT7_FN, PTT6_FN, PTT5_FN, PTT4_FN,
        PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
        PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN,
        PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
@@ -253,181 +280,248 @@ enum {
        PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
        PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
 
-       PS0_15_FN1, PS0_15_FN3,
-       PS0_14_FN1, PS0_14_FN3,
-       PS0_13_FN1, PS0_13_FN3,
-       PS0_12_FN1, PS0_12_FN3,
+       PS0_15_FN1, PS0_15_FN2,
+       PS0_14_FN1, PS0_14_FN2,
+       PS0_13_FN1, PS0_13_FN2,
+       PS0_12_FN1, PS0_12_FN2,
+       PS0_11_FN1, PS0_11_FN2,
+       PS0_10_FN1, PS0_10_FN2,
+       PS0_9_FN1, PS0_9_FN2,
+       PS0_8_FN1, PS0_8_FN2,
        PS0_7_FN1, PS0_7_FN2,
        PS0_6_FN1, PS0_6_FN2,
        PS0_5_FN1, PS0_5_FN2,
        PS0_4_FN1, PS0_4_FN2,
        PS0_3_FN1, PS0_3_FN2,
        PS0_2_FN1, PS0_2_FN2,
-       PS0_1_FN1, PS0_1_FN2,
 
-       PS1_7_FN1, PS1_7_FN3,
-       PS1_6_FN1, PS1_6_FN3,
+       PS1_10_FN1, PS1_10_FN2,
+       PS1_9_FN1, PS1_9_FN2,
+       PS1_8_FN1, PS1_8_FN2,
+       PS1_2_FN1, PS1_2_FN2,
+
+       PS2_13_FN1, PS2_13_FN2,
+       PS2_12_FN1, PS2_12_FN2,
+       PS2_7_FN1, PS2_7_FN2,
+       PS2_6_FN1, PS2_6_FN2,
+       PS2_5_FN1, PS2_5_FN2,
+       PS2_4_FN1, PS2_4_FN2,
+       PS2_2_FN1, PS2_2_FN2,
+
+       PS3_15_FN1, PS3_15_FN2,
+       PS3_14_FN1, PS3_14_FN2,
+       PS3_13_FN1, PS3_13_FN2,
+       PS3_12_FN1, PS3_12_FN2,
+       PS3_11_FN1, PS3_11_FN2,
+       PS3_10_FN1, PS3_10_FN2,
+       PS3_9_FN1, PS3_9_FN2,
+       PS3_8_FN1, PS3_8_FN2,
+       PS3_7_FN1, PS3_7_FN2,
+       PS3_2_FN1, PS3_2_FN2,
+       PS3_1_FN1, PS3_1_FN2,
 
-       PS2_13_FN1, PS2_13_FN3,
-       PS2_12_FN1, PS2_12_FN3,
-       PS2_1_FN1, PS2_1_FN2,
-       PS2_0_FN1, PS2_0_FN2,
-
-       PS4_15_FN1, PS4_15_FN2,
        PS4_14_FN1, PS4_14_FN2,
        PS4_13_FN1, PS4_13_FN2,
        PS4_12_FN1, PS4_12_FN2,
-       PS4_11_FN1, PS4_11_FN2,
        PS4_10_FN1, PS4_10_FN2,
        PS4_9_FN1, PS4_9_FN2,
+       PS4_8_FN1, PS4_8_FN2,
+       PS4_4_FN1, PS4_4_FN2,
        PS4_3_FN1, PS4_3_FN2,
        PS4_2_FN1, PS4_2_FN2,
        PS4_1_FN1, PS4_1_FN2,
        PS4_0_FN1, PS4_0_FN2,
 
+       PS5_11_FN1, PS5_11_FN2,
+       PS5_10_FN1, PS5_10_FN2,
        PS5_9_FN1, PS5_9_FN2,
        PS5_8_FN1, PS5_8_FN2,
        PS5_7_FN1, PS5_7_FN2,
        PS5_6_FN1, PS5_6_FN2,
        PS5_5_FN1, PS5_5_FN2,
        PS5_4_FN1, PS5_4_FN2,
-
-       /* AN15 to 8 : EVENT15 to 8 */
-       PS6_7_FN_AN, PS6_7_FN_EV,
-       PS6_6_FN_AN, PS6_6_FN_EV,
-       PS6_5_FN_AN, PS6_5_FN_EV,
-       PS6_4_FN_AN, PS6_4_FN_EV,
-       PS6_3_FN_AN, PS6_3_FN_EV,
-       PS6_2_FN_AN, PS6_2_FN_EV,
-       PS6_1_FN_AN, PS6_1_FN_EV,
-       PS6_0_FN_AN, PS6_0_FN_EV,
-
+       PS5_3_FN1, PS5_3_FN2,
+       PS5_2_FN1, PS5_2_FN2,
+
+       PS6_15_FN1, PS6_15_FN2,
+       PS6_14_FN1, PS6_14_FN2,
+       PS6_13_FN1, PS6_13_FN2,
+       PS6_12_FN1, PS6_12_FN2,
+       PS6_11_FN1, PS6_11_FN2,
+       PS6_10_FN1, PS6_10_FN2,
+       PS6_9_FN1, PS6_9_FN2,
+       PS6_8_FN1, PS6_8_FN2,
+       PS6_7_FN1, PS6_7_FN2,
+       PS6_6_FN1, PS6_6_FN2,
+       PS6_5_FN1, PS6_5_FN2,
+       PS6_4_FN1, PS6_4_FN2,
+       PS6_3_FN1, PS6_3_FN2,
+       PS6_2_FN1, PS6_2_FN2,
+       PS6_1_FN1, PS6_1_FN2,
+       PS6_0_FN1, PS6_0_FN2,
+
+       PS7_15_FN1, PS7_15_FN2,
+       PS7_14_FN1, PS7_14_FN2,
+       PS7_13_FN1, PS7_13_FN2,
+       PS7_12_FN1, PS7_12_FN2,
+       PS7_11_FN1, PS7_11_FN2,
+       PS7_10_FN1, PS7_10_FN2,
+       PS7_9_FN1, PS7_9_FN2,
+       PS7_8_FN1, PS7_8_FN2,
+       PS7_7_FN1, PS7_7_FN2,
+       PS7_6_FN1, PS7_6_FN2,
+       PS7_5_FN1, PS7_5_FN2,
+       PS7_4_FN1, PS7_4_FN2,
+
+       PS8_15_FN1, PS8_15_FN2,
+       PS8_14_FN1, PS8_14_FN2,
+       PS8_13_FN1, PS8_13_FN2,
+       PS8_12_FN1, PS8_12_FN2,
+       PS8_11_FN1, PS8_11_FN2,
+       PS8_10_FN1, PS8_10_FN2,
+       PS8_9_FN1, PS8_9_FN2,
+       PS8_8_FN1, PS8_8_FN2,
        PINMUX_FUNCTION_END,
 
        PINMUX_MARK_BEGIN,
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        BS_MARK,        RDWR_MARK,      WE1_MARK,       RDY_MARK,
-       MD10_MARK,      MD9_MARK,       MD8_MARK,
-       LGPIO7_MARK,    LGPIO6_MARK,    LGPIO5_MARK,    LGPIO4_MARK,
-       LGPIO3_MARK,    LGPIO2_MARK,    LGPIO1_MARK,    LGPIO0_MARK,
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       D15_MARK,       D14_MARK,       D13_MARK,       D12_MARK,
-       D11_MARK,       D10_MARK,       D9_MARK,        D8_MARK,
        ET0_MDC_MARK,   ET0_MDIO_MARK,  ET1_MDC_MARK,   ET1_MDIO_MARK,
-       SIM_D_MARK,     SIM_CLK_MARK,   SIM_RST_MARK,
-       WPSZ1_MARK,     WPSZ0_MARK,     FWID_MARK,      FLSHSZ_MARK,
-       LPC_SPIEN_MARK, BASEL_MARK,
 
-       /* PTC (mobule: SD) */
-       SD_WP_MARK,     SD_CD_MARK,     SD_CLK_MARK,    SD_CMD_MARK,
-       SD_D3_MARK,     SD_D2_MARK,     SD_D1_MARK,     SD_D0_MARK,
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       IRQ15_MARK,     IRQ14_MARK,     IRQ13_MARK,     IRQ12_MARK,
+       IRQ11_MARK,     IRQ10_MARK,     IRQ9_MARK,      IRQ8_MARK,
+       ON_NRE_MARK,    ON_NWE_MARK,    ON_NWP_MARK,    ON_NCE0_MARK,
+       ON_R_B0_MARK,   ON_ALE_MARK,    ON_CLE_MARK,    TCLK_MARK,
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTC (mobule: IRQ, PWMU) */
        IRQ7_MARK,      IRQ6_MARK,      IRQ5_MARK,      IRQ4_MARK,
        IRQ3_MARK,      IRQ2_MARK,      IRQ1_MARK,      IRQ0_MARK,
-       MD6_MARK,       MD5_MARK,       MD3_MARK,       MD2_MARK,
-       MD1_MARK,       MD0_MARK,       ADTRG1_MARK,    ADTRG0_MARK,
-
-       /* PTE (mobule: EtherC) */
-       ET0_CRS_DV_MARK,        ET0_TXD1_MARK,
-       ET0_TXD0_MARK,          ET0_TX_EN_MARK,
-       ET0_REF_CLK_MARK,       ET0_RXD1_MARK,
-       ET0_RXD0_MARK,          ET0_RX_ER_MARK,
-
-       /* PTF (mobule: EtherC) */
-       ET1_CRS_DV_MARK,        ET1_TXD1_MARK,
-       ET1_TXD0_MARK,          ET1_TX_EN_MARK,
-       ET1_REF_CLK_MARK,       ET1_RXD1_MARK,
-       ET1_RXD0_MARK,          ET1_RX_ER_MARK,
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       STATUS0_MARK,   STATUS1_MARK,
-       PWX0_MARK,      PWX1_MARK,      PWX2_MARK,      PWX3_MARK,
-       SERIRQ_MARK,    CLKRUN_MARK,    LPCPD_MARK,     LDRQ_MARK,
-
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       TCLK_MARK,      RXD4_MARK,      TXD4_MARK,
+       PWMU0_MARK,     PWMU1_MARK,     PWMU2_MARK,     PWMU3_MARK,
+       PWMU4_MARK,     PWMU5_MARK,
+
+       /* PTD (mobule: SPI0, DMAC) */
+       SP0_MOSI_MARK,  SP0_MISO_MARK,  SP0_SCK_MARK,   SP0_SCK_FB_MARK,
+       SP0_SS0_MARK,   SP0_SS1_MARK,   SP0_SS2_MARK,   SP0_SS3_MARK,
+       DREQ0_MARK,     DACK0_MARK,     TEND0_MARK,
+
+       /* PTE (mobule: RMII) */
+       RMII0_CRS_DV_MARK,      RMII0_TXD1_MARK,
+       RMII0_TXD0_MARK,        RMII0_TXEN_MARK,
+       RMII0_REFCLK_MARK,      RMII0_RXD1_MARK,
+       RMII0_RXD0_MARK,        RMII0_RX_ER_MARK,
+
+       /* PTF (mobule: RMII, SerMux) */
+       RMII1_CRS_DV_MARK,      RMII1_TXD1_MARK,
+       RMII1_TXD0_MARK,        RMII1_TXEN_MARK,
+       RMII1_REFCLK_MARK,      RMII1_RXD1_MARK,
+       RMII1_RXD0_MARK,        RMII1_RX_ER_MARK,
+       RAC_RI_MARK,
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       BOOTFMS_MARK,   BOOTWP_MARK,    A25_MARK,       A24_MARK,
+       SERIRQ_MARK,    WDTOVF_MARK,    LPCPD_MARK,     LDRQ_MARK,
+       MMCCLK_MARK,    MMCCMD_MARK,
+
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        SP1_MOSI_MARK,  SP1_MISO_MARK,  SP1_SCK_MARK,   SP1_SCK_FB_MARK,
-       SP1_SS0_MARK,   SP1_SS1_MARK,   SP0_SS1_MARK,
+       SP1_SS0_MARK,   SP1_SS1_MARK,   WP_MARK,        FMS0_MARK,
+       TEND1_MARK,     DREQ1_MARK,     DACK1_MARK,     ADTRG1_MARK,
+       ADTRG0_MARK,
 
-       /* PTI (mobule: INTC) */
-       IRQ15_MARK,     IRQ14_MARK,     IRQ13_MARK,     IRQ12_MARK,
-       IRQ11_MARK,     IRQ10_MARK,     IRQ9_MARK,      IRQ8_MARK,
+       /* PTI (mobule: LBSC, SDHI) */
+       D15_MARK,       D14_MARK,       D13_MARK,       D12_MARK,
+       D11_MARK,       D10_MARK,       D9_MARK,        D8_MARK,
+       SD_WP_MARK,     SD_CD_MARK,     SD_CLK_MARK,    SD_CMD_MARK,
+       SD_D3_MARK,     SD_D2_MARK,     SD_D1_MARK,     SD_D0_MARK,
 
-       /* PTJ (mobule: SCIF234, SERMUX) */
-       RXD3_MARK,      TXD3_MARK,      RXD2_MARK,      TXD2_MARK,
-       COM1_TXD_MARK,  COM1_RXD_MARK,  COM1_RTS_MARK,  COM1_CTS_MARK,
+       /* PTJ (mobule: SCIF234) */
+       RTS3_MARK,      CTS3_MARK,      TXD3_MARK,      RXD3_MARK,
+       RTS4_MARK,      RXD4_MARK,      TXD4_MARK,
 
-       /* PTK (mobule: SERMUX) */
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
        COM2_TXD_MARK,  COM2_RXD_MARK,  COM2_RTS_MARK,  COM2_CTS_MARK,
-       COM2_DTR_MARK,  COM2_DSR_MARK,  COM2_DCD_MARK,  COM2_RI_MARK,
+       COM2_DTR_MARK,  COM2_DSR_MARK,  COM2_DCD_MARK,  CLKOUT_MARK,
+       SCK2_MARK,      SCK4_MARK,      SCK3_MARK,
 
-       /* PTL (mobule: SERMUX) */
-       RAC_TXD_MARK,   RAC_RXD_MARK,   RAC_RTS_MARK,   RAC_CTS_MARK,
-       RAC_DTR_MARK,   RAC_DSR_MARK,   RAC_DCD_MARK,   RAC_RI_MARK,
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
+       RAC_RXD_MARK,   RAC_RTS_MARK,   RAC_CTS_MARK,   RAC_DTR_MARK,
+       RAC_DSR_MARK,   RAC_DCD_MARK,   RAC_TXD_MARK,   RXD2_MARK,
+       CS5_MARK,       CS6_MARK,       AUDSYNC_MARK,   AUDCK_MARK,
+       TXD2_MARK,
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTM (mobule: LBSC, IIC) */
+       CS4_MARK,       RD_MARK,        WE0_MARK,       CS0_MARK,
        SDA6_MARK,      SCL6_MARK,      SDA7_MARK,      SCL7_MARK,
-       WP_MARK,        FMS0_MARK,      FMS1_MARK,
 
-       /* PTN (mobule: SCIF234, EVC) */
-       SCK2_MARK,      RTS4_MARK,      RTS3_MARK,      RTS2_MARK,
-       CTS4_MARK,      CTS3_MARK,      CTS2_MARK,
-       EVENT7_MARK,    EVENT6_MARK,    EVENT5_MARK,    EVENT4_MARK,
-       EVENT3_MARK,    EVENT2_MARK,    EVENT1_MARK,    EVENT0_MARK,
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       VBUS_EN_MARK,   VBUS_OC_MARK,   JMCTCK_MARK,    JMCTMS_MARK,
+       JMCTDO_MARK,    JMCTDI_MARK,    JMCTRST_MARK,
+       SGPIO1_CLK_MARK,        SGPIO1_LOAD_MARK,       SGPIO1_DI_MARK,
+       SGPIO1_DO_MARK,         SUB_CLKIN_MARK,
 
-       /* PTO (mobule: SGPIO) */
-       SGPIO0_CLK_MARK,        SGPIO0_LOAD_MARK,
-       SGPIO0_DI_MARK,         SGPIO0_DO_MARK,
-       SGPIO1_CLK_MARK,        SGPIO1_LOAD_MARK,
-       SGPIO1_DI_MARK,         SGPIO1_DO_MARK,
-
-       /* PTP (mobule: JMC, SCIF234) */
-       JMCTCK_MARK,    JMCTMS_MARK,    JMCTDO_MARK,    JMCTDI_MARK,
-       JMCRST_MARK,    SCK4_MARK,      SCK3_MARK,
+       /* PTO (mobule: SGPIO, SerMux) */
+       SGPIO0_CLK_MARK,        SGPIO0_LOAD_MARK,       SGPIO0_DI_MARK,
+       SGPIO0_DO_MARK,         SGPIO2_CLK_MARK,        SGPIO2_LOAD_MARK,
+       SGPIO2_DI_MARK,         SGPIO2_DO_MARK,
+       COM1_TXD_MARK,  COM1_RXD_MARK,  COM1_RTS_MARK,  COM1_CTS_MARK,
 
        /* PTQ (mobule: LPC) */
        LAD3_MARK,      LAD2_MARK,      LAD1_MARK,      LAD0_MARK,
        LFRAME_MARK,    LRESET_MARK,    LCLK_MARK,
 
        /* PTR (mobule: GRA, IIC) */
-       DDC3_MARK,      DDC2_MARK,
-       SDA8_MARK,      SCL8_MARK,      SDA2_MARK,      SCL2_MARK,
+       DDC3_MARK,      DDC2_MARK,      SDA2_MARK,      SCL2_MARK,
        SDA1_MARK,      SCL1_MARK,      SDA0_MARK,      SCL0_MARK,
+       SDA8_MARK,      SCL8_MARK,
 
        /* PTS (mobule: GRA, IIC) */
-       DDC1_MARK,      DDC0_MARK,
-       SDA9_MARK,      SCL9_MARK,      SDA5_MARK,      SCL5_MARK,
+       DDC1_MARK,      DDC0_MARK,      SDA5_MARK,      SCL5_MARK,
        SDA4_MARK,      SCL4_MARK,      SDA3_MARK,      SCL3_MARK,
+       SDA9_MARK,      SCL9_MARK,
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       AUDSYNC_MARK,           AUDCK_MARK,
-       AUDATA3_MARK,           AUDATA2_MARK,
-       AUDATA1_MARK,           AUDATA0_MARK,
-       PWX7_MARK,      PWX6_MARK,      PWX5_MARK,      PWX4_MARK,
+       /* PTT (mobule: PWMX, AUD) */
+       PWMX7_MARK,     PWMX6_MARK,     PWMX5_MARK,     PWMX4_MARK,
+       PWMX3_MARK,     PWMX2_MARK,     PWMX1_MARK,     PWMX0_MARK,
+       AUDATA3_MARK,   AUDATA2_MARK,   AUDATA1_MARK,   AUDATA0_MARK,
+       STATUS1_MARK,   STATUS0_MARK,
 
-       /* PTU (mobule: LBSC, DMAC) */
-       CS6_MARK,       CS5_MARK,       CS4_MARK,       CS0_MARK,
-       RD_MARK,        WE0_MARK,       A25_MARK,       A24_MARK,
-       DREQ0_MARK,     DACK0_MARK,
+       /* PTU (mobule: LPC, APM) */
+       LGPIO7_MARK,    LGPIO6_MARK,    LGPIO5_MARK,    LGPIO4_MARK,
+       LGPIO3_MARK,    LGPIO2_MARK,    LGPIO1_MARK,    LGPIO0_MARK,
+       APMONCTL_O_MARK,        APMPWBTOUT_O_MARK,      APMSCI_O_MARK,
+       APMVDDON_MARK,  APMSLPBTN_MARK, APMPWRBTN_MARK, APMS5N_MARK,
+       APMS3N_MARK,
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        A23_MARK,       A22_MARK,       A21_MARK,       A20_MARK,
        A19_MARK,       A18_MARK,       A17_MARK,       A16_MARK,
-       TEND0_MARK,     DREQ1_MARK,     DACK1_MARK,     TEND1_MARK,
+       COM2_RI_MARK,           R_SPI_MOSI_MARK,        R_SPI_MISO_MARK,
+       R_SPI_RSPCK_MARK,       R_SPI_SSL0_MARK,        R_SPI_SSL1_MARK,
+       EVENT7_MARK,    EVENT6_MARK,    VBIOS_DI_MARK,  VBIOS_DO_MARK,
+       VBIOS_CLK_MARK, VBIOS_CS_MARK,
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        A15_MARK,       A14_MARK,       A13_MARK,       A12_MARK,
        A11_MARK,       A10_MARK,       A9_MARK,        A8_MARK,
+       EVENT5_MARK,    EVENT4_MARK,    EVENT3_MARK,    EVENT2_MARK,
+       EVENT1_MARK,    EVENT0_MARK,    CTS4_MARK,      CTS2_MARK,
 
-       /* PTX (mobule: LBSC) */
+       /* PTX (mobule: LBSC, SCIF, SIM) */
        A7_MARK,        A6_MARK,        A5_MARK,        A4_MARK,
        A3_MARK,        A2_MARK,        A1_MARK,        A0_MARK,
+       RTS2_MARK,      SIM_D_MARK,     SIM_CLK_MARK,   SIM_RST_MARK,
 
        /* PTY (mobule: LBSC) */
        D7_MARK,        D6_MARK,        D5_MARK,        D4_MARK,
        D3_MARK,        D2_MARK,        D1_MARK,        D0_MARK,
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       MMCDAT7_MARK,   MMCDAT6_MARK,   MMCDAT5_MARK,   MMCDAT4_MARK,
+       MMCDAT3_MARK,   MMCDAT2_MARK,   MMCDAT1_MARK,   MMCDAT0_MARK,
+       ON_DQ7_MARK,    ON_DQ6_MARK,    ON_DQ5_MARK,    ON_DQ4_MARK,
+       ON_DQ3_MARK,    ON_DQ2_MARK,    ON_DQ1_MARK,    ON_DQ0_MARK,
+
        PINMUX_MARK_END,
 };
 
@@ -473,6 +567,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
 
        /* PTE GPIO */
+       PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT),
+       PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT),
        PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT),
        PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
        PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
@@ -521,7 +617,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTI0_DATA, PTI0_IN, PTI0_OUT),
 
        /* PTJ GPIO */
-       PINMUX_DATA(PTJ7_DATA, PTJ7_IN, PTJ7_OUT),
        PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT),
        PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT),
        PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT),
@@ -541,7 +636,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT),
 
        /* PTL GPIO */
-       PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT),
        PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT),
        PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT),
        PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT),
@@ -560,7 +654,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT),
 
        /* PTN GPIO */
-       PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT),
        PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT),
        PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT),
        PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT),
@@ -609,6 +702,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
 
        /* PTT GPIO */
+       PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT),
+       PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT),
        PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT),
        PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
        PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
@@ -677,186 +772,204 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT),
 
        /* PTA FN */
-       PINMUX_DATA(BS_MARK, PS0_15_FN1, PTA7_FN),
-       PINMUX_DATA(LGPIO7_MARK, PS0_15_FN3, PTA7_FN),
-       PINMUX_DATA(RDWR_MARK, PS0_14_FN1, PTA6_FN),
-       PINMUX_DATA(LGPIO6_MARK, PS0_14_FN3, PTA6_FN),
-       PINMUX_DATA(WE1_MARK, PS0_13_FN1, PTA5_FN),
-       PINMUX_DATA(LGPIO5_MARK, PS0_13_FN3, PTA5_FN),
-       PINMUX_DATA(RDY_MARK, PS0_12_FN1, PTA4_FN),
-       PINMUX_DATA(LGPIO4_MARK, PS0_12_FN3, PTA4_FN),
-       PINMUX_DATA(LGPIO3_MARK, PTA3_FN),
-       PINMUX_DATA(LGPIO2_MARK, PTA2_FN),
-       PINMUX_DATA(LGPIO1_MARK, PTA1_FN),
-       PINMUX_DATA(LGPIO0_MARK, PTA0_FN),
+       PINMUX_DATA(BS_MARK, PTA7_FN),
+       PINMUX_DATA(RDWR_MARK, PTA6_FN),
+       PINMUX_DATA(WE1_MARK, PTA5_FN),
+       PINMUX_DATA(RDY_MARK, PTA4_FN),
+       PINMUX_DATA(ET0_MDC_MARK, PTA3_FN),
+       PINMUX_DATA(ET0_MDIO_MARK, PTA2_FN),
+       PINMUX_DATA(ET1_MDC_MARK, PTA1_FN),
+       PINMUX_DATA(ET1_MDIO_MARK, PTA0_FN),
 
        /* PTB FN */
-       PINMUX_DATA(D15_MARK, PS0_7_FN1, PTB7_FN),
-       PINMUX_DATA(ET0_MDC_MARK, PS0_7_FN2, PTB7_FN),
-       PINMUX_DATA(D14_MARK, PS0_6_FN1, PTB6_FN),
-       PINMUX_DATA(ET0_MDIO_MARK, PS0_6_FN2, PTB6_FN),
-       PINMUX_DATA(D13_MARK, PS0_5_FN1, PTB5_FN),
-       PINMUX_DATA(ET1_MDC_MARK, PS0_5_FN2, PTB5_FN),
-       PINMUX_DATA(D12_MARK, PS0_4_FN1, PTB4_FN),
-       PINMUX_DATA(ET1_MDIO_MARK, PS0_4_FN2, PTB4_FN),
-       PINMUX_DATA(D11_MARK, PS0_3_FN1, PTB3_FN),
-       PINMUX_DATA(SIM_D_MARK, PS0_3_FN2, PTB3_FN),
-       PINMUX_DATA(D10_MARK, PS0_2_FN1, PTB2_FN),
-       PINMUX_DATA(SIM_CLK_MARK, PS0_2_FN2, PTB2_FN),
-       PINMUX_DATA(D9_MARK, PS0_1_FN1, PTB1_FN),
-       PINMUX_DATA(SIM_RST_MARK, PS0_1_FN2, PTB1_FN),
-       PINMUX_DATA(D8_MARK, PTB0_FN),
+       PINMUX_DATA(IRQ15_MARK, PS0_15_FN1, PTB7_FN),
+       PINMUX_DATA(ON_NRE_MARK, PS0_15_FN2, PTB7_FN),
+       PINMUX_DATA(IRQ14_MARK, PS0_14_FN1, PTB6_FN),
+       PINMUX_DATA(ON_NWE_MARK, PS0_14_FN2, PTB6_FN),
+       PINMUX_DATA(IRQ13_MARK, PS0_13_FN1, PTB5_FN),
+       PINMUX_DATA(ON_NWP_MARK, PS0_13_FN2, PTB5_FN),
+       PINMUX_DATA(IRQ12_MARK, PS0_12_FN1, PTB4_FN),
+       PINMUX_DATA(ON_NCE0_MARK, PS0_12_FN2, PTB4_FN),
+       PINMUX_DATA(IRQ11_MARK, PS0_11_FN1, PTB3_FN),
+       PINMUX_DATA(ON_R_B0_MARK, PS0_11_FN2, PTB3_FN),
+       PINMUX_DATA(IRQ10_MARK, PS0_10_FN1, PTB2_FN),
+       PINMUX_DATA(ON_ALE_MARK, PS0_10_FN2, PTB2_FN),
+       PINMUX_DATA(IRQ9_MARK, PS0_9_FN1, PTB1_FN),
+       PINMUX_DATA(ON_CLE_MARK, PS0_9_FN2, PTB1_FN),
+       PINMUX_DATA(IRQ8_MARK, PS0_8_FN1, PTB0_FN),
+       PINMUX_DATA(TCLK_MARK, PS0_8_FN2, PTB0_FN),
 
        /* PTC FN */
-       PINMUX_DATA(SD_WP_MARK, PTC7_FN),
-       PINMUX_DATA(SD_CD_MARK, PTC6_FN),
-       PINMUX_DATA(SD_CLK_MARK, PTC5_FN),
-       PINMUX_DATA(SD_CMD_MARK, PTC4_FN),
-       PINMUX_DATA(SD_D3_MARK, PTC3_FN),
-       PINMUX_DATA(SD_D2_MARK, PTC2_FN),
-       PINMUX_DATA(SD_D1_MARK, PTC1_FN),
-       PINMUX_DATA(SD_D0_MARK, PTC0_FN),
+       PINMUX_DATA(IRQ7_MARK, PS0_7_FN1, PTC7_FN),
+       PINMUX_DATA(PWMU0_MARK, PS0_7_FN2, PTC7_FN),
+       PINMUX_DATA(IRQ6_MARK, PS0_6_FN1, PTC6_FN),
+       PINMUX_DATA(PWMU1_MARK, PS0_6_FN2, PTC6_FN),
+       PINMUX_DATA(IRQ5_MARK, PS0_5_FN1, PTC5_FN),
+       PINMUX_DATA(PWMU2_MARK, PS0_5_FN2, PTC5_FN),
+       PINMUX_DATA(IRQ4_MARK, PS0_4_FN1, PTC5_FN),
+       PINMUX_DATA(PWMU3_MARK, PS0_4_FN2, PTC4_FN),
+       PINMUX_DATA(IRQ3_MARK, PS0_3_FN1, PTC3_FN),
+       PINMUX_DATA(PWMU4_MARK, PS0_3_FN2, PTC3_FN),
+       PINMUX_DATA(IRQ2_MARK, PS0_2_FN1, PTC2_FN),
+       PINMUX_DATA(PWMU5_MARK, PS0_2_FN2, PTC2_FN),
+       PINMUX_DATA(IRQ1_MARK, PTC1_FN),
+       PINMUX_DATA(IRQ0_MARK, PTC0_FN),
 
        /* PTD FN */
-       PINMUX_DATA(IRQ7_MARK, PS1_7_FN1, PTD7_FN),
-       PINMUX_DATA(ADTRG1_MARK, PS1_7_FN3, PTD7_FN),
-       PINMUX_DATA(IRQ6_MARK, PS1_6_FN1, PTD6_FN),
-       PINMUX_DATA(ADTRG0_MARK, PS1_6_FN3, PTD6_FN),
-       PINMUX_DATA(IRQ5_MARK, PTD5_FN),
-       PINMUX_DATA(IRQ4_MARK, PTD4_FN),
-       PINMUX_DATA(IRQ3_MARK, PTD3_FN),
-       PINMUX_DATA(IRQ2_MARK, PTD2_FN),
-       PINMUX_DATA(IRQ1_MARK, PTD1_FN),
-       PINMUX_DATA(IRQ0_MARK, PTD0_FN),
+       PINMUX_DATA(SP0_MOSI_MARK, PTD7_FN),
+       PINMUX_DATA(SP0_MISO_MARK, PTD6_FN),
+       PINMUX_DATA(SP0_SCK_MARK, PTD5_FN),
+       PINMUX_DATA(SP0_SCK_FB_MARK, PTD4_FN),
+       PINMUX_DATA(SP0_SS0_MARK, PTD3_FN),
+       PINMUX_DATA(SP0_SS1_MARK, PS1_10_FN1, PTD2_FN),
+       PINMUX_DATA(DREQ0_MARK, PS1_10_FN2, PTD2_FN),
+       PINMUX_DATA(SP0_SS2_MARK, PS1_9_FN1, PTD1_FN),
+       PINMUX_DATA(DACK0_MARK, PS1_9_FN2, PTD1_FN),
+       PINMUX_DATA(SP0_SS3_MARK, PS1_8_FN1, PTD0_FN),
+       PINMUX_DATA(TEND0_MARK, PS1_8_FN2, PTD0_FN),
 
        /* PTE FN */
-       PINMUX_DATA(ET0_CRS_DV_MARK, PTE7_FN),
-       PINMUX_DATA(ET0_TXD1_MARK, PTE6_FN),
-       PINMUX_DATA(ET0_TXD0_MARK, PTE5_FN),
-       PINMUX_DATA(ET0_TX_EN_MARK, PTE4_FN),
-       PINMUX_DATA(ET0_REF_CLK_MARK, PTE3_FN),
-       PINMUX_DATA(ET0_RXD1_MARK, PTE2_FN),
-       PINMUX_DATA(ET0_RXD0_MARK, PTE1_FN),
-       PINMUX_DATA(ET0_RX_ER_MARK, PTE0_FN),
+       PINMUX_DATA(RMII0_CRS_DV_MARK, PTE7_FN),
+       PINMUX_DATA(RMII0_TXD1_MARK, PTE6_FN),
+       PINMUX_DATA(RMII0_TXD0_MARK, PTE5_FN),
+       PINMUX_DATA(RMII0_TXEN_MARK, PTE4_FN),
+       PINMUX_DATA(RMII0_REFCLK_MARK, PTE3_FN),
+       PINMUX_DATA(RMII0_RXD1_MARK, PTE2_FN),
+       PINMUX_DATA(RMII0_RXD0_MARK, PTE1_FN),
+       PINMUX_DATA(RMII0_RX_ER_MARK, PTE0_FN),
 
        /* PTF FN */
-       PINMUX_DATA(ET1_CRS_DV_MARK, PTF7_FN),
-       PINMUX_DATA(ET1_TXD1_MARK, PTF6_FN),
-       PINMUX_DATA(ET1_TXD0_MARK, PTF5_FN),
-       PINMUX_DATA(ET1_TX_EN_MARK, PTF4_FN),
-       PINMUX_DATA(ET1_REF_CLK_MARK, PTF3_FN),
-       PINMUX_DATA(ET1_RXD1_MARK, PTF2_FN),
-       PINMUX_DATA(ET1_RXD0_MARK, PTF1_FN),
-       PINMUX_DATA(ET1_RX_ER_MARK, PTF0_FN),
+       PINMUX_DATA(RMII1_CRS_DV_MARK, PTF7_FN),
+       PINMUX_DATA(RMII1_TXD1_MARK, PTF6_FN),
+       PINMUX_DATA(RMII1_TXD0_MARK, PTF5_FN),
+       PINMUX_DATA(RMII1_TXEN_MARK, PTF4_FN),
+       PINMUX_DATA(RMII1_REFCLK_MARK, PTF3_FN),
+       PINMUX_DATA(RMII1_RXD1_MARK, PS1_2_FN1, PTF2_FN),
+       PINMUX_DATA(RAC_RI_MARK, PS1_2_FN2, PTF2_FN),
+       PINMUX_DATA(RMII1_RXD0_MARK, PTF1_FN),
+       PINMUX_DATA(RMII1_RX_ER_MARK, PTF0_FN),
 
        /* PTG FN */
-       PINMUX_DATA(PWX0_MARK, PTG7_FN),
-       PINMUX_DATA(PWX1_MARK, PTG6_FN),
-       PINMUX_DATA(STATUS0_MARK, PS2_13_FN1, PTG5_FN),
-       PINMUX_DATA(PWX2_MARK, PS2_13_FN3, PTG5_FN),
-       PINMUX_DATA(STATUS1_MARK, PS2_12_FN1, PTG4_FN),
-       PINMUX_DATA(PWX3_MARK, PS2_12_FN3, PTG4_FN),
+       PINMUX_DATA(BOOTFMS_MARK, PTG7_FN),
+       PINMUX_DATA(BOOTWP_MARK, PTG6_FN),
+       PINMUX_DATA(A25_MARK, PS2_13_FN1, PTG5_FN),
+       PINMUX_DATA(MMCCLK_MARK, PS2_13_FN2, PTG5_FN),
+       PINMUX_DATA(A24_MARK, PS2_12_FN1, PTG4_FN),
+       PINMUX_DATA(MMCCMD_MARK, PS2_12_FN2, PTG4_FN),
        PINMUX_DATA(SERIRQ_MARK, PTG3_FN),
-       PINMUX_DATA(CLKRUN_MARK, PTG2_FN),
+       PINMUX_DATA(WDTOVF_MARK, PTG2_FN),
        PINMUX_DATA(LPCPD_MARK, PTG1_FN),
        PINMUX_DATA(LDRQ_MARK, PTG0_FN),
 
        /* PTH FN */
-       PINMUX_DATA(SP1_MOSI_MARK, PTH7_FN),
-       PINMUX_DATA(SP1_MISO_MARK, PTH6_FN),
-       PINMUX_DATA(SP1_SCK_MARK, PTH5_FN),
-       PINMUX_DATA(SP1_SCK_FB_MARK, PTH4_FN),
+       PINMUX_DATA(SP1_MOSI_MARK, PS2_7_FN1, PTH7_FN),
+       PINMUX_DATA(TEND1_MARK, PS2_7_FN2, PTH7_FN),
+       PINMUX_DATA(SP1_MISO_MARK, PS2_6_FN1, PTH6_FN),
+       PINMUX_DATA(DREQ1_MARK, PS2_6_FN2, PTH6_FN),
+       PINMUX_DATA(SP1_SCK_MARK, PS2_5_FN1, PTH5_FN),
+       PINMUX_DATA(DACK1_MARK, PS2_5_FN2, PTH5_FN),
+       PINMUX_DATA(SP1_SCK_FB_MARK, PS2_4_FN1, PTH4_FN),
+       PINMUX_DATA(ADTRG1_MARK, PS2_4_FN2, PTH4_FN),
        PINMUX_DATA(SP1_SS0_MARK, PTH3_FN),
-       PINMUX_DATA(TCLK_MARK, PTH2_FN),
-       PINMUX_DATA(RXD4_MARK, PS2_1_FN1, PTH1_FN),
-       PINMUX_DATA(SP1_SS1_MARK, PS2_1_FN2, PTH1_FN),
-       PINMUX_DATA(TXD4_MARK, PS2_0_FN1, PTH0_FN),
-       PINMUX_DATA(SP0_SS1_MARK, PS2_0_FN2, PTH0_FN),
+       PINMUX_DATA(SP1_SS1_MARK, PS2_2_FN1, PTH2_FN),
+       PINMUX_DATA(ADTRG0_MARK, PS2_2_FN2, PTH2_FN),
+       PINMUX_DATA(WP_MARK, PTH1_FN),
+       PINMUX_DATA(FMS0_MARK, PTH0_FN),
 
        /* PTI FN */
-       PINMUX_DATA(IRQ15_MARK, PTI7_FN),
-       PINMUX_DATA(IRQ14_MARK, PTI6_FN),
-       PINMUX_DATA(IRQ13_MARK, PTI5_FN),
-       PINMUX_DATA(IRQ12_MARK, PTI4_FN),
-       PINMUX_DATA(IRQ11_MARK, PTI3_FN),
-       PINMUX_DATA(IRQ10_MARK, PTI2_FN),
-       PINMUX_DATA(IRQ9_MARK, PTI1_FN),
-       PINMUX_DATA(IRQ8_MARK, PTI0_FN),
+       PINMUX_DATA(D15_MARK, PS3_15_FN1, PTI7_FN),
+       PINMUX_DATA(SD_WP_MARK, PS3_15_FN2, PTI7_FN),
+       PINMUX_DATA(D14_MARK, PS3_14_FN1, PTI6_FN),
+       PINMUX_DATA(SD_CD_MARK, PS3_14_FN2, PTI6_FN),
+       PINMUX_DATA(D13_MARK, PS3_13_FN1, PTI5_FN),
+       PINMUX_DATA(SD_CLK_MARK, PS3_13_FN2, PTI5_FN),
+       PINMUX_DATA(D12_MARK, PS3_12_FN1, PTI4_FN),
+       PINMUX_DATA(SD_CMD_MARK, PS3_12_FN2, PTI4_FN),
+       PINMUX_DATA(D11_MARK, PS3_11_FN1, PTI3_FN),
+       PINMUX_DATA(SD_D3_MARK, PS3_11_FN2, PTI3_FN),
+       PINMUX_DATA(D10_MARK, PS3_10_FN1, PTI2_FN),
+       PINMUX_DATA(SD_D2_MARK, PS3_10_FN2, PTI2_FN),
+       PINMUX_DATA(D9_MARK, PS3_9_FN1, PTI1_FN),
+       PINMUX_DATA(SD_D1_MARK, PS3_9_FN2, PTI1_FN),
+       PINMUX_DATA(D8_MARK, PS3_8_FN1, PTI0_FN),
+       PINMUX_DATA(SD_D0_MARK, PS3_8_FN2, PTI0_FN),
 
        /* PTJ FN */
-       PINMUX_DATA(RXD3_MARK, PTJ7_FN),
-       PINMUX_DATA(TXD3_MARK, PTJ6_FN),
-       PINMUX_DATA(RXD2_MARK, PTJ5_FN),
-       PINMUX_DATA(TXD2_MARK, PTJ4_FN),
-       PINMUX_DATA(COM1_TXD_MARK, PTJ3_FN),
-       PINMUX_DATA(COM1_RXD_MARK, PTJ2_FN),
-       PINMUX_DATA(COM1_RTS_MARK, PTJ1_FN),
-       PINMUX_DATA(COM1_CTS_MARK, PTJ0_FN),
+       PINMUX_DATA(RTS3_MARK, PTJ6_FN),
+       PINMUX_DATA(CTS3_MARK, PTJ5_FN),
+       PINMUX_DATA(TXD3_MARK, PTJ4_FN),
+       PINMUX_DATA(RXD3_MARK, PTJ3_FN),
+       PINMUX_DATA(RTS4_MARK, PTJ2_FN),
+       PINMUX_DATA(RXD4_MARK, PTJ1_FN),
+       PINMUX_DATA(TXD4_MARK, PTJ0_FN),
 
        /* PTK FN */
-       PINMUX_DATA(COM2_TXD_MARK, PTK7_FN),
+       PINMUX_DATA(COM2_TXD_MARK, PS3_7_FN1, PTK7_FN),
+       PINMUX_DATA(SCK2_MARK, PS3_7_FN2, PTK7_FN),
        PINMUX_DATA(COM2_RXD_MARK, PTK6_FN),
        PINMUX_DATA(COM2_RTS_MARK, PTK5_FN),
        PINMUX_DATA(COM2_CTS_MARK, PTK4_FN),
        PINMUX_DATA(COM2_DTR_MARK, PTK3_FN),
-       PINMUX_DATA(COM2_DSR_MARK, PTK2_FN),
-       PINMUX_DATA(COM2_DCD_MARK, PTK1_FN),
-       PINMUX_DATA(COM2_RI_MARK, PTK0_FN),
+       PINMUX_DATA(COM2_DSR_MARK, PS3_2_FN1, PTK2_FN),
+       PINMUX_DATA(SCK4_MARK, PS3_2_FN2, PTK2_FN),
+       PINMUX_DATA(COM2_DCD_MARK, PS3_1_FN1, PTK1_FN),
+       PINMUX_DATA(SCK3_MARK, PS3_1_FN2, PTK1_FN),
+       PINMUX_DATA(CLKOUT_MARK, PTK0_FN),
 
        /* PTL FN */
-       PINMUX_DATA(RAC_TXD_MARK, PTL7_FN),
-       PINMUX_DATA(RAC_RXD_MARK, PTL6_FN),
-       PINMUX_DATA(RAC_RTS_MARK, PTL5_FN),
-       PINMUX_DATA(RAC_CTS_MARK, PTL4_FN),
+       PINMUX_DATA(RAC_RXD_MARK, PS4_14_FN1, PTL6_FN),
+       PINMUX_DATA(RXD2_MARK, PS4_14_FN2, PTL6_FN),
+       PINMUX_DATA(RAC_RTS_MARK, PS4_13_FN1, PTL5_FN),
+       PINMUX_DATA(CS5_MARK, PS4_13_FN2, PTL5_FN),
+       PINMUX_DATA(RAC_CTS_MARK, PS4_12_FN1, PTL4_FN),
+       PINMUX_DATA(CS6_MARK, PS4_12_FN2, PTL4_FN),
        PINMUX_DATA(RAC_DTR_MARK, PTL3_FN),
-       PINMUX_DATA(RAC_DSR_MARK, PTL2_FN),
-       PINMUX_DATA(RAC_DCD_MARK, PTL1_FN),
-       PINMUX_DATA(RAC_RI_MARK, PTL0_FN),
+       PINMUX_DATA(RAC_DSR_MARK, PS4_10_FN1, PTL2_FN),
+       PINMUX_DATA(AUDSYNC_MARK, PS4_10_FN2, PTL2_FN),
+       PINMUX_DATA(RAC_DCD_MARK, PS4_9_FN1, PTL1_FN),
+       PINMUX_DATA(AUDCK_MARK, PS4_9_FN2, PTL1_FN),
+       PINMUX_DATA(RAC_TXD_MARK, PS4_8_FN1, PTL0_FN),
+       PINMUX_DATA(TXD2_MARK, PS4_8_FN1, PTL0_FN),
 
        /* PTM FN */
-       PINMUX_DATA(WP_MARK, PTM6_FN),
-       PINMUX_DATA(FMS0_MARK, PTM5_FN),
-       PINMUX_DATA(FMS1_MARK, PTM4_FN),
+       PINMUX_DATA(CS4_MARK, PTM7_FN),
+       PINMUX_DATA(RD_MARK, PTM6_FN),
+       PINMUX_DATA(WE0_MARK, PTM7_FN),
+       PINMUX_DATA(CS0_MARK, PTM4_FN),
        PINMUX_DATA(SDA6_MARK, PTM3_FN),
        PINMUX_DATA(SCL6_MARK, PTM2_FN),
        PINMUX_DATA(SDA7_MARK, PTM1_FN),
        PINMUX_DATA(SCL7_MARK, PTM0_FN),
 
        /* PTN FN */
-       PINMUX_DATA(SCK2_MARK, PS4_15_FN1, PTN7_FN),
-       PINMUX_DATA(EVENT7_MARK, PS4_15_FN2, PTN7_FN),
-       PINMUX_DATA(RTS4_MARK, PS4_14_FN1, PTN6_FN),
-       PINMUX_DATA(EVENT6_MARK, PS4_14_FN2, PTN6_FN),
-       PINMUX_DATA(RTS3_MARK, PS4_13_FN1, PTN5_FN),
-       PINMUX_DATA(EVENT5_MARK, PS4_13_FN2, PTN5_FN),
-       PINMUX_DATA(RTS2_MARK, PS4_12_FN1, PTN4_FN),
-       PINMUX_DATA(EVENT4_MARK, PS4_12_FN2, PTN4_FN),
-       PINMUX_DATA(CTS4_MARK, PS4_11_FN1, PTN3_FN),
-       PINMUX_DATA(EVENT3_MARK, PS4_11_FN2, PTN3_FN),
-       PINMUX_DATA(CTS3_MARK, PS4_10_FN1, PTN2_FN),
-       PINMUX_DATA(EVENT2_MARK, PS4_10_FN2, PTN2_FN),
-       PINMUX_DATA(CTS2_MARK, PS4_9_FN1, PTN1_FN),
-       PINMUX_DATA(EVENT1_MARK, PS4_9_FN2, PTN1_FN),
-       PINMUX_DATA(EVENT0_MARK, PTN0_FN),
+       PINMUX_DATA(VBUS_EN_MARK, PTN6_FN),
+       PINMUX_DATA(VBUS_OC_MARK, PTN5_FN),
+       PINMUX_DATA(JMCTCK_MARK, PS4_4_FN1, PTN4_FN),
+       PINMUX_DATA(SGPIO1_CLK_MARK, PS4_4_FN2, PTN4_FN),
+       PINMUX_DATA(JMCTMS_MARK, PS4_3_FN1, PTN5_FN),
+       PINMUX_DATA(SGPIO1_LOAD_MARK, PS4_3_FN2, PTN5_FN),
+       PINMUX_DATA(JMCTDO_MARK, PS4_2_FN1, PTN2_FN),
+       PINMUX_DATA(SGPIO1_DO_MARK, PS4_2_FN2, PTN2_FN),
+       PINMUX_DATA(JMCTDI_MARK, PS4_1_FN1, PTN1_FN),
+       PINMUX_DATA(SGPIO1_DI_MARK, PS4_1_FN2, PTN1_FN),
+       PINMUX_DATA(JMCTRST_MARK, PS4_0_FN1, PTN0_FN),
+       PINMUX_DATA(SUB_CLKIN_MARK, PS4_0_FN2, PTN0_FN),
 
        /* PTO FN */
        PINMUX_DATA(SGPIO0_CLK_MARK, PTO7_FN),
        PINMUX_DATA(SGPIO0_LOAD_MARK, PTO6_FN),
        PINMUX_DATA(SGPIO0_DI_MARK, PTO5_FN),
        PINMUX_DATA(SGPIO0_DO_MARK, PTO4_FN),
-       PINMUX_DATA(SGPIO1_CLK_MARK, PTO3_FN),
-       PINMUX_DATA(SGPIO1_LOAD_MARK, PTO2_FN),
-       PINMUX_DATA(SGPIO1_DI_MARK, PTO1_FN),
-       PINMUX_DATA(SGPIO1_DO_MARK, PTO0_FN),
+       PINMUX_DATA(SGPIO2_CLK_MARK, PS5_11_FN1, PTO3_FN),
+       PINMUX_DATA(COM1_TXD_MARK, PS5_11_FN2, PTO3_FN),
+       PINMUX_DATA(SGPIO2_LOAD_MARK, PS5_10_FN1, PTO2_FN),
+       PINMUX_DATA(COM1_RXD_MARK, PS5_10_FN2, PTO2_FN),
+       PINMUX_DATA(SGPIO2_DI_MARK, PS5_9_FN1, PTO1_FN),
+       PINMUX_DATA(COM1_RTS_MARK, PS5_9_FN2, PTO1_FN),
+       PINMUX_DATA(SGPIO2_DO_MARK, PS5_8_FN1, PTO0_FN),
+       PINMUX_DATA(COM1_CTS_MARK, PS5_8_FN2, PTO0_FN),
 
        /* PTP FN */
-       PINMUX_DATA(JMCTCK_MARK, PTP6_FN),
-       PINMUX_DATA(JMCTMS_MARK, PTP5_FN),
-       PINMUX_DATA(JMCTDO_MARK, PTP4_FN),
-       PINMUX_DATA(JMCTDI_MARK, PTP3_FN),
-       PINMUX_DATA(JMCRST_MARK, PTP2_FN),
-       PINMUX_DATA(SCK4_MARK, PTP1_FN),
-       PINMUX_DATA(SCK3_MARK, PTP0_FN),
 
        /* PTQ FN */
        PINMUX_DATA(LAD3_MARK, PTQ6_FN),
@@ -864,8 +977,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(LAD1_MARK, PTQ4_FN),
        PINMUX_DATA(LAD0_MARK, PTQ3_FN),
        PINMUX_DATA(LFRAME_MARK, PTQ2_FN),
-       PINMUX_DATA(SCK4_MARK, PTQ1_FN),
-       PINMUX_DATA(SCK3_MARK, PTQ0_FN),
+       PINMUX_DATA(LRESET_MARK, PTQ1_FN),
+       PINMUX_DATA(LCLK_MARK, PTQ0_FN),
 
        /* PTR FN */
        PINMUX_DATA(SDA8_MARK, PTR7_FN),        /* DDC3? */
@@ -888,58 +1001,84 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(SCL3_MARK, PTS0_FN),
 
        /* PTT FN */
-       PINMUX_DATA(AUDSYNC_MARK, PTS5_FN),
-       PINMUX_DATA(AUDCK_MARK, PTS4_FN),
-       PINMUX_DATA(AUDATA3_MARK, PS4_3_FN1, PTS3_FN),
-       PINMUX_DATA(PWX7_MARK, PS4_3_FN2, PTS3_FN),
-       PINMUX_DATA(AUDATA2_MARK, PS4_2_FN1, PTS2_FN),
-       PINMUX_DATA(PWX6_MARK, PS4_2_FN2, PTS2_FN),
-       PINMUX_DATA(AUDATA1_MARK, PS4_1_FN1, PTS1_FN),
-       PINMUX_DATA(PWX5_MARK, PS4_1_FN2, PTS1_FN),
-       PINMUX_DATA(AUDATA0_MARK, PS4_0_FN1, PTS0_FN),
-       PINMUX_DATA(PWX4_MARK, PS4_0_FN2, PTS0_FN),
+       PINMUX_DATA(PWMX7_MARK, PS5_7_FN1, PTT7_FN),
+       PINMUX_DATA(AUDATA3_MARK, PS5_7_FN2, PTT7_FN),
+       PINMUX_DATA(PWMX6_MARK, PS5_6_FN1, PTT6_FN),
+       PINMUX_DATA(AUDATA2_MARK, PS5_6_FN2, PTT6_FN),
+       PINMUX_DATA(PWMX5_MARK, PS5_5_FN1, PTT5_FN),
+       PINMUX_DATA(AUDATA1_MARK, PS5_5_FN2, PTT5_FN),
+       PINMUX_DATA(PWMX4_MARK, PS5_4_FN1, PTT4_FN),
+       PINMUX_DATA(AUDATA0_MARK, PS5_4_FN2, PTT4_FN),
+       PINMUX_DATA(PWMX3_MARK, PS5_3_FN1, PTT3_FN),
+       PINMUX_DATA(STATUS1_MARK, PS5_3_FN2, PTT3_FN),
+       PINMUX_DATA(PWMX2_MARK, PS5_2_FN1, PTT2_FN),
+       PINMUX_DATA(STATUS0_MARK, PS5_2_FN2, PTT2_FN),
+       PINMUX_DATA(PWMX1_MARK, PTT1_FN),
+       PINMUX_DATA(PWMX0_MARK, PTT0_FN),
 
        /* PTU FN */
-       PINMUX_DATA(CS6_MARK, PTU7_FN),
-       PINMUX_DATA(CS5_MARK, PTU6_FN),
-       PINMUX_DATA(CS4_MARK, PTU5_FN),
-       PINMUX_DATA(CS0_MARK, PTU4_FN),
-       PINMUX_DATA(RD_MARK, PTU3_FN),
-       PINMUX_DATA(WE0_MARK, PTU2_FN),
-       PINMUX_DATA(A25_MARK, PS5_9_FN1, PTU1_FN),
-       PINMUX_DATA(DREQ0_MARK, PS5_9_FN2, PTU1_FN),
-       PINMUX_DATA(A24_MARK, PS5_8_FN1, PTU0_FN),
-       PINMUX_DATA(DACK0_MARK, PS5_8_FN2, PTU0_FN),
+       PINMUX_DATA(LGPIO7_MARK, PS6_15_FN1, PTU7_FN),
+       PINMUX_DATA(APMONCTL_O_MARK, PS6_15_FN2, PTU7_FN),
+       PINMUX_DATA(LGPIO6_MARK, PS6_14_FN1, PTU6_FN),
+       PINMUX_DATA(APMPWBTOUT_O_MARK, PS6_14_FN2, PTU6_FN),
+       PINMUX_DATA(LGPIO5_MARK, PS6_13_FN1, PTU5_FN),
+       PINMUX_DATA(APMSCI_O_MARK, PS6_13_FN2, PTU5_FN),
+       PINMUX_DATA(LGPIO4_MARK, PS6_12_FN1, PTU4_FN),
+       PINMUX_DATA(APMVDDON_MARK, PS6_12_FN2, PTU4_FN),
+       PINMUX_DATA(LGPIO3_MARK, PS6_11_FN1, PTU3_FN),
+       PINMUX_DATA(APMSLPBTN_MARK, PS6_11_FN2, PTU3_FN),
+       PINMUX_DATA(LGPIO2_MARK, PS6_10_FN1, PTU2_FN),
+       PINMUX_DATA(APMPWRBTN_MARK, PS6_10_FN2, PTU2_FN),
+       PINMUX_DATA(LGPIO1_MARK, PS6_9_FN1, PTU1_FN),
+       PINMUX_DATA(APMS5N_MARK, PS6_9_FN2, PTU1_FN),
+       PINMUX_DATA(LGPIO0_MARK, PS6_8_FN1, PTU0_FN),
+       PINMUX_DATA(APMS3N_MARK, PS6_8_FN2, PTU0_FN),
 
        /* PTV FN */
-       PINMUX_DATA(A23_MARK, PS5_7_FN1, PTV7_FN),
-       PINMUX_DATA(TEND0_MARK, PS5_7_FN2, PTV7_FN),
-       PINMUX_DATA(A22_MARK, PS5_6_FN1, PTV6_FN),
-       PINMUX_DATA(DREQ1_MARK, PS5_6_FN2, PTV6_FN),
-       PINMUX_DATA(A21_MARK, PS5_5_FN1, PTV5_FN),
-       PINMUX_DATA(DACK1_MARK, PS5_5_FN2, PTV5_FN),
-       PINMUX_DATA(A20_MARK, PS5_4_FN1, PTV4_FN),
-       PINMUX_DATA(TEND1_MARK, PS5_4_FN2, PTV4_FN),
-       PINMUX_DATA(A19_MARK, PTV3_FN),
-       PINMUX_DATA(A18_MARK, PTV2_FN),
-       PINMUX_DATA(A17_MARK, PTV1_FN),
-       PINMUX_DATA(A16_MARK, PTV0_FN),
+       PINMUX_DATA(A23_MARK, PS6_7_FN1, PTV7_FN),
+       PINMUX_DATA(COM2_RI_MARK, PS6_7_FN2, PTV7_FN),
+       PINMUX_DATA(A22_MARK, PS6_6_FN1, PTV6_FN),
+       PINMUX_DATA(R_SPI_MOSI_MARK, PS6_6_FN2, PTV6_FN),
+       PINMUX_DATA(A21_MARK, PS6_5_FN1, PTV5_FN),
+       PINMUX_DATA(R_SPI_MISO_MARK, PS6_5_FN2, PTV5_FN),
+       PINMUX_DATA(A20_MARK, PS6_4_FN1, PTV4_FN),
+       PINMUX_DATA(R_SPI_RSPCK_MARK, PS6_4_FN2, PTV4_FN),
+       PINMUX_DATA(A19_MARK, PS6_3_FN1, PTV3_FN),
+       PINMUX_DATA(R_SPI_SSL0_MARK, PS6_3_FN2, PTV3_FN),
+       PINMUX_DATA(A18_MARK, PS6_2_FN1, PTV2_FN),
+       PINMUX_DATA(R_SPI_SSL1_MARK, PS6_2_FN2, PTV2_FN),
+       PINMUX_DATA(A17_MARK, PS6_1_FN1, PTV1_FN),
+       PINMUX_DATA(EVENT7_MARK, PS6_1_FN2, PTV1_FN),
+       PINMUX_DATA(A16_MARK, PS6_0_FN1, PTV0_FN),
+       PINMUX_DATA(EVENT6_MARK, PS6_0_FN1, PTV0_FN),
 
        /* PTW FN */
-       PINMUX_DATA(A15_MARK, PTW7_FN),
-       PINMUX_DATA(A14_MARK, PTW6_FN),
-       PINMUX_DATA(A13_MARK, PTW5_FN),
-       PINMUX_DATA(A12_MARK, PTW4_FN),
-       PINMUX_DATA(A11_MARK, PTW3_FN),
-       PINMUX_DATA(A10_MARK, PTW2_FN),
-       PINMUX_DATA(A9_MARK, PTW1_FN),
-       PINMUX_DATA(A8_MARK, PTW0_FN),
+       PINMUX_DATA(A15_MARK, PS7_15_FN1, PTW7_FN),
+       PINMUX_DATA(EVENT5_MARK, PS7_15_FN2, PTW7_FN),
+       PINMUX_DATA(A14_MARK, PS7_14_FN1, PTW6_FN),
+       PINMUX_DATA(EVENT4_MARK, PS7_14_FN2, PTW6_FN),
+       PINMUX_DATA(A13_MARK, PS7_13_FN1, PTW5_FN),
+       PINMUX_DATA(EVENT3_MARK, PS7_13_FN2, PTW5_FN),
+       PINMUX_DATA(A12_MARK, PS7_12_FN1, PTW4_FN),
+       PINMUX_DATA(EVENT2_MARK, PS7_12_FN2, PTW4_FN),
+       PINMUX_DATA(A11_MARK, PS7_11_FN1, PTW3_FN),
+       PINMUX_DATA(EVENT1_MARK, PS7_11_FN2, PTW3_FN),
+       PINMUX_DATA(A10_MARK, PS7_10_FN1, PTW2_FN),
+       PINMUX_DATA(EVENT0_MARK, PS7_10_FN2, PTW2_FN),
+       PINMUX_DATA(A9_MARK, PS7_9_FN1, PTW1_FN),
+       PINMUX_DATA(CTS4_MARK, PS7_9_FN2, PTW1_FN),
+       PINMUX_DATA(A8_MARK, PS7_8_FN1, PTW0_FN),
+       PINMUX_DATA(CTS2_MARK, PS7_8_FN2, PTW0_FN),
 
        /* PTX FN */
-       PINMUX_DATA(A7_MARK, PTX7_FN),
-       PINMUX_DATA(A6_MARK, PTX6_FN),
-       PINMUX_DATA(A5_MARK, PTX5_FN),
-       PINMUX_DATA(A4_MARK, PTX4_FN),
+       PINMUX_DATA(A7_MARK, PS7_7_FN1, PTX7_FN),
+       PINMUX_DATA(RTS2_MARK, PS7_7_FN2, PTX7_FN),
+       PINMUX_DATA(A6_MARK, PS7_6_FN1, PTX6_FN),
+       PINMUX_DATA(SIM_D_MARK, PS7_6_FN2, PTX6_FN),
+       PINMUX_DATA(A5_MARK, PS7_5_FN1, PTX5_FN),
+       PINMUX_DATA(SIM_CLK_MARK, PS7_5_FN2, PTX5_FN),
+       PINMUX_DATA(A4_MARK, PS7_4_FN1, PTX4_FN),
+       PINMUX_DATA(SIM_RST_MARK, PS7_4_FN2, PTX4_FN),
        PINMUX_DATA(A3_MARK, PTX3_FN),
        PINMUX_DATA(A2_MARK, PTX2_FN),
        PINMUX_DATA(A1_MARK, PTX1_FN),
@@ -954,6 +1093,24 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(D2_MARK, PTY2_FN),
        PINMUX_DATA(D1_MARK, PTY1_FN),
        PINMUX_DATA(D0_MARK, PTY0_FN),
+
+       /* PTZ FN */
+       PINMUX_DATA(MMCDAT7_MARK, PS8_15_FN1, PTZ7_FN),
+       PINMUX_DATA(ON_DQ7_MARK, PS8_15_FN2, PTZ7_FN),
+       PINMUX_DATA(MMCDAT6_MARK, PS8_14_FN1, PTZ6_FN),
+       PINMUX_DATA(ON_DQ6_MARK, PS8_14_FN2, PTZ6_FN),
+       PINMUX_DATA(MMCDAT5_MARK, PS8_13_FN1, PTZ5_FN),
+       PINMUX_DATA(ON_DQ5_MARK, PS8_13_FN2, PTZ5_FN),
+       PINMUX_DATA(MMCDAT4_MARK, PS8_12_FN1, PTZ4_FN),
+       PINMUX_DATA(ON_DQ4_MARK, PS8_12_FN2, PTZ4_FN),
+       PINMUX_DATA(MMCDAT3_MARK, PS8_11_FN1, PTZ3_FN),
+       PINMUX_DATA(ON_DQ3_MARK, PS8_11_FN2, PTZ3_FN),
+       PINMUX_DATA(MMCDAT2_MARK, PS8_10_FN1, PTZ2_FN),
+       PINMUX_DATA(ON_DQ2_MARK, PS8_10_FN2, PTZ2_FN),
+       PINMUX_DATA(MMCDAT1_MARK, PS8_9_FN1, PTZ1_FN),
+       PINMUX_DATA(ON_DQ1_MARK, PS8_9_FN2, PTZ1_FN),
+       PINMUX_DATA(MMCDAT0_MARK, PS8_8_FN1, PTZ0_FN),
+       PINMUX_DATA(ON_DQ0_MARK, PS8_8_FN2, PTZ0_FN),
 };
 
 static struct pinmux_gpio pinmux_gpios[] = {
@@ -1048,7 +1205,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTI0, PTI0_DATA),
 
        /* PTJ */
-       PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
        PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
        PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
        PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
@@ -1068,7 +1224,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
 
        /* PTL */
-       PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
        PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
        PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
        PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
@@ -1078,6 +1233,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
 
        /* PTM */
+       PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
        PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
        PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
        PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
@@ -1087,7 +1243,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
 
        /* PTN */
-       PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
        PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
        PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
        PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
@@ -1107,6 +1262,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTO0, PTO0_DATA),
 
        /* PTP */
+       PINMUX_GPIO(GPIO_PTP7, PTP7_DATA),
        PINMUX_GPIO(GPIO_PTP6, PTP6_DATA),
        PINMUX_GPIO(GPIO_PTP5, PTP5_DATA),
        PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
@@ -1145,6 +1301,8 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
 
        /* PTT */
+       PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
+       PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
        PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
        PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
        PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
@@ -1212,54 +1370,35 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
        PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
 
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
        PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
        PINMUX_GPIO(GPIO_FN_WE1, WE1_MARK),
        PINMUX_GPIO(GPIO_FN_RDY, RDY_MARK),
-       PINMUX_GPIO(GPIO_FN_MD10, MD10_MARK),
-       PINMUX_GPIO(GPIO_FN_MD9, MD9_MARK),
-       PINMUX_GPIO(GPIO_FN_MD8, MD8_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
-       PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
-       PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
-       PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
-       PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
-       PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
-       PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
-       PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
        PINMUX_GPIO(GPIO_FN_ET0_MDC, ET0_MDC_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDIO_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDC_MARK),
        PINMUX_GPIO(GPIO_FN_ET1_MDC, ET1_MDC_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDIO_MARK),
-       PINMUX_GPIO(GPIO_FN_WPSZ1, WPSZ1_MARK),
-       PINMUX_GPIO(GPIO_FN_WPSZ0, WPSZ0_MARK),
-       PINMUX_GPIO(GPIO_FN_FWID, FWID_MARK),
-       PINMUX_GPIO(GPIO_FN_FLSHSZ, FLSHSZ_MARK),
-       PINMUX_GPIO(GPIO_FN_LPC_SPIEN, LPC_SPIEN_MARK),
-       PINMUX_GPIO(GPIO_FN_BASEL, BASEL_MARK),
-
-       /* PTC (mobule: SD) */
-       PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDC_MARK),
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NRE, ON_NRE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NWE, ON_NWE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NWP, ON_NWP_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NCE0, ON_NCE0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_R_B0, ON_R_B0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_ALE, ON_ALE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_CLE, ON_CLE_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
+
+       /* PTC (mobule: IRQ, PWMU) */
        PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
@@ -1268,80 +1407,102 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
-       PINMUX_GPIO(GPIO_FN_MD6, MD6_MARK),
-       PINMUX_GPIO(GPIO_FN_MD5, MD5_MARK),
-       PINMUX_GPIO(GPIO_FN_MD3, MD3_MARK),
-       PINMUX_GPIO(GPIO_FN_MD2, MD2_MARK),
-       PINMUX_GPIO(GPIO_FN_MD1, MD1_MARK),
-       PINMUX_GPIO(GPIO_FN_MD0, MD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
-       PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU0, PWMU0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU1, PWMU1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU2, PWMU2_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU3, PWMU3_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU4, PWMU4_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU5, PWMU5_MARK),
+
+       /* PTD (mobule: SPI0, DMAC) */
+       PINMUX_GPIO(GPIO_FN_SP0_MOSI, SP0_MOSI_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_MISO, SP0_MISO_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SCK, SP0_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SCK_FB, SP0_SCK_FB_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS0, SP0_SS0_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS2, SP0_SS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS3, SP0_SS3_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
 
-       /* PTE (mobule: EtherC) */
-       PINMUX_GPIO(GPIO_FN_ET0_CRS_DV, ET0_CRS_DV_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TXD1, ET0_TXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TXD0, ET0_TXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TX_EN, ET0_TX_EN_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_REF_CLK, ET0_REF_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RXD1, ET0_RXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RXD0, ET0_RXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RX_ER, ET0_RX_ER_MARK),
-
-       /* PTF (mobule: EtherC) */
-       PINMUX_GPIO(GPIO_FN_ET1_CRS_DV, ET1_CRS_DV_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TXD1, ET1_TXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TXD0, ET1_TXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TX_EN, ET1_TX_EN_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_REF_CLK, ET1_REF_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RXD1, ET1_RXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RXD0, ET1_RXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RX_ER, ET1_RX_ER_MARK),
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX0, PWX0_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX1, PWX1_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX2, PWX2_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX3, PWX3_MARK),
+       /* PTE (mobule: RMII) */
+       PINMUX_GPIO(GPIO_FN_RMII0_CRS_DV, RMII0_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXD1, RMII0_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXD0, RMII0_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXEN, RMII0_TXEN_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_REFCLK, RMII0_REFCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RXD1, RMII0_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RXD0, RMII0_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RX_ER, RMII0_RX_ER_MARK),
+
+       /* PTF (mobule: RMII, SerMux) */
+       PINMUX_GPIO(GPIO_FN_RMII1_CRS_DV, RMII1_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXD1, RMII1_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXD0, RMII1_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXEN, RMII1_TXEN_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_REFCLK, RMII1_REFCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RXD1, RMII1_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RXD0, RMII1_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RX_ER, RMII1_RX_ER_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       PINMUX_GPIO(GPIO_FN_BOOTFMS, BOOTFMS_MARK),
+       PINMUX_GPIO(GPIO_FN_BOOTWP, BOOTWP_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
        PINMUX_GPIO(GPIO_FN_SERIRQ, SERIRQ_MARK),
-       PINMUX_GPIO(GPIO_FN_CLKRUN, CLKRUN_MARK),
+       PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
        PINMUX_GPIO(GPIO_FN_LPCPD, LPCPD_MARK),
        PINMUX_GPIO(GPIO_FN_LDRQ, LDRQ_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCCLK, MMCCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCCMD, MMCCMD_MARK),
 
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
-       PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
-       PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        PINMUX_GPIO(GPIO_FN_SP1_MOSI, SP1_MOSI_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_MISO, SP1_MISO_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SCK, SP1_SCK_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SCK_FB, SP1_SCK_FB_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SS0, SP1_SS0_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SS1, SP1_SS1_MARK),
-       PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
+       PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
 
-       /* PTI (mobule: INTC) */
-       PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
+       /* PTI (mobule: LBSC, SDHI) */
+       PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+       PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+       PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+       PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+       PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+       PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+       PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+       PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
 
        /* PTJ (mobule: SCIF234, SERMUX) */
-       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
        PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
-       PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
-       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
 
-       /* PTK (mobule: SERMUX) */
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
        PINMUX_GPIO(GPIO_FN_COM2_TXD, COM2_TXD_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_RXD, COM2_RXD_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_RTS, COM2_RTS_MARK),
@@ -1349,62 +1510,65 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_COM2_DTR, COM2_DTR_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_DSR, COM2_DSR_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_DCD, COM2_DCD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_CLKOUT, CLKOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
 
-       /* PTL (mobule: SERMUX) */
-       PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
        PINMUX_GPIO(GPIO_FN_RAC_RXD, RAC_RXD_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_RTS, RAC_RTS_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_CTS, RAC_CTS_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DTR, RAC_DTR_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DSR, RAC_DSR_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DCD, RAC_DCD_MARK),
-       PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTM (mobule: LBSC, IIC) */
+       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
+       PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
+       PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
        PINMUX_GPIO(GPIO_FN_SDA6, SDA6_MARK),
        PINMUX_GPIO(GPIO_FN_SCL6, SCL6_MARK),
        PINMUX_GPIO(GPIO_FN_SDA7, SDA7_MARK),
        PINMUX_GPIO(GPIO_FN_SCL7, SCL7_MARK),
-       PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
-       PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
-       PINMUX_GPIO(GPIO_FN_FMS1, FMS1_MARK),
 
-       /* PTN (mobule: SCIF234, EVC) */
-       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       PINMUX_GPIO(GPIO_FN_VBUS_EN, VBUS_EN_MARK),
+       PINMUX_GPIO(GPIO_FN_VBUS_OC, VBUS_OC_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTRST, JMCTRST_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_SUB_CLKIN, SUB_CLKIN_MARK),
 
-       /* PTO (mobule: SGPIO) */
+       /* PTO (mobule: SGPIO, SerMux) */
        PINMUX_GPIO(GPIO_FN_SGPIO0_CLK, SGPIO0_CLK_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_LOAD, SGPIO0_LOAD_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_DI, SGPIO0_DI_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_DO, SGPIO0_DO_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_CLK, SGPIO2_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_LOAD, SGPIO2_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_DI, SGPIO2_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_DO, SGPIO2_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
 
-       /* PTP (mobule: JMC, SCIF234) */
-       PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCRST, JMCRST_MARK),
-       PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
-       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+       /* PTP (mobule: EVC, ADC) */
 
        /* PTQ (mobule: LPC) */
        PINMUX_GPIO(GPIO_FN_LAD3, LAD3_MARK),
@@ -1439,31 +1603,41 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
        PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       /* PTT (mobule: PWMX, AUD) */
+       PINMUX_GPIO(GPIO_FN_PWMX7, PWMX7_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX6, PWMX6_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX5, PWMX5_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX4, PWMX4_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX3, PWMX3_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX2, PWMX2_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX1, PWMX1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX0, PWMX0_MARK),
        PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
        PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
        PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
        PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX7, PWX7_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX6, PWX6_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX5, PWX5_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX4, PWX4_MARK),
-
-       /* PTU (mobule: LBSC, DMAC) */
-       PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
-       PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
-       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-       PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
-       PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
-       PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
-       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTU (mobule: LPC, APM) */
+       PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
+       PINMUX_GPIO(GPIO_FN_APMONCTL_O, APMONCTL_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMPWBTOUT_O, APMPWBTOUT_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMSCI_O, APMSCI_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMVDDON, APMVDDON_MARK),
+       PINMUX_GPIO(GPIO_FN_APMSLPBTN, APMSLPBTN_MARK),
+       PINMUX_GPIO(GPIO_FN_APMPWRBTN, APMPWRBTN_MARK),
+       PINMUX_GPIO(GPIO_FN_APMS5N, APMS5N_MARK),
+       PINMUX_GPIO(GPIO_FN_APMS3N, APMS3N_MARK),
+
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
        PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
        PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
@@ -1472,12 +1646,20 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
        PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
        PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
-       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_MOSI, R_SPI_MOSI_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_MISO, R_SPI_MISO_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_RSPCK, R_SPI_RSPCK_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_SSL0, R_SPI_SSL0_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_SSL1, R_SPI_SSL1_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_DI, VBIOS_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_DO, VBIOS_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_CLK, VBIOS_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_CS, VBIOS_CS_MARK),
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
        PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
        PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
@@ -1487,6 +1669,14 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
        PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
        PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
 
        /* PTX (mobule: LBSC) */
        PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
@@ -1497,6 +1687,10 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
        PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
        PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
 
        /* PTY (mobule: LBSC) */
        PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
@@ -1507,18 +1701,36 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
        PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
        PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       PINMUX_GPIO(GPIO_FN_MMCDAT7, MMCDAT7_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT6, MMCDAT6_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT5, MMCDAT5_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT4, MMCDAT4_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT3, MMCDAT3_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT2, MMCDAT2_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT1, MMCDAT1_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT0, MMCDAT0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ7, ON_DQ7_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ6, ON_DQ6_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ5, ON_DQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ4, ON_DQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ3, ON_DQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ2, ON_DQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ1, ON_DQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ0, ON_DQ0_MARK),
  };
 
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        { PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) {
-               PTA7_FN, PTA7_OUT, PTA7_IN, 0,
-               PTA6_FN, PTA6_OUT, PTA6_IN, 0,
-               PTA5_FN, PTA5_OUT, PTA5_IN, 0,
-               PTA4_FN, PTA4_OUT, PTA4_IN, 0,
-               PTA3_FN, PTA3_OUT, PTA3_IN, 0,
-               PTA2_FN, PTA2_OUT, PTA2_IN, 0,
-               PTA1_FN, PTA1_OUT, PTA1_IN, 0,
-               PTA0_FN, PTA0_OUT, PTA0_IN, 0 }
+               PTA7_FN, PTA7_OUT, PTA7_IN, PTA7_IN_PU,
+               PTA6_FN, PTA6_OUT, PTA6_IN, PTA6_IN_PU,
+               PTA5_FN, PTA5_OUT, PTA5_IN, PTA5_IN_PU,
+               PTA4_FN, PTA4_OUT, PTA4_IN, PTA4_IN_PU,
+               PTA3_FN, PTA3_OUT, PTA3_IN, PTA3_IN_PU,
+               PTA2_FN, PTA2_OUT, PTA2_IN, PTA2_IN_PU,
+               PTA1_FN, PTA1_OUT, PTA1_IN, PTA1_IN_PU,
+               PTA0_FN, PTA0_OUT, PTA0_IN, PTA0_IN_PU }
        },
        { PINMUX_CFG_REG("PBCR", 0xffec0002, 16, 2) {
                PTB7_FN, PTB7_OUT, PTB7_IN, 0,
@@ -1541,125 +1753,126 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTC0_FN, PTC0_OUT, PTC0_IN, 0 }
        },
        { PINMUX_CFG_REG("PDCR", 0xffec0006, 16, 2) {
-               PTD7_FN, PTD7_OUT, PTD7_IN, 0,
-               PTD6_FN, PTD6_OUT, PTD6_IN, 0,
-               PTD5_FN, PTD5_OUT, PTD5_IN, 0,
-               PTD4_FN, PTD4_OUT, PTD4_IN, 0,
-               PTD3_FN, PTD3_OUT, PTD3_IN, 0,
-               PTD2_FN, PTD2_OUT, PTD2_IN, 0,
-               PTD1_FN, PTD1_OUT, PTD1_IN, 0,
-               PTD0_FN, PTD0_OUT, PTD0_IN, 0 }
+               PTD7_FN, PTD7_OUT, PTD7_IN, PTD7_IN_PU,
+               PTD6_FN, PTD6_OUT, PTD6_IN, PTD6_IN_PU,
+               PTD5_FN, PTD5_OUT, PTD5_IN, PTD5_IN_PU,
+               PTD4_FN, PTD4_OUT, PTD4_IN, PTD4_IN_PU,
+               PTD3_FN, PTD3_OUT, PTD3_IN, PTD3_IN_PU,
+               PTD2_FN, PTD2_OUT, PTD2_IN, PTD2_IN_PU,
+               PTD1_FN, PTD1_OUT, PTD1_IN, PTD1_IN_PU,
+               PTD0_FN, PTD0_OUT, PTD0_IN, PTD0_IN_PU }
        },
        { PINMUX_CFG_REG("PECR", 0xffec0008, 16, 2) {
-               PTE7_FN, PTE7_OUT, PTE7_IN, 0,
-               PTE6_FN, PTE6_OUT, PTE6_IN, 0,
-               PTE5_FN, PTE5_OUT, PTE5_IN, 0,
-               PTE4_FN, PTE4_OUT, PTE4_IN, 0,
-               PTE3_FN, PTE3_OUT, PTE3_IN, 0,
-               PTE2_FN, PTE2_OUT, PTE2_IN, 0,
-               PTE1_FN, PTE1_OUT, PTE1_IN, 0,
-               PTE0_FN, PTE0_OUT, PTE0_IN, 0 }
+               PTE7_FN, PTE7_OUT, PTE7_IN, PTE7_IN_PU,
+               PTE6_FN, PTE6_OUT, PTE6_IN, PTE6_IN_PU,
+               PTE5_FN, PTE5_OUT, PTE5_IN, PTE5_IN_PU,
+               PTE4_FN, PTE4_OUT, PTE4_IN, PTE4_IN_PU,
+               PTE3_FN, PTE3_OUT, PTE3_IN, PTE3_IN_PU,
+               PTE2_FN, PTE2_OUT, PTE2_IN, PTE2_IN_PU,
+               PTE1_FN, PTE1_OUT, PTE1_IN, PTE1_IN_PU,
+               PTE0_FN, PTE0_OUT, PTE0_IN, PTE0_IN_PU }
        },
        { PINMUX_CFG_REG("PFCR", 0xffec000a, 16, 2) {
-               PTF7_FN, PTF7_OUT, PTF7_IN, 0,
-               PTF6_FN, PTF6_OUT, PTF6_IN, 0,
-               PTF5_FN, PTF5_OUT, PTF5_IN, 0,
-               PTF4_FN, PTF4_OUT, PTF4_IN, 0,
-               PTF3_FN, PTF3_OUT, PTF3_IN, 0,
-               PTF2_FN, PTF2_OUT, PTF2_IN, 0,
-               PTF1_FN, PTF1_OUT, PTF1_IN, 0,
-               PTF0_FN, PTF0_OUT, PTF0_IN, 0 }
+               PTF7_FN, PTF7_OUT, PTF7_IN, PTF7_IN_PU,
+               PTF6_FN, PTF6_OUT, PTF6_IN, PTF6_IN_PU,
+               PTF5_FN, PTF5_OUT, PTF5_IN, PTF5_IN_PU,
+               PTF4_FN, PTF4_OUT, PTF4_IN, PTF4_IN_PU,
+               PTF3_FN, PTF3_OUT, PTF3_IN, PTF3_IN_PU,
+               PTF2_FN, PTF2_OUT, PTF2_IN, PTF2_IN_PU,
+               PTF1_FN, PTF1_OUT, PTF1_IN, PTF1_IN_PU,
+               PTF0_FN, PTF0_OUT, PTF0_IN, PTF0_IN_PU }
        },
        { PINMUX_CFG_REG("PGCR", 0xffec000c, 16, 2) {
-               PTG7_FN, PTG7_OUT, PTG7_IN, 0,
-               PTG6_FN, PTG6_OUT, PTG6_IN, 0,
+               PTG7_FN, PTG7_OUT, PTG7_IN, PTG7_IN_PU ,
+               PTG6_FN, PTG6_OUT, PTG6_IN, PTG6_IN_PU ,
                PTG5_FN, PTG5_OUT, PTG5_IN, 0,
-               PTG4_FN, PTG4_OUT, PTG4_IN, 0,
+               PTG4_FN, PTG4_OUT, PTG4_IN, PTG4_IN_PU ,
                PTG3_FN, PTG3_OUT, PTG3_IN, 0,
                PTG2_FN, PTG2_OUT, PTG2_IN, 0,
                PTG1_FN, PTG1_OUT, PTG1_IN, 0,
                PTG0_FN, PTG0_OUT, PTG0_IN, 0 }
        },
        { PINMUX_CFG_REG("PHCR", 0xffec000e, 16, 2) {
-               PTH7_FN, PTH7_OUT, PTH7_IN, 0,
-               PTH6_FN, PTH6_OUT, PTH6_IN, 0,
-               PTH5_FN, PTH5_OUT, PTH5_IN, 0,
-               PTH4_FN, PTH4_OUT, PTH4_IN, 0,
-               PTH3_FN, PTH3_OUT, PTH3_IN, 0,
-               PTH2_FN, PTH2_OUT, PTH2_IN, 0,
-               PTH1_FN, PTH1_OUT, PTH1_IN, 0,
-               PTH0_FN, PTH0_OUT, PTH0_IN, 0 }
+               PTH7_FN, PTH7_OUT, PTH7_IN, PTH7_IN_PU,
+               PTH6_FN, PTH6_OUT, PTH6_IN, PTH6_IN_PU,
+               PTH5_FN, PTH5_OUT, PTH5_IN, PTH5_IN_PU,
+               PTH4_FN, PTH4_OUT, PTH4_IN, PTH4_IN_PU,
+               PTH3_FN, PTH3_OUT, PTH3_IN, PTH3_IN_PU,
+               PTH2_FN, PTH2_OUT, PTH2_IN, PTH2_IN_PU,
+               PTH1_FN, PTH1_OUT, PTH1_IN, PTH1_IN_PU,
+               PTH0_FN, PTH0_OUT, PTH0_IN, PTH0_IN_PU }
        },
        { PINMUX_CFG_REG("PICR", 0xffec0010, 16, 2) {
-               PTI7_FN, PTI7_OUT, PTI7_IN, 0,
-               PTI6_FN, PTI6_OUT, PTI6_IN, 0,
+               PTI7_FN, PTI7_OUT, PTI7_IN, PTI7_IN_PU,
+               PTI6_FN, PTI6_OUT, PTI6_IN, PTI6_IN_PU,
                PTI5_FN, PTI5_OUT, PTI5_IN, 0,
-               PTI4_FN, PTI4_OUT, PTI4_IN, 0,
-               PTI3_FN, PTI3_OUT, PTI3_IN, 0,
-               PTI2_FN, PTI2_OUT, PTI2_IN, 0,
-               PTI1_FN, PTI1_OUT, PTI1_IN, 0,
-               PTI0_FN, PTI0_OUT, PTI0_IN, 0 }
+               PTI4_FN, PTI4_OUT, PTI4_IN, PTI4_IN_PU,
+               PTI3_FN, PTI3_OUT, PTI3_IN, PTI3_IN_PU,
+               PTI2_FN, PTI2_OUT, PTI2_IN, PTI2_IN_PU,
+               PTI1_FN, PTI1_OUT, PTI1_IN, PTI1_IN_PU,
+               PTI0_FN, PTI0_OUT, PTI0_IN, PTI0_IN_PU }
        },
        { PINMUX_CFG_REG("PJCR", 0xffec0012, 16, 2) {
-               PTJ7_FN, PTJ7_OUT, PTJ7_IN, 0,
-               PTJ6_FN, PTJ6_OUT, PTJ6_IN, 0,
-               PTJ5_FN, PTJ5_OUT, PTJ5_IN, 0,
-               PTJ4_FN, PTJ4_OUT, PTJ4_IN, 0,
-               PTJ3_FN, PTJ3_OUT, PTJ3_IN, 0,
-               PTJ2_FN, PTJ2_OUT, PTJ2_IN, 0,
-               PTJ1_FN, PTJ1_OUT, PTJ1_IN, 0,
-               PTJ0_FN, PTJ0_OUT, PTJ0_IN, 0 }
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTJ6_FN, PTJ6_OUT, PTJ6_IN, PTJ6_IN_PU,
+               PTJ5_FN, PTJ5_OUT, PTJ5_IN, PTJ5_IN_PU,
+               PTJ4_FN, PTJ4_OUT, PTJ4_IN, PTJ4_IN_PU,
+               PTJ3_FN, PTJ3_OUT, PTJ3_IN, PTJ3_IN_PU,
+               PTJ2_FN, PTJ2_OUT, PTJ2_IN, PTJ2_IN_PU,
+               PTJ1_FN, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU,
+               PTJ0_FN, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU }
        },
        { PINMUX_CFG_REG("PKCR", 0xffec0014, 16, 2) {
-               PTK7_FN, PTK7_OUT, PTK7_IN, 0,
-               PTK6_FN, PTK6_OUT, PTK6_IN, 0,
-               PTK5_FN, PTK5_OUT, PTK5_IN, 0,
-               PTK4_FN, PTK4_OUT, PTK4_IN, 0,
-               PTK3_FN, PTK3_OUT, PTK3_IN, 0,
-               PTK2_FN, PTK2_OUT, PTK2_IN, 0,
-               PTK1_FN, PTK1_OUT, PTK1_IN, 0,
-               PTK0_FN, PTK0_OUT, PTK0_IN, 0 }
+               PTK7_FN, PTK7_OUT, PTK7_IN, PTK7_IN_PU,
+               PTK6_FN, PTK6_OUT, PTK6_IN, PTK6_IN_PU,
+               PTK5_FN, PTK5_OUT, PTK5_IN, PTK5_IN_PU,
+               PTK4_FN, PTK4_OUT, PTK4_IN, PTK4_IN_PU,
+               PTK3_FN, PTK3_OUT, PTK3_IN, PTK3_IN_PU,
+               PTK2_FN, PTK2_OUT, PTK2_IN, PTK2_IN_PU,
+               PTK1_FN, PTK1_OUT, PTK1_IN, PTK1_IN_PU,
+               PTK0_FN, PTK0_OUT, PTK0_IN, PTK0_IN_PU }
        },
        { PINMUX_CFG_REG("PLCR", 0xffec0016, 16, 2) {
-               PTL7_FN, PTL7_OUT, PTL7_IN, 0,
-               PTL6_FN, PTL6_OUT, PTL6_IN, 0,
-               PTL5_FN, PTL5_OUT, PTL5_IN, 0,
-               PTL4_FN, PTL4_OUT, PTL4_IN, 0,
-               PTL3_FN, PTL3_OUT, PTL3_IN, 0,
-               PTL2_FN, PTL2_OUT, PTL2_IN, 0,
-               PTL1_FN, PTL1_OUT, PTL1_IN, 0,
-               PTL0_FN, PTL0_OUT, PTL0_IN, 0 }
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTL6_FN, PTL6_OUT, PTL6_IN, PTL6_IN_PU,
+               PTL5_FN, PTL5_OUT, PTL5_IN, PTL5_IN_PU,
+               PTL4_FN, PTL4_OUT, PTL4_IN, PTL4_IN_PU,
+               PTL3_FN, PTL3_OUT, PTL3_IN, PTL3_IN_PU,
+               PTL2_FN, PTL2_OUT, PTL2_IN, PTL2_IN_PU,
+               PTL1_FN, PTL1_OUT, PTL1_IN, PTL1_IN_PU,
+               PTL0_FN, PTL0_OUT, PTL0_IN, PTL0_IN_PU }
        },
        { PINMUX_CFG_REG("PMCR", 0xffec0018, 16, 2) {
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               PTM6_FN, PTM6_OUT, PTM6_IN, 0,
-               PTM5_FN, PTM5_OUT, PTM5_IN, 0,
-               PTM4_FN, PTM4_OUT, PTM4_IN, 0,
+               PTM7_FN, PTM7_OUT, PTM7_IN, PTM7_IN_PU,
+               PTM6_FN, PTM6_OUT, PTM6_IN, PTM6_IN_PU,
+               PTM5_FN, PTM5_OUT, PTM5_IN, PTM5_IN_PU,
+               PTM4_FN, PTM4_OUT, PTM4_IN, PTM4_IN_PU,
                PTM3_FN, PTM3_OUT, PTM3_IN, 0,
                PTM2_FN, PTM2_OUT, PTM2_IN, 0,
                PTM1_FN, PTM1_OUT, PTM1_IN, 0,
                PTM0_FN, PTM0_OUT, PTM0_IN, 0 }
        },
        { PINMUX_CFG_REG("PNCR", 0xffec001a, 16, 2) {
-               PTN7_FN, PTN7_OUT, PTN7_IN, 0,
+               0, 0, 0, 0,     /* reserved: always set 1 */
                PTN6_FN, PTN6_OUT, PTN6_IN, 0,
                PTN5_FN, PTN5_OUT, PTN5_IN, 0,
-               PTN4_FN, PTN4_OUT, PTN4_IN, 0,
-               PTN3_FN, PTN3_OUT, PTN3_IN, 0,
-               PTN2_FN, PTN2_OUT, PTN2_IN, 0,
-               PTN1_FN, PTN1_OUT, PTN1_IN, 0,
-               PTN0_FN, PTN0_OUT, PTN0_IN, 0 }
+               PTN4_FN, PTN4_OUT, PTN4_IN, PTN4_IN_PU,
+               PTN3_FN, PTN3_OUT, PTN3_IN, PTN3_IN_PU,
+               PTN2_FN, PTN2_OUT, PTN2_IN, PTN2_IN_PU,
+               PTN1_FN, PTN1_OUT, PTN1_IN, PTN1_IN_PU,
+               PTN0_FN, PTN0_OUT, PTN0_IN, PTN0_IN_PU }
        },
        { PINMUX_CFG_REG("POCR", 0xffec001c, 16, 2) {
-               PTO7_FN, PTO7_OUT, PTO7_IN, 0,
-               PTO6_FN, PTO6_OUT, PTO6_IN, 0,
-               PTO5_FN, PTO5_OUT, PTO5_IN, 0,
-               PTO4_FN, PTO4_OUT, PTO4_IN, 0,
-               PTO3_FN, PTO3_OUT, PTO3_IN, 0,
-               PTO2_FN, PTO2_OUT, PTO2_IN, 0,
-               PTO1_FN, PTO1_OUT, PTO1_IN, 0,
-               PTO0_FN, PTO0_OUT, PTO0_IN, 0 }
+               PTO7_FN, PTO7_OUT, PTO7_IN, PTO7_IN_PU,
+               PTO6_FN, PTO6_OUT, PTO6_IN, PTO6_IN_PU,
+               PTO5_FN, PTO5_OUT, PTO5_IN, PTO5_IN_PU,
+               PTO4_FN, PTO4_OUT, PTO4_IN, PTO4_IN_PU,
+               PTO3_FN, PTO3_OUT, PTO3_IN, PTO3_IN_PU,
+               PTO2_FN, PTO2_OUT, PTO2_IN, PTO2_IN_PU,
+               PTO1_FN, PTO1_OUT, PTO1_IN, PTO1_IN_PU,
+               PTO0_FN, PTO0_OUT, PTO0_IN, PTO0_IN_PU }
        },
+#if 0  /* FIXME: Remove it? */
        { PINMUX_CFG_REG("PPCR", 0xffec001e, 16, 2) {
                0, 0, 0, 0,     /* reserved: always set 1 */
                PTP6_FN, PTP6_OUT, PTP6_IN, 0,
@@ -1670,6 +1883,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTP1_FN, PTP1_OUT, PTP1_IN, 0,
                PTP0_FN, PTP0_OUT, PTP0_IN, 0 }
        },
+#endif
        { PINMUX_CFG_REG("PQCR", 0xffec0020, 16, 2) {
                0, 0, 0, 0,     /* reserved: always set 1 */
                PTQ6_FN, PTQ6_OUT, PTQ6_IN, 0,
@@ -1701,14 +1915,14 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTS0_FN, PTS0_OUT, PTS0_IN, 0 }
        },
        { PINMUX_CFG_REG("PTCR", 0xffec0026, 16, 2) {
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               PTT5_FN, PTT5_OUT, PTT5_IN, 0,
-               PTT4_FN, PTT4_OUT, PTT4_IN, 0,
-               PTT3_FN, PTT3_OUT, PTT3_IN, 0,
-               PTT2_FN, PTT2_OUT, PTT2_IN, 0,
-               PTT1_FN, PTT1_OUT, PTT1_IN, 0,
-               PTT0_FN, PTT0_OUT, PTT0_IN, 0 }
+               PTT7_FN, PTT7_OUT, PTT7_IN, PTO7_IN_PU,
+               PTT6_FN, PTT6_OUT, PTT6_IN, PTO6_IN_PU,
+               PTT5_FN, PTT5_OUT, PTT5_IN, PTO5_IN_PU,
+               PTT4_FN, PTT4_OUT, PTT4_IN, PTO4_IN_PU,
+               PTT3_FN, PTT3_OUT, PTT3_IN, PTO3_IN_PU,
+               PTT2_FN, PTT2_OUT, PTT2_IN, PTO2_IN_PU,
+               PTT1_FN, PTT1_OUT, PTT1_IN, PTO1_IN_PU,
+               PTT0_FN, PTT0_OUT, PTT0_IN, PTO0_IN_PU }
        },
        { PINMUX_CFG_REG("PUCR", 0xffec0028, 16, 2) {
                PTU7_FN, PTU7_OUT, PTU7_IN, PTU7_IN_PU,
@@ -1727,16 +1941,16 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTV4_FN, PTV4_OUT, PTV4_IN, PTV4_IN_PU,
                PTV3_FN, PTV3_OUT, PTV3_IN, PTV3_IN_PU,
                PTV2_FN, PTV2_OUT, PTV2_IN, PTV2_IN_PU,
-               PTV1_FN, PTV1_OUT, PTV1_IN, PTV1_IN_PU,
-               PTV0_FN, PTV0_OUT, PTV0_IN, PTV0_IN_PU }
+               PTV1_FN, PTV1_OUT, PTV1_IN, 0,
+               PTV0_FN, PTV0_OUT, PTV0_IN, 0 }
        },
        { PINMUX_CFG_REG("PWCR", 0xffec002c, 16, 2) {
-               PTW7_FN, PTW7_OUT, PTW7_IN, PTW7_IN_PU,
-               PTW6_FN, PTW6_OUT, PTW6_IN, PTW6_IN_PU,
-               PTW5_FN, PTW5_OUT, PTW5_IN, PTW5_IN_PU,
-               PTW4_FN, PTW4_OUT, PTW4_IN, PTW4_IN_PU,
-               PTW3_FN, PTW3_OUT, PTW3_IN, PTW3_IN_PU,
-               PTW2_FN, PTW2_OUT, PTW2_IN, PTW2_IN_PU,
+               PTW7_FN, PTW7_OUT, PTW7_IN, 0,
+               PTW6_FN, PTW6_OUT, PTW6_IN, 0,
+               PTW5_FN, PTW5_OUT, PTW5_IN, 0,
+               PTW4_FN, PTW4_OUT, PTW4_IN, 0,
+               PTW3_FN, PTW3_OUT, PTW3_IN, 0,
+               PTW2_FN, PTW2_OUT, PTW2_IN, 0,
                PTW1_FN, PTW1_OUT, PTW1_IN, PTW1_IN_PU,
                PTW0_FN, PTW0_OUT, PTW0_IN, PTW0_IN_PU }
        },
@@ -1761,32 +1975,32 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTY0_FN, PTY0_OUT, PTY0_IN, PTY0_IN_PU }
        },
        { PINMUX_CFG_REG("PZCR", 0xffec0032, 16, 2) {
-               0, PTZ7_OUT, PTZ7_IN, 0,
-               0, PTZ6_OUT, PTZ6_IN, 0,
-               0, PTZ5_OUT, PTZ5_IN, 0,
-               0, PTZ4_OUT, PTZ4_IN, 0,
-               0, PTZ3_OUT, PTZ3_IN, 0,
-               0, PTZ2_OUT, PTZ2_IN, 0,
-               0, PTZ1_OUT, PTZ1_IN, 0,
-               0, PTZ0_OUT, PTZ0_IN, 0 }
+               PTZ7_FN, PTZ7_OUT, PTZ7_IN, 0,
+               PTZ6_FN, PTZ6_OUT, PTZ6_IN, 0,
+               PTZ5_FN, PTZ5_OUT, PTZ5_IN, 0,
+               PTZ4_FN, PTZ4_OUT, PTZ4_IN, 0,
+               PTZ3_FN, PTZ3_OUT, PTZ3_IN, 0,
+               PTZ2_FN, PTZ2_OUT, PTZ2_IN, 0,
+               PTZ1_FN, PTZ1_OUT, PTZ1_IN, 0,
+               PTZ0_FN, PTZ0_OUT, PTZ0_IN, 0 }
        },
 
        { PINMUX_CFG_REG("PSEL0", 0xffec0070, 16, 1) {
-               PS0_15_FN3, PS0_15_FN1,
-               PS0_14_FN3, PS0_14_FN1,
-               PS0_13_FN3, PS0_13_FN1,
-               PS0_12_FN3, PS0_12_FN1,
-               0, 0,
-               0, 0,
+               PS0_15_FN1, PS0_15_FN2,
+               PS0_14_FN1, PS0_14_FN2,
+               PS0_13_FN1, PS0_13_FN2,
+               PS0_12_FN1, PS0_12_FN2,
+               PS0_11_FN1, PS0_11_FN2,
+               PS0_10_FN1, PS0_10_FN2,
+               PS0_9_FN1, PS0_9_FN2,
+               PS0_8_FN1, PS0_8_FN2,
+               PS0_7_FN1, PS0_7_FN2,
+               PS0_6_FN1, PS0_6_FN2,
+               PS0_5_FN1, PS0_5_FN2,
+               PS0_4_FN1, PS0_4_FN2,
+               PS0_3_FN1, PS0_3_FN2,
+               PS0_2_FN1, PS0_2_FN2,
                0, 0,
-               0, 0,
-               PS0_7_FN2, PS0_7_FN1,
-               PS0_6_FN2, PS0_6_FN1,
-               PS0_5_FN2, PS0_5_FN1,
-               PS0_4_FN2, PS0_4_FN1,
-               PS0_3_FN2, PS0_3_FN1,
-               PS0_2_FN2, PS0_2_FN1,
-               PS0_1_FN2, PS0_1_FN1,
                0, 0, }
        },
        { PINMUX_CFG_REG("PSEL1", 0xffec0072, 16, 1) {
@@ -1795,73 +2009,136 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                0, 0,
                0, 0,
                0, 0,
+               PS1_10_FN1, PS1_10_FN2,
+               PS1_9_FN1, PS1_9_FN2,
+               PS1_8_FN1, PS1_8_FN2,
                0, 0,
                0, 0,
                0, 0,
-               PS1_7_FN1, PS1_7_FN3,
-               PS1_6_FN1, PS1_6_FN3,
-               0, 0,
-               0, 0,
                0, 0,
                0, 0,
+               PS1_2_FN1, PS1_2_FN2,
                0, 0,
                0, 0, }
        },
        { PINMUX_CFG_REG("PSEL2", 0xffec0074, 16, 1) {
                0, 0,
                0, 0,
-               PS2_13_FN3, PS2_13_FN1,
-               PS2_12_FN3, PS2_12_FN1,
+               PS2_13_FN1, PS2_13_FN2,
+               PS2_12_FN1, PS2_12_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
+               PS2_7_FN1, PS2_7_FN2,
+               PS2_6_FN1, PS2_6_FN2,
+               PS2_5_FN1, PS2_5_FN2,
+               PS2_4_FN1, PS2_4_FN2,
                0, 0,
+               PS2_2_FN1, PS2_2_FN2,
                0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL3", 0xffec0076, 16, 1) {
+               PS3_15_FN1, PS3_15_FN2,
+               PS3_14_FN1, PS3_14_FN2,
+               PS3_13_FN1, PS3_13_FN2,
+               PS3_12_FN1, PS3_12_FN2,
+               PS3_11_FN1, PS3_11_FN2,
+               PS3_10_FN1, PS3_10_FN2,
+               PS3_9_FN1, PS3_9_FN2,
+               PS3_8_FN1, PS3_8_FN2,
+               PS3_7_FN1, PS3_7_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
-               PS2_1_FN1, PS2_1_FN2,
-               PS2_0_FN1, PS2_0_FN2, }
+               PS3_2_FN1, PS3_2_FN2,
+               PS3_1_FN1, PS3_1_FN2,
+               0, 0, }
        },
+
        { PINMUX_CFG_REG("PSEL4", 0xffec0078, 16, 1) {
-               PS4_15_FN2, PS4_15_FN1,
-               PS4_14_FN2, PS4_14_FN1,
-               PS4_13_FN2, PS4_13_FN1,
-               PS4_12_FN2, PS4_12_FN1,
-               PS4_11_FN2, PS4_11_FN1,
-               PS4_10_FN2, PS4_10_FN1,
-               PS4_9_FN2, PS4_9_FN1,
                0, 0,
+               PS4_14_FN1, PS4_14_FN2,
+               PS4_13_FN1, PS4_13_FN2,
+               PS4_12_FN1, PS4_12_FN2,
                0, 0,
+               PS4_10_FN1, PS4_10_FN2,
+               PS4_9_FN1, PS4_9_FN2,
+               PS4_8_FN1, PS4_8_FN2,
                0, 0,
                0, 0,
                0, 0,
-               PS4_3_FN2, PS4_3_FN1,
-               PS4_2_FN2, PS4_2_FN1,
-               PS4_1_FN2, PS4_1_FN1,
-               PS4_0_FN2, PS4_0_FN1, }
+               PS4_4_FN1, PS4_4_FN2,
+               PS4_3_FN1, PS4_3_FN2,
+               PS4_2_FN1, PS4_2_FN2,
+               PS4_1_FN1, PS4_1_FN2,
+               PS4_0_FN1, PS4_0_FN2, }
        },
        { PINMUX_CFG_REG("PSEL5", 0xffec007a, 16, 1) {
                0, 0,
                0, 0,
                0, 0,
                0, 0,
-               0, 0,
-               0, 0,
+               PS5_11_FN1, PS5_11_FN2,
+               PS5_10_FN1, PS5_10_FN2,
                PS5_9_FN1, PS5_9_FN2,
                PS5_8_FN1, PS5_8_FN2,
                PS5_7_FN1, PS5_7_FN2,
                PS5_6_FN1, PS5_6_FN2,
                PS5_5_FN1, PS5_5_FN2,
+               PS5_4_FN1, PS5_4_FN2,
+               PS5_3_FN1, PS5_3_FN2,
+               PS5_2_FN1, PS5_2_FN2,
+               0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) {
+               PS6_15_FN1, PS6_15_FN2,
+               PS6_14_FN1, PS6_14_FN2,
+               PS6_13_FN1, PS6_13_FN2,
+               PS6_12_FN1, PS6_12_FN2,
+               PS6_11_FN1, PS6_11_FN2,
+               PS6_10_FN1, PS6_10_FN2,
+               PS6_9_FN1, PS6_9_FN2,
+               PS6_8_FN1, PS6_8_FN2,
+               PS6_7_FN1, PS6_7_FN2,
+               PS6_6_FN1, PS6_6_FN2,
+               PS6_5_FN1, PS6_5_FN2,
+               PS6_4_FN1, PS6_4_FN2,
+               PS6_3_FN1, PS6_3_FN2,
+               PS6_2_FN1, PS6_2_FN2,
+               PS6_1_FN1, PS6_1_FN2,
+               PS6_0_FN1, PS6_0_FN2, }
+       },
+       { PINMUX_CFG_REG("PSEL7", 0xffec0082, 16, 1) {
+               PS7_15_FN1, PS7_15_FN2,
+               PS7_14_FN1, PS7_14_FN2,
+               PS7_13_FN1, PS7_13_FN2,
+               PS7_12_FN1, PS7_12_FN2,
+               PS7_11_FN1, PS7_11_FN2,
+               PS7_10_FN1, PS7_10_FN2,
+               PS7_9_FN1, PS7_9_FN2,
+               PS7_8_FN1, PS7_8_FN2,
+               PS7_7_FN1, PS7_7_FN2,
+               PS7_6_FN1, PS7_6_FN2,
+               PS7_5_FN1, PS7_5_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0, }
        },
-       { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) {
+       { PINMUX_CFG_REG("PSEL8", 0xffec0084, 16, 1) {
+               PS8_15_FN1, PS8_15_FN2,
+               PS8_14_FN1, PS8_14_FN2,
+               PS8_13_FN1, PS8_13_FN2,
+               PS8_12_FN1, PS8_12_FN2,
+               PS8_11_FN1, PS8_11_FN2,
+               PS8_10_FN1, PS8_10_FN2,
+               PS8_9_FN1, PS8_9_FN2,
+               PS8_8_FN1, PS8_8_FN2,
                0, 0,
                0, 0,
                0, 0,
@@ -1869,15 +2146,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                0, 0,
                0, 0,
                0, 0,
-               0, 0,
-               PS6_7_FN_AN, PS6_7_FN_EV,
-               PS6_6_FN_AN, PS6_6_FN_EV,
-               PS6_5_FN_AN, PS6_5_FN_EV,
-               PS6_4_FN_AN, PS6_4_FN_EV,
-               PS6_3_FN_AN, PS6_3_FN_EV,
-               PS6_2_FN_AN, PS6_2_FN_EV,
-               PS6_1_FN_AN, PS6_1_FN_EV,
-               PS6_0_FN_AN, PS6_0_FN_EV, }
+               0, 0, }
        },
        {}
 };
@@ -1920,7 +2189,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA }
        },
        { PINMUX_DATA_REG("PJDR", 0xffec0046, 8) {
-               PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+               0, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
                PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
        },
        { PINMUX_DATA_REG("PKDR", 0xffec0048, 8) {
@@ -1928,15 +2197,15 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
        },
        { PINMUX_DATA_REG("PLDR", 0xffec004a, 8) {
-               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               0, PTL6_DATA, PTL5_DATA, PTL4_DATA,
                PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
        },
        { PINMUX_DATA_REG("PMDR", 0xffec004c, 8) {
-               0, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
                PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
        },
        { PINMUX_DATA_REG("PNDR", 0xffec004e, 8) {
-               PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+               0, PTN6_DATA, PTN5_DATA, PTN4_DATA,
                PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
        },
        { PINMUX_DATA_REG("PODR", 0xffec0050, 8) {
@@ -1944,7 +2213,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA }
        },
        { PINMUX_DATA_REG("PPDR", 0xffec0052, 8) {
-               0, PTP6_DATA, PTP5_DATA, PTP4_DATA,
+               PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA,
                PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA }
        },
        { PINMUX_DATA_REG("PQDR", 0xffec0054, 8) {
@@ -1960,7 +2229,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
        },
        { PINMUX_DATA_REG("PTDR", 0xffec005a, 8) {
-               0, 0, PTT5_DATA, PTT4_DATA,
+               PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
                PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
        },
        { PINMUX_DATA_REG("PUDR", 0xffec005c, 8) {
@@ -2000,8 +2269,8 @@ static struct pinmux_info sh7757_pinmux_info = {
        .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
        .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-       .first_gpio = GPIO_PTA7,
-       .last_gpio = GPIO_FN_D0,
+       .first_gpio = GPIO_PTA0,
+       .last_gpio = GPIO_FN_ON_DQ0,
 
        .gpios = pinmux_gpios,
        .cfg_regs = pinmux_config_regs,
@@ -2015,5 +2284,4 @@ static int __init plat_pinmux_setup(void)
 {
        return register_pinmux(&sh7757_pinmux_info);
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
new file mode 100644 (file)
index 0000000..aaa5338
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * SH-X3 prototype CPU pinmux
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/shx3.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+       PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+       PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+       PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
+       PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+       PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+       PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+       PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+       PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+       PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+       PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+       PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+       PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+       PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+
+       PH5_DATA, PH4_DATA,
+       PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PA7_IN, PA6_IN, PA5_IN, PA4_IN,
+       PA3_IN, PA2_IN, PA1_IN, PA0_IN,
+       PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+       PB3_IN, PB2_IN, PB1_IN, PB0_IN,
+       PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+       PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+       PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+       PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+       PE7_IN, PE6_IN, PE5_IN, PE4_IN,
+       PE3_IN, PE2_IN, PE1_IN, PE0_IN,
+       PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+       PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+       PG7_IN, PG6_IN, PG5_IN, PG4_IN,
+       PG3_IN, PG2_IN, PG1_IN, PG0_IN,
+
+       PH5_IN, PH4_IN,
+       PH3_IN, PH2_IN, PH1_IN, PH0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PA7_IN_PU, PA6_IN_PU, PA5_IN_PU, PA4_IN_PU,
+       PA3_IN_PU, PA2_IN_PU, PA1_IN_PU, PA0_IN_PU,
+       PB7_IN_PU, PB6_IN_PU, PB5_IN_PU, PB4_IN_PU,
+       PB3_IN_PU, PB2_IN_PU, PB1_IN_PU, PB0_IN_PU,
+       PC7_IN_PU, PC6_IN_PU, PC5_IN_PU, PC4_IN_PU,
+       PC3_IN_PU, PC2_IN_PU, PC1_IN_PU, PC0_IN_PU,
+       PD7_IN_PU, PD6_IN_PU, PD5_IN_PU, PD4_IN_PU,
+       PD3_IN_PU, PD2_IN_PU, PD1_IN_PU, PD0_IN_PU,
+       PE7_IN_PU, PE6_IN_PU, PE5_IN_PU, PE4_IN_PU,
+       PE3_IN_PU, PE2_IN_PU, PE1_IN_PU, PE0_IN_PU,
+       PF7_IN_PU, PF6_IN_PU, PF5_IN_PU, PF4_IN_PU,
+       PF3_IN_PU, PF2_IN_PU, PF1_IN_PU, PF0_IN_PU,
+       PG7_IN_PU, PG6_IN_PU, PG5_IN_PU, PG4_IN_PU,
+       PG3_IN_PU, PG2_IN_PU, PG1_IN_PU, PG0_IN_PU,
+
+       PH5_IN_PU, PH4_IN_PU,
+       PH3_IN_PU, PH2_IN_PU, PH1_IN_PU, PH0_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PA7_OUT, PA6_OUT, PA5_OUT, PA4_OUT,
+       PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
+       PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
+       PB3_OUT, PB2_OUT, PB1_OUT, PB0_OUT,
+       PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+       PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+       PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+       PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+       PE7_OUT, PE6_OUT, PE5_OUT, PE4_OUT,
+       PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
+       PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+       PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+       PG7_OUT, PG6_OUT, PG5_OUT, PG4_OUT,
+       PG3_OUT, PG2_OUT, PG1_OUT, PG0_OUT,
+
+       PH5_OUT, PH4_OUT,
+       PH3_OUT, PH2_OUT, PH1_OUT, PH0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PA7_FN, PA6_FN, PA5_FN, PA4_FN,
+       PA3_FN, PA2_FN, PA1_FN, PA0_FN,
+       PB7_FN, PB6_FN, PB5_FN, PB4_FN,
+       PB3_FN, PB2_FN, PB1_FN, PB0_FN,
+       PC7_FN, PC6_FN, PC5_FN, PC4_FN,
+       PC3_FN, PC2_FN, PC1_FN, PC0_FN,
+       PD7_FN, PD6_FN, PD5_FN, PD4_FN,
+       PD3_FN, PD2_FN, PD1_FN, PD0_FN,
+       PE7_FN, PE6_FN, PE5_FN, PE4_FN,
+       PE3_FN, PE2_FN, PE1_FN, PE0_FN,
+       PF7_FN, PF6_FN, PF5_FN, PF4_FN,
+       PF3_FN, PF2_FN, PF1_FN, PF0_FN,
+       PG7_FN, PG6_FN, PG5_FN, PG4_FN,
+       PG3_FN, PG2_FN, PG1_FN, PG0_FN,
+
+       PH5_FN, PH4_FN,
+       PH3_FN, PH2_FN, PH1_FN, PH0_FN,
+       PINMUX_FUNCTION_END,
+
+       PINMUX_MARK_BEGIN,
+
+       D31_MARK, D30_MARK, D29_MARK, D28_MARK, D27_MARK, D26_MARK,
+       D25_MARK, D24_MARK, D23_MARK, D22_MARK, D21_MARK, D20_MARK,
+       D19_MARK, D18_MARK, D17_MARK, D16_MARK,
+
+       BACK_MARK, BREQ_MARK,
+       WE3_MARK, WE2_MARK,
+       CS6_MARK, CS5_MARK, CS4_MARK,
+       CLKOUTENB_MARK,
+
+       DACK3_MARK, DACK2_MARK, DACK1_MARK, DACK0_MARK,
+       DREQ3_MARK, DREQ2_MARK, DREQ1_MARK, DREQ0_MARK,
+
+       IRQ3_MARK, IRQ2_MARK, IRQ1_MARK, IRQ0_MARK,
+
+       DRAK3_MARK, DRAK2_MARK, DRAK1_MARK, DRAK0_MARK,
+
+       SCK3_MARK, SCK2_MARK, SCK1_MARK, SCK0_MARK,
+       IRL3_MARK, IRL2_MARK, IRL1_MARK, IRL0_MARK,
+       TXD3_MARK, TXD2_MARK, TXD1_MARK, TXD0_MARK,
+       RXD3_MARK, RXD2_MARK, RXD1_MARK, RXD0_MARK,
+
+       CE2B_MARK, CE2A_MARK, IOIS16_MARK,
+       STATUS1_MARK, STATUS0_MARK,
+
+       IRQOUT_MARK,
+
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t shx3_pinmux_data[] = {
+
+       /* PA GPIO */
+       PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
+       PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT, PA6_IN_PU),
+       PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT, PA5_IN_PU),
+       PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT, PA4_IN_PU),
+       PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT, PA3_IN_PU),
+       PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT, PA2_IN_PU),
+       PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT, PA1_IN_PU),
+       PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT, PA0_IN_PU),
+
+       /* PB GPIO */
+       PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT, PB7_IN_PU),
+       PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT, PB6_IN_PU),
+       PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT, PB5_IN_PU),
+       PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT, PB4_IN_PU),
+       PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT, PB3_IN_PU),
+       PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT, PB2_IN_PU),
+       PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT, PB1_IN_PU),
+       PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT, PB0_IN_PU),
+
+       /* PC GPIO */
+       PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT, PC7_IN_PU),
+       PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT, PC6_IN_PU),
+       PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT, PC5_IN_PU),
+       PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT, PC4_IN_PU),
+       PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT, PC3_IN_PU),
+       PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT, PC2_IN_PU),
+       PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT, PC1_IN_PU),
+       PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT, PC0_IN_PU),
+
+       /* PD GPIO */
+       PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT, PD7_IN_PU),
+       PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT, PD6_IN_PU),
+       PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT, PD5_IN_PU),
+       PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT, PD4_IN_PU),
+       PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT, PD3_IN_PU),
+       PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT, PD2_IN_PU),
+       PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT, PD1_IN_PU),
+       PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT, PD0_IN_PU),
+
+       /* PE GPIO */
+       PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT, PE7_IN_PU),
+       PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT, PE6_IN_PU),
+       PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT, PE5_IN_PU),
+       PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT, PE4_IN_PU),
+       PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT, PE3_IN_PU),
+       PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT, PE2_IN_PU),
+       PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT, PE1_IN_PU),
+       PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT, PE0_IN_PU),
+
+       /* PF GPIO */
+       PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT, PF7_IN_PU),
+       PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT, PF6_IN_PU),
+       PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT, PF5_IN_PU),
+       PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT, PF4_IN_PU),
+       PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT, PF3_IN_PU),
+       PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT, PF2_IN_PU),
+       PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT, PF1_IN_PU),
+       PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT, PF0_IN_PU),
+
+       /* PG GPIO */
+       PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT, PG7_IN_PU),
+       PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT, PG6_IN_PU),
+       PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT, PG5_IN_PU),
+       PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT, PG4_IN_PU),
+       PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT, PG3_IN_PU),
+       PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT, PG2_IN_PU),
+       PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT, PG1_IN_PU),
+       PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT, PG0_IN_PU),
+
+       /* PH GPIO */
+       PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT, PH5_IN_PU),
+       PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT, PH4_IN_PU),
+       PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT, PH3_IN_PU),
+       PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT, PH2_IN_PU),
+       PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT, PH1_IN_PU),
+       PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT, PH0_IN_PU),
+
+       /* PA FN */
+       PINMUX_DATA(D31_MARK, PA7_FN),
+       PINMUX_DATA(D30_MARK, PA6_FN),
+       PINMUX_DATA(D29_MARK, PA5_FN),
+       PINMUX_DATA(D28_MARK, PA4_FN),
+       PINMUX_DATA(D27_MARK, PA3_FN),
+       PINMUX_DATA(D26_MARK, PA2_FN),
+       PINMUX_DATA(D25_MARK, PA1_FN),
+       PINMUX_DATA(D24_MARK, PA0_FN),
+
+       /* PB FN */
+       PINMUX_DATA(D23_MARK, PB7_FN),
+       PINMUX_DATA(D22_MARK, PB6_FN),
+       PINMUX_DATA(D21_MARK, PB5_FN),
+       PINMUX_DATA(D20_MARK, PB4_FN),
+       PINMUX_DATA(D19_MARK, PB3_FN),
+       PINMUX_DATA(D18_MARK, PB2_FN),
+       PINMUX_DATA(D17_MARK, PB1_FN),
+       PINMUX_DATA(D16_MARK, PB0_FN),
+
+       /* PC FN */
+       PINMUX_DATA(BACK_MARK,          PC7_FN),
+       PINMUX_DATA(BREQ_MARK,          PC6_FN),
+       PINMUX_DATA(WE3_MARK,           PC5_FN),
+       PINMUX_DATA(WE2_MARK,           PC4_FN),
+       PINMUX_DATA(CS6_MARK,           PC3_FN),
+       PINMUX_DATA(CS5_MARK,           PC2_FN),
+       PINMUX_DATA(CS4_MARK,           PC1_FN),
+       PINMUX_DATA(CLKOUTENB_MARK,     PC0_FN),
+
+       /* PD FN */
+       PINMUX_DATA(DACK3_MARK, PD7_FN),
+       PINMUX_DATA(DACK2_MARK, PD6_FN),
+       PINMUX_DATA(DACK1_MARK, PD5_FN),
+       PINMUX_DATA(DACK0_MARK, PD4_FN),
+       PINMUX_DATA(DREQ3_MARK, PD3_FN),
+       PINMUX_DATA(DREQ2_MARK, PD2_FN),
+       PINMUX_DATA(DREQ1_MARK, PD1_FN),
+       PINMUX_DATA(DREQ0_MARK, PD0_FN),
+
+       /* PE FN */
+       PINMUX_DATA(IRQ3_MARK,  PE7_FN),
+       PINMUX_DATA(IRQ2_MARK,  PE6_FN),
+       PINMUX_DATA(IRQ1_MARK,  PE5_FN),
+       PINMUX_DATA(IRQ0_MARK,  PE4_FN),
+       PINMUX_DATA(DRAK3_MARK, PE3_FN),
+       PINMUX_DATA(DRAK2_MARK, PE2_FN),
+       PINMUX_DATA(DRAK1_MARK, PE1_FN),
+       PINMUX_DATA(DRAK0_MARK, PE0_FN),
+
+       /* PF FN */
+       PINMUX_DATA(SCK3_MARK, PF7_FN),
+       PINMUX_DATA(SCK2_MARK, PF6_FN),
+       PINMUX_DATA(SCK1_MARK, PF5_FN),
+       PINMUX_DATA(SCK0_MARK, PF4_FN),
+       PINMUX_DATA(IRL3_MARK, PF3_FN),
+       PINMUX_DATA(IRL2_MARK, PF2_FN),
+       PINMUX_DATA(IRL1_MARK, PF1_FN),
+       PINMUX_DATA(IRL0_MARK, PF0_FN),
+
+       /* PG FN */
+       PINMUX_DATA(TXD3_MARK, PG7_FN),
+       PINMUX_DATA(TXD2_MARK, PG6_FN),
+       PINMUX_DATA(TXD1_MARK, PG5_FN),
+       PINMUX_DATA(TXD0_MARK, PG4_FN),
+       PINMUX_DATA(RXD3_MARK, PG3_FN),
+       PINMUX_DATA(RXD2_MARK, PG2_FN),
+       PINMUX_DATA(RXD1_MARK, PG1_FN),
+       PINMUX_DATA(RXD0_MARK, PG0_FN),
+
+       /* PH FN */
+       PINMUX_DATA(CE2B_MARK,          PH5_FN),
+       PINMUX_DATA(CE2A_MARK,          PH4_FN),
+       PINMUX_DATA(IOIS16_MARK,        PH3_FN),
+       PINMUX_DATA(STATUS1_MARK,       PH2_FN),
+       PINMUX_DATA(STATUS0_MARK,       PH1_FN),
+       PINMUX_DATA(IRQOUT_MARK,        PH0_FN),
+};
+
+static struct pinmux_gpio shx3_pinmux_gpios[] = {
+       /* PA */
+       PINMUX_GPIO(GPIO_PA7, PA7_DATA),
+       PINMUX_GPIO(GPIO_PA6, PA6_DATA),
+       PINMUX_GPIO(GPIO_PA5, PA5_DATA),
+       PINMUX_GPIO(GPIO_PA4, PA4_DATA),
+       PINMUX_GPIO(GPIO_PA3, PA3_DATA),
+       PINMUX_GPIO(GPIO_PA2, PA2_DATA),
+       PINMUX_GPIO(GPIO_PA1, PA1_DATA),
+       PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+
+       /* PB */
+       PINMUX_GPIO(GPIO_PB7, PB7_DATA),
+       PINMUX_GPIO(GPIO_PB6, PB6_DATA),
+       PINMUX_GPIO(GPIO_PB5, PB5_DATA),
+       PINMUX_GPIO(GPIO_PB4, PB4_DATA),
+       PINMUX_GPIO(GPIO_PB3, PB3_DATA),
+       PINMUX_GPIO(GPIO_PB2, PB2_DATA),
+       PINMUX_GPIO(GPIO_PB1, PB1_DATA),
+       PINMUX_GPIO(GPIO_PB0, PB0_DATA),
+
+       /* PC */
+       PINMUX_GPIO(GPIO_PC7, PC7_DATA),
+       PINMUX_GPIO(GPIO_PC6, PC6_DATA),
+       PINMUX_GPIO(GPIO_PC5, PC5_DATA),
+       PINMUX_GPIO(GPIO_PC4, PC4_DATA),
+       PINMUX_GPIO(GPIO_PC3, PC3_DATA),
+       PINMUX_GPIO(GPIO_PC2, PC2_DATA),
+       PINMUX_GPIO(GPIO_PC1, PC1_DATA),
+       PINMUX_GPIO(GPIO_PC0, PC0_DATA),
+
+       /* PD */
+       PINMUX_GPIO(GPIO_PD7, PD7_DATA),
+       PINMUX_GPIO(GPIO_PD6, PD6_DATA),
+       PINMUX_GPIO(GPIO_PD5, PD5_DATA),
+       PINMUX_GPIO(GPIO_PD4, PD4_DATA),
+       PINMUX_GPIO(GPIO_PD3, PD3_DATA),
+       PINMUX_GPIO(GPIO_PD2, PD2_DATA),
+       PINMUX_GPIO(GPIO_PD1, PD1_DATA),
+       PINMUX_GPIO(GPIO_PD0, PD0_DATA),
+
+       /* PE */
+       PINMUX_GPIO(GPIO_PE7, PE7_DATA),
+       PINMUX_GPIO(GPIO_PE6, PE6_DATA),
+       PINMUX_GPIO(GPIO_PE5, PE5_DATA),
+       PINMUX_GPIO(GPIO_PE4, PE4_DATA),
+       PINMUX_GPIO(GPIO_PE3, PE3_DATA),
+       PINMUX_GPIO(GPIO_PE2, PE2_DATA),
+       PINMUX_GPIO(GPIO_PE1, PE1_DATA),
+       PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+
+       /* PF */
+       PINMUX_GPIO(GPIO_PF7, PF7_DATA),
+       PINMUX_GPIO(GPIO_PF6, PF6_DATA),
+       PINMUX_GPIO(GPIO_PF5, PF5_DATA),
+       PINMUX_GPIO(GPIO_PF4, PF4_DATA),
+       PINMUX_GPIO(GPIO_PF3, PF3_DATA),
+       PINMUX_GPIO(GPIO_PF2, PF2_DATA),
+       PINMUX_GPIO(GPIO_PF1, PF1_DATA),
+       PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+
+       /* PG */
+       PINMUX_GPIO(GPIO_PG7, PG7_DATA),
+       PINMUX_GPIO(GPIO_PG6, PG6_DATA),
+       PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+       PINMUX_GPIO(GPIO_PG4, PG4_DATA),
+       PINMUX_GPIO(GPIO_PG3, PG3_DATA),
+       PINMUX_GPIO(GPIO_PG2, PG2_DATA),
+       PINMUX_GPIO(GPIO_PG1, PG1_DATA),
+       PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+
+       /* PH */
+       PINMUX_GPIO(GPIO_PH5, PH5_DATA),
+       PINMUX_GPIO(GPIO_PH4, PH4_DATA),
+       PINMUX_GPIO(GPIO_PH3, PH3_DATA),
+       PINMUX_GPIO(GPIO_PH2, PH2_DATA),
+       PINMUX_GPIO(GPIO_PH1, PH1_DATA),
+       PINMUX_GPIO(GPIO_PH0, PH0_DATA),
+
+       /* FN */
+       PINMUX_GPIO(GPIO_FN_D31,        D31_MARK),
+       PINMUX_GPIO(GPIO_FN_D30,        D30_MARK),
+       PINMUX_GPIO(GPIO_FN_D29,        D29_MARK),
+       PINMUX_GPIO(GPIO_FN_D28,        D28_MARK),
+       PINMUX_GPIO(GPIO_FN_D27,        D27_MARK),
+       PINMUX_GPIO(GPIO_FN_D26,        D26_MARK),
+       PINMUX_GPIO(GPIO_FN_D25,        D25_MARK),
+       PINMUX_GPIO(GPIO_FN_D24,        D24_MARK),
+       PINMUX_GPIO(GPIO_FN_D23,        D23_MARK),
+       PINMUX_GPIO(GPIO_FN_D22,        D22_MARK),
+       PINMUX_GPIO(GPIO_FN_D21,        D21_MARK),
+       PINMUX_GPIO(GPIO_FN_D20,        D20_MARK),
+       PINMUX_GPIO(GPIO_FN_D19,        D19_MARK),
+       PINMUX_GPIO(GPIO_FN_D18,        D18_MARK),
+       PINMUX_GPIO(GPIO_FN_D17,        D17_MARK),
+       PINMUX_GPIO(GPIO_FN_D16,        D16_MARK),
+       PINMUX_GPIO(GPIO_FN_BACK,       BACK_MARK),
+       PINMUX_GPIO(GPIO_FN_BREQ,       BREQ_MARK),
+       PINMUX_GPIO(GPIO_FN_WE3,        WE3_MARK),
+       PINMUX_GPIO(GPIO_FN_WE2,        WE2_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6,        CS6_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5,        CS5_MARK),
+       PINMUX_GPIO(GPIO_FN_CS4,        CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CLKOUTENB,  CLKOUTENB_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK3,      DACK3_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK2,      DACK2_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1,      DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0,      DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ3,      DREQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ2,      DREQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1,      DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0,      DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3,       IRQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2,       IRQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1,       IRQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0,       IRQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK3,      DRAK3_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK2,      DRAK2_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK1,      DRAK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK0,      DRAK0_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3,       SCK3_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK2,       SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK1,       SCK1_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK0,       SCK0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL3,       IRL3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL2,       IRL2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL1,       IRL1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL0,       IRL0_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD3,       TXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2,       TXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD1,       TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD0,       TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD3,       RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2,       RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD1,       RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD0,       RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2B,       CE2B_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2A,       CE2A_MARK),
+       PINMUX_GPIO(GPIO_FN_IOIS16,     IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1,    STATUS1_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS0,    STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQOUT,     IRQOUT_MARK),
+};
+
+static struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PABCR", 0xffc70000, 32, 2) {
+               PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
+               PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
+               PA5_FN, PA5_OUT, PA5_IN, PA5_IN_PU,
+               PA4_FN, PA4_OUT, PA4_IN, PA4_IN_PU,
+               PA3_FN, PA3_OUT, PA3_IN, PA3_IN_PU,
+               PA2_FN, PA2_OUT, PA2_IN, PA2_IN_PU,
+               PA1_FN, PA1_OUT, PA1_IN, PA1_IN_PU,
+               PA0_FN, PA0_OUT, PA0_IN, PA0_IN_PU,
+               PB7_FN, PB7_OUT, PB7_IN, PB7_IN_PU,
+               PB6_FN, PB6_OUT, PB6_IN, PB6_IN_PU,
+               PB5_FN, PB5_OUT, PB5_IN, PB5_IN_PU,
+               PB4_FN, PB4_OUT, PB4_IN, PB4_IN_PU,
+               PB3_FN, PB3_OUT, PB3_IN, PB3_IN_PU,
+               PB2_FN, PB2_OUT, PB2_IN, PB2_IN_PU,
+               PB1_FN, PB1_OUT, PB1_IN, PB1_IN_PU,
+               PB0_FN, PB0_OUT, PB0_IN, PB0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PCDCR", 0xffc70004, 32, 2) {
+               PC7_FN, PC7_OUT, PC7_IN, PC7_IN_PU,
+               PC6_FN, PC6_OUT, PC6_IN, PC6_IN_PU,
+               PC5_FN, PC5_OUT, PC5_IN, PC5_IN_PU,
+               PC4_FN, PC4_OUT, PC4_IN, PC4_IN_PU,
+               PC3_FN, PC3_OUT, PC3_IN, PC3_IN_PU,
+               PC2_FN, PC2_OUT, PC2_IN, PC2_IN_PU,
+               PC1_FN, PC1_OUT, PC1_IN, PC1_IN_PU,
+               PC0_FN, PC0_OUT, PC0_IN, PC0_IN_PU,
+               PD7_FN, PD7_OUT, PD7_IN, PD7_IN_PU,
+               PD6_FN, PD6_OUT, PD6_IN, PD6_IN_PU,
+               PD5_FN, PD5_OUT, PD5_IN, PD5_IN_PU,
+               PD4_FN, PD4_OUT, PD4_IN, PD4_IN_PU,
+               PD3_FN, PD3_OUT, PD3_IN, PD3_IN_PU,
+               PD2_FN, PD2_OUT, PD2_IN, PD2_IN_PU,
+               PD1_FN, PD1_OUT, PD1_IN, PD1_IN_PU,
+               PD0_FN, PD0_OUT, PD0_IN, PD0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PEFCR", 0xffc70008, 32, 2) {
+               PE7_FN, PE7_OUT, PE7_IN, PE7_IN_PU,
+               PE6_FN, PE6_OUT, PE6_IN, PE6_IN_PU,
+               PE5_FN, PE5_OUT, PE5_IN, PE5_IN_PU,
+               PE4_FN, PE4_OUT, PE4_IN, PE4_IN_PU,
+               PE3_FN, PE3_OUT, PE3_IN, PE3_IN_PU,
+               PE2_FN, PE2_OUT, PE2_IN, PE2_IN_PU,
+               PE1_FN, PE1_OUT, PE1_IN, PE1_IN_PU,
+               PE0_FN, PE0_OUT, PE0_IN, PE0_IN_PU,
+               PF7_FN, PF7_OUT, PF7_IN, PF7_IN_PU,
+               PF6_FN, PF6_OUT, PF6_IN, PF6_IN_PU,
+               PF5_FN, PF5_OUT, PF5_IN, PF5_IN_PU,
+               PF4_FN, PF4_OUT, PF4_IN, PF4_IN_PU,
+               PF3_FN, PF3_OUT, PF3_IN, PF3_IN_PU,
+               PF2_FN, PF2_OUT, PF2_IN, PF2_IN_PU,
+               PF1_FN, PF1_OUT, PF1_IN, PF1_IN_PU,
+               PF0_FN, PF0_OUT, PF0_IN, PF0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PGHCR", 0xffc7000c, 32, 2) {
+               PG7_FN, PG7_OUT, PG7_IN, PG7_IN_PU,
+               PG6_FN, PG6_OUT, PG6_IN, PG6_IN_PU,
+               PG5_FN, PG5_OUT, PG5_IN, PG5_IN_PU,
+               PG4_FN, PG4_OUT, PG4_IN, PG4_IN_PU,
+               PG3_FN, PG3_OUT, PG3_IN, PG3_IN_PU,
+               PG2_FN, PG2_OUT, PG2_IN, PG2_IN_PU,
+               PG1_FN, PG1_OUT, PG1_IN, PG1_IN_PU,
+               PG0_FN, PG0_OUT, PG0_IN, PG0_IN_PU,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PH5_FN, PH5_OUT, PH5_IN, PH5_IN_PU,
+               PH4_FN, PH4_OUT, PH4_IN, PH4_IN_PU,
+               PH3_FN, PH3_OUT, PH3_IN, PH3_IN_PU,
+               PH2_FN, PH2_OUT, PH2_IN, PH2_IN_PU,
+               PH1_FN, PH1_OUT, PH1_IN, PH1_IN_PU,
+               PH0_FN, PH0_OUT, PH0_IN, PH0_IN_PU, },
+       },
+       { },
+};
+
+static struct pinmux_data_reg shx3_pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PABDR", 0xffc70010, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+               PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+               PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA, },
+       },
+       { PINMUX_DATA_REG("PCDDR", 0xffc70014, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+               PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+               PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA, },
+       },
+       { PINMUX_DATA_REG("PEFDR", 0xffc70018, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+               PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+               PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA, },
+       },
+       { PINMUX_DATA_REG("PGHDR", 0xffc7001c, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+               PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, PH5_DATA, PH4_DATA,
+               PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA, },
+       },
+       { },
+};
+
+static struct pinmux_info shx3_pinmux_info = {
+       .name           = "shx3_pfc",
+       .reserved_id    = PINMUX_RESERVED,
+       .data           = { PINMUX_DATA_BEGIN,     PINMUX_DATA_END },
+       .input          = { PINMUX_INPUT_BEGIN,    PINMUX_INPUT_END },
+       .input_pu       = { PINMUX_INPUT_PULLUP_BEGIN,
+                           PINMUX_INPUT_PULLUP_END },
+       .output         = { PINMUX_OUTPUT_BEGIN,   PINMUX_OUTPUT_END },
+       .mark           = { PINMUX_MARK_BEGIN,     PINMUX_MARK_END },
+       .function       = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+       .first_gpio     = GPIO_PA7,
+       .last_gpio      = GPIO_FN_IRQOUT,
+       .gpios          = shx3_pinmux_gpios,
+       .gpio_data      = shx3_pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(shx3_pinmux_data),
+       .cfg_regs       = shx3_pinmux_config_regs,
+       .data_regs      = shx3_pinmux_data_regs,
+};
+
+static int __init shx3_pinmux_setup(void)
+{
+       return register_pinmux(&shx3_pinmux_info);
+}
+arch_initcall(shx3_pinmux_setup);
index 156ccc9..d551ed8 100644 (file)
@@ -551,7 +551,7 @@ static struct resource siu_resources[] = {
 };
 
 static struct platform_device siu_device = {
-       .name           = "sh_siu",
+       .name           = "siu-pcm-audio",
        .id             = -1,
        .dev = {
                .platform_data  = &siu_platform_data,
index 79c556e..828c965 100644 (file)
@@ -524,6 +524,70 @@ static struct platform_device veu1_device = {
        },
 };
 
+/* BEU0 */
+static struct uio_info beu0_platform_data = {
+       .name = "BEU0",
+       .version = "0",
+       .irq = evt2irq(0x8A0),
+};
+
+static struct resource beu0_resources[] = {
+       [0] = {
+               .name   = "BEU0",
+               .start  = 0xfe930000,
+               .end    = 0xfe933400,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device beu0_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 6,
+       .dev = {
+               .platform_data  = &beu0_platform_data,
+       },
+       .resource       = beu0_resources,
+       .num_resources  = ARRAY_SIZE(beu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_BEU0,
+       },
+};
+
+/* BEU1 */
+static struct uio_info beu1_platform_data = {
+       .name = "BEU1",
+       .version = "0",
+       .irq = evt2irq(0xA00),
+};
+
+static struct resource beu1_resources[] = {
+       [0] = {
+               .name   = "BEU1",
+               .start  = 0xfe940000,
+               .end    = 0xfe943400,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device beu1_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 7,
+       .dev = {
+               .platform_data  = &beu1_platform_data,
+       },
+       .resource       = beu1_resources,
+       .num_resources  = ARRAY_SIZE(beu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_BEU1,
+       },
+};
+
 static struct sh_timer_config cmt_platform_data = {
        .channel_offset = 0x60,
        .timer_bit = 5,
@@ -857,6 +921,8 @@ static struct platform_device *sh7724_devices[] __initdata = {
        &vpu_device,
        &veu0_device,
        &veu1_device,
+       &beu0_device,
+       &beu1_device,
        &jpu_device,
        &spu0_device,
        &spu1_device,
index 444aca9..749c638 100644 (file)
@@ -26,7 +26,7 @@ static struct plat_sci_port scif2_platform_data = {
 
 static struct platform_device scif2_device = {
        .name           = "sh-sci",
-       .id             = 2,
+       .id             = 0,
        .dev            = {
                .platform_data  = &scif2_platform_data,
        },
@@ -41,7 +41,7 @@ static struct plat_sci_port scif3_platform_data = {
 
 static struct platform_device scif3_device = {
        .name           = "sh-sci",
-       .id             = 3,
+       .id             = 1,
        .dev            = {
                .platform_data  = &scif3_platform_data,
        },
@@ -56,7 +56,7 @@ static struct plat_sci_port scif4_platform_data = {
 
 static struct platform_device scif4_device = {
        .name           = "sh-sci",
-       .id             = 4,
+       .id             = 2,
        .dev            = {
                .platform_data  = &scif4_platform_data,
        },
@@ -163,39 +163,23 @@ enum {
        IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
        IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 
-       SDHI,
-       DVC,
-       IRQ8, IRQ9, IRQ10,
-       WDT0,
-       TMU0, TMU1, TMU2, TMU2_TICPI,
+       SDHI, DVC,
+       IRQ8, IRQ9, IRQ11, IRQ10, IRQ12, IRQ13, IRQ14, IRQ15,
+       TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5,
        HUDI,
-
        ARC4,
-       DMAC0,
-       IRQ11,
-       SCIF2,
-       DMAC1_6,
-       USB0,
-       IRQ12,
+       DMAC0_5, DMAC6_7, DMAC8_11,
+       SCIF0, SCIF1, SCIF2, SCIF3, SCIF4,
+       USB0, USB1,
        JMC,
-       SPI1,
-       IRQ13, IRQ14,
-       USB1,
+       SPI0, SPI1,
        TMR01, TMR23, TMR45,
-       WDT1,
        FRT,
-       LPC,
-       SCIF0, SCIF1, SCIF3,
-       PECI0I, PECI1I, PECI2I,
-       IRQ15,
+       LPC, LPC5, LPC6, LPC7, LPC8,
+       PECI0, PECI1, PECI2, PECI3, PECI4, PECI5,
        ETHERC,
-       SPI0,
-       ADC1,
-       DMAC1_8,
+       ADC0, ADC1,
        SIM,
-       TMU3, TMU4, TMU5,
-       ADC0,
-       SCIF4,
        IIC0_0, IIC0_1, IIC0_2, IIC0_3,
        IIC1_0, IIC1_1, IIC1_2, IIC1_3,
        IIC2_0, IIC2_1, IIC2_2, IIC2_3,
@@ -206,9 +190,23 @@ enum {
        IIC7_0, IIC7_1, IIC7_2, IIC7_3,
        IIC8_0, IIC8_1, IIC8_2, IIC8_3,
        IIC9_0, IIC9_1, IIC9_2, IIC9_3,
-       PCIINTA,
-       PCIE,
+       ONFICTL,
+       MMC1, MMC2,
+       ECCU,
+       PCIC,
+       G200,
+       RSPI,
        SGPIO,
+       DMINT12, DMINT13, DMINT14, DMINT15, DMINT16, DMINT17, DMINT18, DMINT19,
+       DMINT20, DMINT21, DMINT22, DMINT23,
+       DDRECC,
+       TSIP,
+       PCIE_BRIDGE,
+       WDT0B, WDT1B, WDT2B, WDT3B, WDT4B, WDT5B, WDT6B, WDT7B, WDT8B,
+       GETHER0, GETHER1, GETHER2,
+       PBIA, PBIB, PBIC,
+       DMAE2, DMAE3,
+       SERMUX2, SERMUX3,
 
        /* interrupt groups */
 
@@ -221,19 +219,18 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(DVC, 0x4e0),
        INTC_VECT(IRQ8, 0x500), INTC_VECT(IRQ9, 0x520),
        INTC_VECT(IRQ10, 0x540),
-       INTC_VECT(WDT0, 0x560),
        INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
        INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
        INTC_VECT(HUDI, 0x600),
        INTC_VECT(ARC4, 0x620),
-       INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660),
-       INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0),
-       INTC_VECT(DMAC0, 0x6c0),
+       INTC_VECT(DMAC0_5, 0x640), INTC_VECT(DMAC0_5, 0x660),
+       INTC_VECT(DMAC0_5, 0x680), INTC_VECT(DMAC0_5, 0x6a0),
+       INTC_VECT(DMAC0_5, 0x6c0),
        INTC_VECT(IRQ11, 0x6e0),
        INTC_VECT(SCIF2, 0x700), INTC_VECT(SCIF2, 0x720),
        INTC_VECT(SCIF2, 0x740), INTC_VECT(SCIF2, 0x760),
-       INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0),
-       INTC_VECT(DMAC1_6, 0x7c0), INTC_VECT(DMAC1_6, 0x7e0),
+       INTC_VECT(DMAC0_5, 0x780), INTC_VECT(DMAC0_5, 0x7a0),
+       INTC_VECT(DMAC6_7, 0x7c0), INTC_VECT(DMAC6_7, 0x7e0),
        INTC_VECT(USB0, 0x840),
        INTC_VECT(IRQ12, 0x880),
        INTC_VECT(JMC, 0x8a0),
@@ -242,7 +239,6 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(USB1, 0x920),
        INTC_VECT(TMR01, 0xa00), INTC_VECT(TMR23, 0xa20),
        INTC_VECT(TMR45, 0xa40),
-       INTC_VECT(WDT1, 0xa60),
        INTC_VECT(FRT, 0xa80),
        INTC_VECT(LPC, 0xaa0), INTC_VECT(LPC, 0xac0),
        INTC_VECT(LPC, 0xae0), INTC_VECT(LPC, 0xb00),
@@ -250,14 +246,14 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(SCIF0, 0xb40), INTC_VECT(SCIF1, 0xb60),
        INTC_VECT(SCIF3, 0xb80), INTC_VECT(SCIF3, 0xba0),
        INTC_VECT(SCIF3, 0xbc0), INTC_VECT(SCIF3, 0xbe0),
-       INTC_VECT(PECI0I, 0xc00), INTC_VECT(PECI1I, 0xc20),
-       INTC_VECT(PECI2I, 0xc40),
+       INTC_VECT(PECI0, 0xc00), INTC_VECT(PECI1, 0xc20),
+       INTC_VECT(PECI2, 0xc40),
        INTC_VECT(IRQ15, 0xc60),
        INTC_VECT(ETHERC, 0xc80), INTC_VECT(ETHERC, 0xca0),
        INTC_VECT(SPI0, 0xcc0),
        INTC_VECT(ADC1, 0xce0),
-       INTC_VECT(DMAC1_8, 0xd00), INTC_VECT(DMAC1_8, 0xd20),
-       INTC_VECT(DMAC1_8, 0xd40), INTC_VECT(DMAC1_8, 0xd60),
+       INTC_VECT(DMAC8_11, 0xd00), INTC_VECT(DMAC8_11, 0xd20),
+       INTC_VECT(DMAC8_11, 0xd40), INTC_VECT(DMAC8_11, 0xd60),
        INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
        INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
        INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
@@ -278,17 +274,47 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(IIC5_0, 0x1860), INTC_VECT(IIC5_1, 0x1880),
        INTC_VECT(IIC5_2, 0x18a0), INTC_VECT(IIC5_3, 0x18c0),
        INTC_VECT(IIC6_0, 0x18e0), INTC_VECT(IIC6_1, 0x1900),
-       INTC_VECT(IIC6_2, 0x1920), INTC_VECT(IIC6_3, 0x1980),
+       INTC_VECT(IIC6_2, 0x1920),
+       INTC_VECT(ONFICTL, 0x1960),
+       INTC_VECT(IIC6_3, 0x1980),
        INTC_VECT(IIC7_0, 0x19a0), INTC_VECT(IIC7_1, 0x1a00),
        INTC_VECT(IIC7_2, 0x1a20), INTC_VECT(IIC7_3, 0x1a40),
        INTC_VECT(IIC8_0, 0x1a60), INTC_VECT(IIC8_1, 0x1a80),
        INTC_VECT(IIC8_2, 0x1aa0), INTC_VECT(IIC8_3, 0x1b40),
        INTC_VECT(IIC9_0, 0x1b60), INTC_VECT(IIC9_1, 0x1b80),
        INTC_VECT(IIC9_2, 0x1c00), INTC_VECT(IIC9_3, 0x1c20),
-       INTC_VECT(PCIINTA, 0x1ce0),
-       INTC_VECT(PCIE, 0x1e00),
-       INTC_VECT(SGPIO, 0x1f80),
-       INTC_VECT(SGPIO, 0x1fa0),
+       INTC_VECT(MMC1, 0x1c60), INTC_VECT(MMC2, 0x1c80),
+       INTC_VECT(ECCU, 0x1cc0),
+       INTC_VECT(PCIC, 0x1ce0),
+       INTC_VECT(G200, 0x1d00),
+       INTC_VECT(RSPI, 0x1d80), INTC_VECT(RSPI, 0x1da0),
+       INTC_VECT(RSPI, 0x1dc0), INTC_VECT(RSPI, 0x1de0),
+       INTC_VECT(PECI3, 0x1ec0), INTC_VECT(PECI4, 0x1ee0),
+       INTC_VECT(PECI5, 0x1f00),
+       INTC_VECT(SGPIO, 0x1f80), INTC_VECT(SGPIO, 0x1fa0),
+       INTC_VECT(SGPIO, 0x1fc0),
+       INTC_VECT(DMINT12, 0x2400), INTC_VECT(DMINT13, 0x2420),
+       INTC_VECT(DMINT14, 0x2440), INTC_VECT(DMINT15, 0x2460),
+       INTC_VECT(DMINT16, 0x2480), INTC_VECT(DMINT17, 0x24e0),
+       INTC_VECT(DMINT18, 0x2500), INTC_VECT(DMINT19, 0x2520),
+       INTC_VECT(DMINT20, 0x2540), INTC_VECT(DMINT21, 0x2560),
+       INTC_VECT(DMINT22, 0x2580), INTC_VECT(DMINT23, 0x2600),
+       INTC_VECT(DDRECC, 0x2620),
+       INTC_VECT(TSIP, 0x2640),
+       INTC_VECT(PCIE_BRIDGE, 0x27c0),
+       INTC_VECT(WDT0B, 0x2800), INTC_VECT(WDT1B, 0x2820),
+       INTC_VECT(WDT2B, 0x2840), INTC_VECT(WDT3B, 0x2860),
+       INTC_VECT(WDT4B, 0x2880), INTC_VECT(WDT5B, 0x28a0),
+       INTC_VECT(WDT6B, 0x28c0), INTC_VECT(WDT7B, 0x28e0),
+       INTC_VECT(WDT8B, 0x2900),
+       INTC_VECT(GETHER0, 0x2960), INTC_VECT(GETHER1, 0x2980),
+       INTC_VECT(GETHER2, 0x29a0),
+       INTC_VECT(PBIA, 0x2a00), INTC_VECT(PBIB, 0x2a20),
+       INTC_VECT(PBIC, 0x2a40),
+       INTC_VECT(DMAE2, 0x2a60), INTC_VECT(DMAE3, 0x2a80),
+       INTC_VECT(SERMUX2, 0x2aa0), INTC_VECT(SERMUX3, 0x2b40),
+       INTC_VECT(LPC5, 0x2b60), INTC_VECT(LPC6, 0x2b80),
+       INTC_VECT(LPC7, 0x2c00), INTC_VECT(LPC8, 0x2c20),
 };
 
 static struct intc_group groups[] __initdata = {
@@ -312,31 +338,45 @@ static struct intc_mask_reg mask_registers[] __initdata = {
 
        { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
          { 0, 0, 0, 0, 0, 0, 0, 0,
-           0, DMAC1_8, 0, PECI0I, LPC, FRT, WDT1, TMR45,
-           TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0,
-           HUDI, 0, WDT0, SCIF3, SCIF2, SDHI, TMU345, TMU012
+           0, DMAC8_11, 0, PECI0, LPC, FRT, 0, TMR45,
+           TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0_5,
+           HUDI, 0, 0, SCIF3, SCIF2, SDHI, TMU345, TMU012
             } },
 
        { 0xffd400d0, 0xffd400d4, 32, /* INT2MSKR1 / INT2MSKCR1 */
          { IRQ15, IRQ14, IRQ13, IRQ12, IRQ11, IRQ10, SCIF4, ETHERC,
            IRQ9, IRQ8, SCIF1, SCIF0, USB0, 0, 0, USB1,
-           ADC1, 0, DMAC1_6, ADC0, SPI0, SIM, PECI2I, PECI1I,
+           ADC1, 0, DMAC6_7, ADC0, SPI0, SIM, PECI2, PECI1,
            ARC4, 0, SPI1, JMC, 0, 0, 0, DVC
             } },
 
        { 0xffd10038, 0xffd1003c, 32, /* INT2MSKR2 / INT2MSKCR2 */
-         { IIC4_1, IIC4_2, IIC5_0, 0, 0, 0, SGPIO, 0,
-           0, 0, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
+         { IIC4_1, IIC4_2, IIC5_0, ONFICTL, 0, 0, SGPIO, 0,
+           0, G200, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
            IIC7_2, IIC7_1, IIC6_3, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC3_1,
-           IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, PCIE, IIC2_2
+           IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, 0, IIC2_2
             } },
 
-       { 0xffd100d0, 0xff1400d4, 32, /* INT2MSKR3 / INT2MSKCR4 */
-         { 0, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, 0, 0,
+       { 0xffd100d0, 0xffd100d4, 32, /* INT2MSKR3 / INT2MSKCR3 */
+         { MMC1, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, PECI5, MMC2,
            IIC1_3, IIC1_2, IIC9_0, IIC8_3, IIC4_3, IIC7_0, 0, IIC6_2,
-           PCIINTA, 0, IIC4_0, 0, 0, 0, 0, IIC9_3,
+           PCIC, 0, IIC4_0, 0, ECCU, RSPI, 0, IIC9_3,
            IIC3_0, 0, IIC5_3, IIC5_2, 0, 0, 0, IIC1_1
             } },
+
+       { 0xffd20038, 0xffd2003c, 32, /* INT2MSKR4 / INT2MSKCR4 */
+         { WDT0B, WDT1B, WDT3B, GETHER0, 0, 0, 0, 0,
+           0, 0, 0, LPC7, SERMUX2, DMAE3, DMAE2, PBIC,
+           PBIB, PBIA, GETHER1, DMINT12, DMINT13, DMINT14, DMINT15, TSIP,
+           DMINT23, 0, DMINT21, LPC6, 0, DMINT16, 0, DMINT22
+            } },
+
+       { 0xffd200d0, 0xffd200d4, 32, /* INT2MSKR5 / INT2MSKCR5 */
+         { 0, WDT8B, WDT7B, WDT4B, 0, DMINT20, 0, 0,
+           DMINT19, DMINT18, LPC5, SERMUX3, WDT2B, GETHER2, 0, 0,
+           0, 0, PCIE_BRIDGE, 0, 0, 0, 0, LPC8,
+           DDRECC, 0, WDT6B, WDT5B, 0, 0, 0, DMINT17
+            } },
 };
 
 #define INTPRI         0xffd00010
@@ -372,6 +412,22 @@ static struct intc_mask_reg mask_registers[] __initdata = {
 #define INT2PRI29      0xffd100b4
 #define INT2PRI30      0xffd100b8
 #define INT2PRI31      0xffd100bc
+#define INT2PRI32      0xffd20000
+#define INT2PRI33      0xffd20004
+#define INT2PRI34      0xffd20008
+#define INT2PRI35      0xffd2000c
+#define INT2PRI36      0xffd20010
+#define INT2PRI37      0xffd20014
+#define INT2PRI38      0xffd20018
+#define INT2PRI39      0xffd2001c
+#define INT2PRI40      0xffd200a0
+#define INT2PRI41      0xffd200a4
+#define INT2PRI42      0xffd200a8
+#define INT2PRI43      0xffd200ac
+#define INT2PRI44      0xffd200b0
+#define INT2PRI45      0xffd200b4
+#define INT2PRI46      0xffd200b8
+#define INT2PRI47      0xffd200bc
 
 static struct intc_prio_reg prio_registers[] __initdata = {
        { INTPRI, 0, 32, 4, { IRQ0, IRQ1, IRQ2, IRQ3,
@@ -379,39 +435,61 @@ static struct intc_prio_reg prio_registers[] __initdata = {
 
        { INT2PRI0, 0, 32, 8, { TMU0, TMU1, TMU2, TMU2_TICPI } },
        { INT2PRI1, 0, 32, 8, { TMU3, TMU4, TMU5, SDHI } },
-       { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, WDT0, IRQ8 } },
-       { INT2PRI3, 0, 32, 8, { HUDI, DMAC0, ADC0, IRQ9 } },
+       { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, 0, IRQ8 } },
+       { INT2PRI3, 0, 32, 8, { HUDI, DMAC0_5, ADC0, IRQ9 } },
        { INT2PRI4, 0, 32, 8, { IRQ10, 0, TMR01, TMR23 } },
-       { INT2PRI5, 0, 32, 8, { TMR45, WDT1, FRT, LPC } },
-       { INT2PRI6, 0, 32, 8, { PECI0I, ETHERC, DMAC1_8, 0 } },
+       { INT2PRI5, 0, 32, 8, { TMR45, 0, FRT, LPC } },
+       { INT2PRI6, 0, 32, 8, { PECI0, ETHERC, DMAC8_11, 0 } },
        { INT2PRI7, 0, 32, 8, { SCIF4, 0, IRQ11, IRQ12 } },
        { INT2PRI8, 0, 32, 8, { 0, 0, 0, DVC } },
        { INT2PRI9, 0, 32, 8, { ARC4, 0, SPI1, JMC } },
-       { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2I, PECI1I } },
-       { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC1_6, IRQ14 } },
+       { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2, PECI1 } },
+       { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC6_7, IRQ14 } },
        { INT2PRI12, 0, 32, 8, { USB0, 0, IRQ15, USB1 } },
        { INT2PRI13, 0, 32, 8, { 0, 0, SCIF1, SCIF0 } },
 
        { INT2PRI16, 0, 32, 8, { IIC2_2, 0, 0, 0 } },
-       { INT2PRI17, 0, 32, 8, { PCIE, 0, 0, IIC1_0 } },
+       { INT2PRI17, 0, 32, 8, { 0, 0, 0, IIC1_0 } },
        { INT2PRI18, 0, 32, 8, { IIC3_3, IIC9_1, IIC2_1, IIC1_2 } },
        { INT2PRI19, 0, 32, 8, { IIC2_3, IIC3_1, 0, IIC1_3 } },
        { INT2PRI20, 0, 32, 8, { IIC2_0, IIC6_3, IIC7_1, IIC7_2 } },
        { INT2PRI21, 0, 32, 8, { IIC7_3, IIC8_0, IIC8_1, IIC8_2 } },
-       { INT2PRI22, 0, 32, 8, { IIC9_2, 0, 0, 0 } },
-       { INT2PRI23, 0, 32, 8, { 0, SGPIO, IIC3_2, IIC5_1 } },
-       { INT2PRI24, 0, 32, 8, { 0, 0, 0, IIC1_1 } },
+       { INT2PRI22, 0, 32, 8, { IIC9_2, MMC2, G200, 0 } },
+       { INT2PRI23, 0, 32, 8, { PECI5, SGPIO, IIC3_2, IIC5_1 } },
+       { INT2PRI24, 0, 32, 8, { PECI4, PECI3, 0, IIC1_1 } },
        { INT2PRI25, 0, 32, 8, { IIC3_0, 0, IIC5_3, IIC5_2 } },
-       { INT2PRI26, 0, 32, 8, { 0, 0, 0, IIC9_3 } },
-       { INT2PRI27, 0, 32, 8, { PCIINTA, IIC6_0, IIC4_0, IIC6_1 } },
-       { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, 0, IIC6_2 } },
+       { INT2PRI26, 0, 32, 8, { ECCU, RSPI, 0, IIC9_3 } },
+       { INT2PRI27, 0, 32, 8, { PCIC, IIC6_0, IIC4_0, IIC6_1 } },
+       { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, MMC1, IIC6_2 } },
        { INT2PRI29, 0, 32, 8, { 0, 0, IIC9_0, IIC8_3 } },
-       { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, 0 } },
+       { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, ONFICTL } },
        { INT2PRI31, 0, 32, 8, { IIC0_0, IIC0_1, IIC0_2, IIC0_3 } },
+       { INT2PRI32, 0, 32, 8, { DMINT22, 0, 0, 0 } },
+       { INT2PRI33, 0, 32, 8, { 0, 0, 0, DMINT16 } },
+       { INT2PRI34, 0, 32, 8, { 0, LPC6, DMINT21, DMINT18 } },
+       { INT2PRI35, 0, 32, 8, { DMINT23, TSIP, 0, DMINT19 } },
+       { INT2PRI36, 0, 32, 8, { DMINT20, GETHER1, PBIA, PBIB } },
+       { INT2PRI37, 0, 32, 8, { PBIC, DMAE2, DMAE3, SERMUX2 } },
+       { INT2PRI38, 0, 32, 8, { LPC7, 0, 0, 0 } },
+       { INT2PRI39, 0, 32, 8, { 0, 0, 0, WDT4B } },
+       { INT2PRI40, 0, 32, 8, { 0, 0, 0, DMINT17 } },
+       { INT2PRI41, 0, 32, 8, { DDRECC, 0, WDT6B, WDT5B } },
+       { INT2PRI42, 0, 32, 8, { 0, 0, 0, LPC8 } },
+       { INT2PRI43, 0, 32, 8, { 0, WDT7B, PCIE_BRIDGE, WDT8B } },
+       { INT2PRI44, 0, 32, 8, { WDT2B, GETHER2, 0, 0 } },
+       { INT2PRI45, 0, 32, 8, { 0, 0, LPC5, SERMUX3 } },
+       { INT2PRI46, 0, 32, 8, { WDT0B, WDT1B, WDT3B, GETHER0 } },
+       { INT2PRI47, 0, 32, 8, { DMINT12, DMINT13, DMINT14, DMINT15 } },
+};
+
+static struct intc_sense_reg sense_registers_irq8to15[] __initdata = {
+       { 0xffd100f8, 32, 2, /* ICR2 */   { IRQ15, IRQ14, IRQ13, IRQ12,
+                                           IRQ11, IRQ10, IRQ9, IRQ8 } },
 };
 
 static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups,
-                        mask_registers, prio_registers, NULL);
+                        mask_registers, prio_registers,
+                        sense_registers_irq8to15);
 
 /* Support for external interrupt pins in IRQ mode */
 static struct intc_vect vectors_irq0123[] __initdata = {
index 8797723..c016c00 100644 (file)
@@ -629,33 +629,10 @@ static void __init sh7786_usb_setup(void)
        }
 }
 
-static int __init sh7786_devices_setup(void)
-{
-       int ret;
-
-       sh7786_usb_setup();
-
-       ret = platform_add_devices(sh7786_early_devices,
-                                  ARRAY_SIZE(sh7786_early_devices));
-       if (unlikely(ret != 0))
-               return ret;
-
-       return platform_add_devices(sh7786_devices,
-                                   ARRAY_SIZE(sh7786_devices));
-}
-arch_initcall(sh7786_devices_setup);
-
-void __init plat_early_device_setup(void)
-{
-       early_platform_add_devices(sh7786_early_devices,
-                                  ARRAY_SIZE(sh7786_early_devices));
-}
-
 enum {
        UNUSED = 0,
 
        /* interrupt sources */
-
        IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
        IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
        IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
@@ -693,9 +670,12 @@ enum {
        Thermal,
        INTICI0, INTICI1, INTICI2, INTICI3,
        INTICI4, INTICI5, INTICI6, INTICI7,
+
+       /* Muxed sub-events */
+       TXI1, BRI1, RXI1, ERI1,
 };
 
-static struct intc_vect vectors[] __initdata = {
+static struct intc_vect sh7786_vectors[] __initdata = {
        INTC_VECT(WDT, 0x3e0),
        INTC_VECT(TMU0_0, 0x400), INTC_VECT(TMU0_1, 0x420),
        INTC_VECT(TMU0_2, 0x440), INTC_VECT(TMU0_3, 0x460),
@@ -756,14 +736,12 @@ static struct intc_vect vectors[] __initdata = {
 
 #define INTDISTCR0     0xfe4100b0
 #define INTDISTCR1     0xfe4100b4
-#define INTACK         0xfe4100b8
-#define INTACKCLR      0xfe4100bc
 #define INT2DISTCR0    0xfe410900
 #define INT2DISTCR1    0xfe410904
 #define INT2DISTCR2    0xfe410908
 #define INT2DISTCR3    0xfe41090c
 
-static struct intc_mask_reg mask_registers[] __initdata = {
+static struct intc_mask_reg sh7786_mask_registers[] __initdata = {
        { CnINTMSK0, CnINTMSKCLR0, 32,
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 },
            INTC_SMP_BALANCING(INTDISTCR0) },
@@ -807,7 +785,7 @@ static struct intc_mask_reg mask_registers[] __initdata = {
            0, 0, 0, 0, 0, 0, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR3) },
 };
 
-static struct intc_prio_reg prio_registers[] __initdata = {
+static struct intc_prio_reg sh7786_prio_registers[] __initdata = {
        { 0xfe410010, 0, 32, 4, /* INTPRI */   { IRQ0, IRQ1, IRQ2, IRQ3,
                                                 IRQ4, IRQ5, IRQ6, IRQ7 } },
        { 0xfe410800, 0, 32, 8, /* INT2PRI0 */ { 0, 0, 0, WDT } },
@@ -851,11 +829,27 @@ static struct intc_prio_reg prio_registers[] __initdata = {
            INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 2) },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7786", vectors, NULL,
-                        mask_registers, prio_registers, NULL);
+static struct intc_subgroup sh7786_subgroups[] __initdata = {
+       { 0xfe410c20, 32, SCIF1,
+         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TXI1, BRI1, RXI1, ERI1 } },
+};
 
-/* Support for external interrupt pins in IRQ mode */
+static struct intc_desc sh7786_intc_desc __initdata = {
+       .name           = "sh7786",
+       .hw             = {
+               .vectors        = sh7786_vectors,
+               .nr_vectors     = ARRAY_SIZE(sh7786_vectors),
+               .mask_regs      = sh7786_mask_registers,
+               .nr_mask_regs   = ARRAY_SIZE(sh7786_mask_registers),
+               .subgroups      = sh7786_subgroups,
+               .nr_subgroups   = ARRAY_SIZE(sh7786_subgroups),
+               .prio_regs      = sh7786_prio_registers,
+               .nr_prio_regs   = ARRAY_SIZE(sh7786_prio_registers),
+       },
+};
 
+/* Support for external interrupt pins in IRQ mode */
 static struct intc_vect vectors_irq0123[] __initdata = {
        INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
        INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
@@ -866,23 +860,25 @@ static struct intc_vect vectors_irq4567[] __initdata = {
        INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
 };
 
-static struct intc_sense_reg sense_registers[] __initdata = {
+static struct intc_sense_reg sh7786_sense_registers[] __initdata = {
        { 0xfe41001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
                                            IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static struct intc_mask_reg ack_registers[] __initdata = {
+static struct intc_mask_reg sh7786_ack_registers[] __initdata = {
        { 0xfe410024, 0, 32, /* INTREQ */
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
 static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7786-irq0123",
-                            vectors_irq0123, NULL, mask_registers,
-                            prio_registers, sense_registers, ack_registers);
+                            vectors_irq0123, NULL, sh7786_mask_registers,
+                            sh7786_prio_registers, sh7786_sense_registers,
+                            sh7786_ack_registers);
 
 static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7786-irq4567",
-                            vectors_irq4567, NULL, mask_registers,
-                            prio_registers, sense_registers, ack_registers);
+                            vectors_irq4567, NULL, sh7786_mask_registers,
+                            sh7786_prio_registers, sh7786_sense_registers,
+                            sh7786_ack_registers);
 
 /* External interrupt pins in IRL mode */
 
@@ -909,10 +905,10 @@ static struct intc_vect vectors_irl4567[] __initdata = {
 };
 
 static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7786-irl0123", vectors_irl0123,
-                        NULL, mask_registers, NULL, NULL);
+                        NULL, sh7786_mask_registers, NULL, NULL);
 
 static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
-                        NULL, mask_registers, NULL, NULL);
+                        NULL, sh7786_mask_registers, NULL, NULL);
 
 #define INTC_ICR0      0xfe410000
 #define INTC_INTMSK0   CnINTMSK0
@@ -920,19 +916,6 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
 #define INTC_INTMSK2   INTMSK2
 #define INTC_INTMSKCLR1        CnINTMSKCLR1
 #define INTC_INTMSKCLR2        INTMSKCLR2
-#define INTC_USERIMASK 0xfe411000
-
-#ifdef CONFIG_INTC_BALANCING
-unsigned int irq_lookup(unsigned int irq)
-{
-       return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE;
-}
-
-void irq_finish(unsigned int irq)
-{
-       __raw_writel(irq2evt(irq), INTACKCLR);
-}
-#endif
 
 void __init plat_irq_setup(void)
 {
@@ -946,8 +929,7 @@ void __init plat_irq_setup(void)
        /* select IRL mode for IRL3-0 + IRL7-4 */
        __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
-       register_intc_controller(&intc_desc);
-       register_intc_userimask(INTC_USERIMASK);
+       register_intc_controller(&sh7786_intc_desc);
 }
 
 void __init plat_irq_setup_pins(int mode)
@@ -991,3 +973,39 @@ void __init plat_irq_setup_pins(int mode)
 void __init plat_mem_setup(void)
 {
 }
+
+static int __init sh7786_devices_setup(void)
+{
+       int ret, irq;
+
+       sh7786_usb_setup();
+
+       /*
+        * De-mux SCIF1 IRQs if possible
+        */
+       irq = intc_irq_lookup(sh7786_intc_desc.name, TXI1);
+       if (irq > 0) {
+               scif1_platform_data.irqs[SCIx_TXI_IRQ] = irq;
+               scif1_platform_data.irqs[SCIx_ERI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, ERI1);
+               scif1_platform_data.irqs[SCIx_BRI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, BRI1);
+               scif1_platform_data.irqs[SCIx_RXI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, RXI1);
+       }
+
+       ret = platform_add_devices(sh7786_early_devices,
+                                  ARRAY_SIZE(sh7786_early_devices));
+       if (unlikely(ret != 0))
+               return ret;
+
+       return platform_add_devices(sh7786_devices,
+                                   ARRAY_SIZE(sh7786_devices));
+}
+arch_initcall(sh7786_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+       early_platform_add_devices(sh7786_early_devices,
+                                  ARRAY_SIZE(sh7786_early_devices));
+}
index 9158bc5..013f0b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH-X3 Prototype Setup
  *
- *  Copyright (C) 2007 - 2009  Paul Mundt
+ *  Copyright (C) 2007 - 2010  Paul Mundt
  *
  * 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
@@ -12,7 +12,9 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 #include <linux/sh_timer.h>
+#include <cpu/shx3.h>
 #include <asm/mmzone.h>
 
 /*
@@ -354,6 +356,10 @@ static struct intc_group groups[] __initdata = {
                   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
 };
 
+#define INT2DISTCR0    0xfe4108a0
+#define INT2DISTCR1    0xfe4108a4
+#define INT2DISTCR2    0xfe4108a8
+
 static struct intc_mask_reg mask_registers[] __initdata = {
        { 0xfe410030, 0xfe410050, 32, /* CnINTMSK0 / CnINTMSKCLR0 */
          { IRQ0, IRQ1, IRQ2, IRQ3 } },
@@ -363,20 +369,23 @@ static struct intc_mask_reg mask_registers[] __initdata = {
          { FE1, FE0, 0, ATAPI, VCORE0, VIN1, VIN0, IIC,
            DU, GPIO3, GPIO2, GPIO1, GPIO0, PAM, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, /* HUDI bits ignored */
-           0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, } },
+           0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, },
+           INTC_SMP_BALANCING(INT2DISTCR0) },
        { 0xfe410830, 0xfe410860, 32, /* CnINT2MSK1 / CnINT2MSKCLR1 */
          { 0, 0, 0, 0, DTU3, DTU2, DTU1, DTU0, /* IRM bits ignored */
            PCII9, PCII8, PCII7, PCII6, PCII5, PCII4, PCII3, PCII2,
            PCII1, PCII0, DMAC1_DMAE, DMAC1_DMINT11,
            DMAC1_DMINT10, DMAC1_DMINT9, DMAC1_DMINT8, DMAC1_DMINT7,
            DMAC1_DMINT6, DMAC0_DMAE, DMAC0_DMINT5, DMAC0_DMINT4,
-           DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 } },
+           DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 },
+           INTC_SMP_BALANCING(INT2DISTCR1) },
        { 0xfe410840, 0xfe410870, 32, /* CnINT2MSK2 / CnINT2MSKCLR2 */
          { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            SCIF3_TXI, SCIF3_BRI, SCIF3_RXI, SCIF3_ERI,
            SCIF2_TXI, SCIF2_BRI, SCIF2_RXI, SCIF2_ERI,
            SCIF1_TXI, SCIF1_BRI, SCIF1_RXI, SCIF1_ERI,
-           SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI } },
+           SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI },
+           INTC_SMP_BALANCING(INT2DISTCR2) },
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -433,11 +442,33 @@ static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups,
 
 void __init plat_irq_setup_pins(int mode)
 {
+       int ret = 0;
+
        switch (mode) {
        case IRQ_MODE_IRQ:
+               ret |= gpio_request(GPIO_FN_IRQ3, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ2, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ1, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ0, intc_desc_irq.name);
+
+               if (unlikely(ret)) {
+                       pr_err("Failed to set IRQ mode\n");
+                       return;
+               }
+
                register_intc_controller(&intc_desc_irq);
                break;
        case IRQ_MODE_IRL3210:
+               ret |= gpio_request(GPIO_FN_IRL3, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL2, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL1, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL0, intc_desc_irl.name);
+
+               if (unlikely(ret)) {
+                       pr_err("Failed to set IRL mode\n");
+                       return;
+               }
+
                register_intc_controller(&intc_desc_irl);
                break;
        default:
@@ -447,6 +478,9 @@ void __init plat_irq_setup_pins(int mode)
 
 void __init plat_irq_setup(void)
 {
+       reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq));
+       reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl));
+
        register_intc_controller(&intc_desc);
 }
 
index 6e35f01..7db2489 100644 (file)
@@ -330,7 +330,7 @@ ENTRY(_stext)
 #if defined(CONFIG_CPU_SH2)
 1:     .long   0x000000F0              ! IMASK=0xF
 #else
-1:     .long   0x400080F0              ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
+1:     .long   0x500080F0              ! MD=1, RB=0, BL=1, FD=1, IMASK=0xF
 #endif
 ENTRY(stack_start)
 2:     .long   init_thread_union+THREAD_SIZE
index 2947d2b..32c385e 100644 (file)
@@ -291,7 +291,7 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address)
        }
 
        tmp = handle_unaligned_access(instruction, regs,
-                                     &trapped_io_access, 1);
+                                     &trapped_io_access, 1, address);
        set_fs(oldfs);
        return tmp == 0;
 }
index ae5bac3..9dc447d 100644 (file)
@@ -283,6 +283,8 @@ void __init init_IRQ(void)
        if (sh_mv.mv_init_irq)
                sh_mv.mv_init_irq();
 
+       intc_finalize();
+
        irq_ctx_init(smp_processor_id());
 }
 
diff --git a/arch/sh/kernel/kdebugfs.c b/arch/sh/kernel/kdebugfs.c
new file mode 100644 (file)
index 0000000..e11c30b
--- /dev/null
@@ -0,0 +1,16 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+
+struct dentry *arch_debugfs_dir;
+EXPORT_SYMBOL(arch_debugfs_dir);
+
+static int __init arch_kdebugfs_init(void)
+{
+       arch_debugfs_dir = debugfs_create_dir("sh", NULL);
+       if (!arch_debugfs_dir)
+               return -ENOMEM;
+
+       return 0;
+}
+arch_initcall(arch_kdebugfs_init);
index 4049d99..1208b09 100644 (file)
@@ -20,9 +20,9 @@
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
-static struct kprobe saved_current_opcode;
-static struct kprobe saved_next_opcode;
-static struct kprobe saved_next_opcode2;
+static DEFINE_PER_CPU(struct kprobe, saved_current_opcode);
+static DEFINE_PER_CPU(struct kprobe, saved_next_opcode);
+static DEFINE_PER_CPU(struct kprobe, saved_next_opcode2);
 
 #define OPCODE_JMP(x)  (((x) & 0xF0FF) == 0x402b)
 #define OPCODE_JSR(x)  (((x) & 0xF0FF) == 0x400b)
@@ -102,16 +102,21 @@ int __kprobes kprobe_handle_illslot(unsigned long pc)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       if (saved_next_opcode.addr != 0x0) {
+       struct kprobe *saved = &__get_cpu_var(saved_next_opcode);
+
+       if (saved->addr) {
                arch_disarm_kprobe(p);
-               arch_disarm_kprobe(&saved_next_opcode);
-               saved_next_opcode.addr = 0x0;
-               saved_next_opcode.opcode = 0x0;
-
-               if (saved_next_opcode2.addr != 0x0) {
-                       arch_disarm_kprobe(&saved_next_opcode2);
-                       saved_next_opcode2.addr = 0x0;
-                       saved_next_opcode2.opcode = 0x0;
+               arch_disarm_kprobe(saved);
+
+               saved->addr = NULL;
+               saved->opcode = 0;
+
+               saved = &__get_cpu_var(saved_next_opcode2);
+               if (saved->addr) {
+                       arch_disarm_kprobe(saved);
+
+                       saved->addr = NULL;
+                       saved->opcode = 0;
                }
        }
 }
@@ -141,57 +146,59 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
  */
 static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
-       kprobe_opcode_t *addr = NULL;
-       saved_current_opcode.addr = (kprobe_opcode_t *) (regs->pc);
-       addr = saved_current_opcode.addr;
+       __get_cpu_var(saved_current_opcode).addr = (kprobe_opcode_t *)regs->pc;
 
        if (p != NULL) {
+               struct kprobe *op1, *op2;
+
                arch_disarm_kprobe(p);
 
+               op1 = &__get_cpu_var(saved_next_opcode);
+               op2 = &__get_cpu_var(saved_next_opcode2);
+
                if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) {
                        unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
-                       saved_next_opcode.addr =
-                           (kprobe_opcode_t *) regs->regs[reg_nr];
+                       op1->addr = (kprobe_opcode_t *) regs->regs[reg_nr];
                } else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
                        unsigned long disp = (p->opcode & 0x0FFF);
-                       saved_next_opcode.addr =
+                       op1->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
 
                } else if (OPCODE_BRAF(p->opcode) || OPCODE_BSRF(p->opcode)) {
                        unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
-                       saved_next_opcode.addr =
+                       op1->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 +
                                                 regs->regs[reg_nr]);
 
                } else if (OPCODE_RTS(p->opcode)) {
-                       saved_next_opcode.addr = (kprobe_opcode_t *) regs->pr;
+                       op1->addr = (kprobe_opcode_t *) regs->pr;
 
                } else if (OPCODE_BF(p->opcode) || OPCODE_BT(p->opcode)) {
                        unsigned long disp = (p->opcode & 0x00FF);
                        /* case 1 */
-                       saved_next_opcode.addr = p->addr + 1;
+                       op1->addr = p->addr + 1;
                        /* case 2 */
-                       saved_next_opcode2.addr =
+                       op2->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
-                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
-                       arch_arm_kprobe(&saved_next_opcode2);
+                       op2->opcode = *(op2->addr);
+                       arch_arm_kprobe(op2);
 
                } else if (OPCODE_BF_S(p->opcode) || OPCODE_BT_S(p->opcode)) {
                        unsigned long disp = (p->opcode & 0x00FF);
                        /* case 1 */
-                       saved_next_opcode.addr = p->addr + 2;
+                       op1->addr = p->addr + 2;
                        /* case 2 */
-                       saved_next_opcode2.addr =
+                       op2->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
-                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
-                       arch_arm_kprobe(&saved_next_opcode2);
+                       op2->opcode = *(op2->addr);
+                       arch_arm_kprobe(op2);
 
                } else {
-                       saved_next_opcode.addr = p->addr + 1;
+                       op1->addr = p->addr + 1;
                }
 
-               saved_next_opcode.opcode = *(saved_next_opcode.addr);
-               arch_arm_kprobe(&saved_next_opcode);
+               op1->opcode = *(op1->addr);
+               arch_arm_kprobe(op1);
        }
 }
 
@@ -376,21 +383,23 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
                cur->post_handler(cur, regs, 0);
        }
 
-       if (saved_next_opcode.addr != 0x0) {
-               arch_disarm_kprobe(&saved_next_opcode);
-               saved_next_opcode.addr = 0x0;
-               saved_next_opcode.opcode = 0x0;
+       p = &__get_cpu_var(saved_next_opcode);
+       if (p->addr) {
+               arch_disarm_kprobe(p);
+               p->addr = NULL;
+               p->opcode = 0;
 
-               addr = saved_current_opcode.addr;
-               saved_current_opcode.addr = 0x0;
+               addr = __get_cpu_var(saved_current_opcode).addr;
+               __get_cpu_var(saved_current_opcode).addr = NULL;
 
                p = get_kprobe(addr);
                arch_arm_kprobe(p);
 
-               if (saved_next_opcode2.addr != 0x0) {
-                       arch_disarm_kprobe(&saved_next_opcode2);
-                       saved_next_opcode2.addr = 0x0;
-                       saved_next_opcode2.opcode = 0x0;
+               p = &__get_cpu_var(saved_next_opcode2);
+               if (p->addr) {
+                       arch_disarm_kprobe(p);
+                       p->addr = NULL;
+                       p->opcode = 0;
                }
        }
 
@@ -572,14 +581,5 @@ static struct kprobe trampoline_p = {
 
 int __init arch_init_kprobes(void)
 {
-       saved_next_opcode.addr = 0x0;
-       saved_next_opcode.opcode = 0x0;
-
-       saved_current_opcode.addr = 0x0;
-       saved_current_opcode.opcode = 0x0;
-
-       saved_next_opcode2.addr = 0x0;
-       saved_next_opcode2.opcode = 0x0;
-
        return register_kprobe(&trampoline_p);
 }
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..0a05983
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/ptrace.h>
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name:      the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+       const struct pt_regs_offset *roff;
+       for (roff = regoffset_table; roff->name != NULL; roff++)
+               if (!strcmp(roff->name, name))
+                       return roff->offset;
+       return -EINVAL;
+}
+
+/**
+ * regs_query_register_name() - query register name from its offset
+ * @offset:    the offset of a register in struct pt_regs.
+ *
+ * regs_query_register_name() returns the name of a register from its
+ * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
+ */
+const char *regs_query_register_name(unsigned int offset)
+{
+       const struct pt_regs_offset *roff;
+       for (roff = regoffset_table; roff->name != NULL; roff++)
+               if (roff->offset == offset)
+                       return roff->name;
+       return NULL;
+}
index 6c4bbba..2cd42b5 100644 (file)
@@ -274,6 +274,33 @@ static int dspregs_active(struct task_struct *target,
 }
 #endif
 
+const struct pt_regs_offset regoffset_table[] = {
+       REGS_OFFSET_NAME(0),
+       REGS_OFFSET_NAME(1),
+       REGS_OFFSET_NAME(2),
+       REGS_OFFSET_NAME(3),
+       REGS_OFFSET_NAME(4),
+       REGS_OFFSET_NAME(5),
+       REGS_OFFSET_NAME(6),
+       REGS_OFFSET_NAME(7),
+       REGS_OFFSET_NAME(8),
+       REGS_OFFSET_NAME(9),
+       REGS_OFFSET_NAME(10),
+       REGS_OFFSET_NAME(11),
+       REGS_OFFSET_NAME(12),
+       REGS_OFFSET_NAME(13),
+       REGS_OFFSET_NAME(14),
+       REGS_OFFSET_NAME(15),
+       REG_OFFSET_NAME(pc),
+       REG_OFFSET_NAME(pr),
+       REG_OFFSET_NAME(sr),
+       REG_OFFSET_NAME(gbr),
+       REG_OFFSET_NAME(mach),
+       REG_OFFSET_NAME(macl),
+       REG_OFFSET_NAME(tra),
+       REG_OFFSET_END,
+};
+
 /*
  * These are our native regset flavours.
  */
index 5fd644d..e0fb065 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -252,6 +252,85 @@ static int fpregs_active(struct task_struct *target,
 }
 #endif
 
+const struct pt_regs_offset regoffset_table[] = {
+       REG_OFFSET_NAME(pc),
+       REG_OFFSET_NAME(sr),
+       REG_OFFSET_NAME(syscall_nr),
+       REGS_OFFSET_NAME(0),
+       REGS_OFFSET_NAME(1),
+       REGS_OFFSET_NAME(2),
+       REGS_OFFSET_NAME(3),
+       REGS_OFFSET_NAME(4),
+       REGS_OFFSET_NAME(5),
+       REGS_OFFSET_NAME(6),
+       REGS_OFFSET_NAME(7),
+       REGS_OFFSET_NAME(8),
+       REGS_OFFSET_NAME(9),
+       REGS_OFFSET_NAME(10),
+       REGS_OFFSET_NAME(11),
+       REGS_OFFSET_NAME(12),
+       REGS_OFFSET_NAME(13),
+       REGS_OFFSET_NAME(14),
+       REGS_OFFSET_NAME(15),
+       REGS_OFFSET_NAME(16),
+       REGS_OFFSET_NAME(17),
+       REGS_OFFSET_NAME(18),
+       REGS_OFFSET_NAME(19),
+       REGS_OFFSET_NAME(20),
+       REGS_OFFSET_NAME(21),
+       REGS_OFFSET_NAME(22),
+       REGS_OFFSET_NAME(23),
+       REGS_OFFSET_NAME(24),
+       REGS_OFFSET_NAME(25),
+       REGS_OFFSET_NAME(26),
+       REGS_OFFSET_NAME(27),
+       REGS_OFFSET_NAME(28),
+       REGS_OFFSET_NAME(29),
+       REGS_OFFSET_NAME(30),
+       REGS_OFFSET_NAME(31),
+       REGS_OFFSET_NAME(32),
+       REGS_OFFSET_NAME(33),
+       REGS_OFFSET_NAME(34),
+       REGS_OFFSET_NAME(35),
+       REGS_OFFSET_NAME(36),
+       REGS_OFFSET_NAME(37),
+       REGS_OFFSET_NAME(38),
+       REGS_OFFSET_NAME(39),
+       REGS_OFFSET_NAME(40),
+       REGS_OFFSET_NAME(41),
+       REGS_OFFSET_NAME(42),
+       REGS_OFFSET_NAME(43),
+       REGS_OFFSET_NAME(44),
+       REGS_OFFSET_NAME(45),
+       REGS_OFFSET_NAME(46),
+       REGS_OFFSET_NAME(47),
+       REGS_OFFSET_NAME(48),
+       REGS_OFFSET_NAME(49),
+       REGS_OFFSET_NAME(50),
+       REGS_OFFSET_NAME(51),
+       REGS_OFFSET_NAME(52),
+       REGS_OFFSET_NAME(53),
+       REGS_OFFSET_NAME(54),
+       REGS_OFFSET_NAME(55),
+       REGS_OFFSET_NAME(56),
+       REGS_OFFSET_NAME(57),
+       REGS_OFFSET_NAME(58),
+       REGS_OFFSET_NAME(59),
+       REGS_OFFSET_NAME(60),
+       REGS_OFFSET_NAME(61),
+       REGS_OFFSET_NAME(62),
+       REGS_OFFSET_NAME(63),
+       TREGS_OFFSET_NAME(0),
+       TREGS_OFFSET_NAME(1),
+       TREGS_OFFSET_NAME(2),
+       TREGS_OFFSET_NAME(3),
+       TREGS_OFFSET_NAME(4),
+       TREGS_OFFSET_NAME(5),
+       TREGS_OFFSET_NAME(6),
+       TREGS_OFFSET_NAME(7),
+       REG_OFFSET_END,
+};
+
 /*
  * These are our native regset flavours.
  */
@@ -395,10 +474,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
 {
 #define WPC_DBRMODE 0x0d104008
-       static int first_call = 1;
+       static unsigned long first_call;
 
-       lock_kernel();
-       if (first_call) {
+       if (!test_and_set_bit(0, &first_call)) {
                /* Set WPC.DBRMODE to 0.  This makes all debug events get
                 * delivered through RESVEC, i.e. into the handlers in entry.S.
                 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
@@ -408,9 +486,7 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
                 * the remote gdb.) */
                printk("DBRMODE set to 0 to permit native debugging\n");
                poke_real_address_q(WPC_DBRMODE, 0);
-               first_call = 0;
        }
-       unlock_kernel();
 
        return sys_ptrace(request, pid, addr, data);
 }
index b1fca66..ca6a5ca 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/addrspace.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -25,6 +26,9 @@ static void native_machine_restart(char * __unused)
 {
        local_irq_disable();
 
+       /* Destroy all of the TLBs in preparation for reset by MMU */
+       __flush_tlb_global();
+
        /* Address error with SR.BL=1 first. */
        trigger_address_error();
 
index e769401..4e27846 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/err.h>
-#include <linux/debugfs.h>
 #include <linux/crash_dump.h>
 #include <linux/mmzone.h>
 #include <linux/clk.h>
@@ -136,8 +135,9 @@ void __init check_for_initrd(void)
                goto disable;
        }
 
-       if (unlikely(start < PAGE_OFFSET)) {
-               pr_err("initrd start < PAGE_OFFSET\n");
+       if (unlikely(start < __MEMORY_START)) {
+               pr_err("initrd start (%08lx) < __MEMORY_START(%x)\n",
+                       start, __MEMORY_START);
                goto disable;
        }
 
@@ -158,7 +158,7 @@ void __init check_for_initrd(void)
        /*
         * Address sanitization
         */
-       initrd_start = (unsigned long)__va(__pa(start));
+       initrd_start = (unsigned long)__va(start);
        initrd_end = initrd_start + INITRD_SIZE;
 
        memblock_reserve(__pa(initrd_start), INITRD_SIZE);
@@ -458,17 +458,3 @@ const struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo,
 };
 #endif /* CONFIG_PROC_FS */
-
-struct dentry *sh_debugfs_root;
-
-static int __init sh_debugfs_init(void)
-{
-       sh_debugfs_root = debugfs_create_dir("sh", NULL);
-       if (!sh_debugfs_root)
-               return -ENOMEM;
-       if (IS_ERR(sh_debugfs_root))
-               return PTR_ERR(sh_debugfs_root);
-
-       return 0;
-}
-arch_initcall(sh_debugfs_init);
index 19fd11d..e872e81 100644 (file)
@@ -353,3 +353,25 @@ ENTRY(sys_call_table)
        .long sys_pwritev
        .long sys_rt_tgsigqueueinfo     /* 335 */
        .long sys_perf_event_open
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
+       /* Broken-out socket family */
+       .long sys_socket                /* 340 */
+       .long sys_bind
+       .long sys_connect
+       .long sys_listen
+       .long sys_accept
+       .long sys_getsockname   /* 345 */
+       .long sys_getpeername
+       .long sys_socketpair
+       .long sys_send
+       .long sys_sendto
+       .long sys_recv                  /* 350 */
+       .long sys_recvfrom
+       .long sys_shutdown
+       .long sys_setsockopt
+       .long sys_getsockopt
+       .long sys_sendmsg               /* 355 */
+       .long sys_recvmsg
+       .long sys_recvmmsg
index 2048a20..6658570 100644 (file)
@@ -393,3 +393,6 @@ sys_call_table:
        .long sys_perf_event_open
        .long sys_recvmmsg              /* 365 */
        .long sys_accept4
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
index c3d86fa..3484c2f 100644 (file)
@@ -5,7 +5,7 @@
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
- *                  Copyright (C) 2002 - 2007 Paul Mundt
+ *                  Copyright (C) 2002 - 2010 Paul Mundt
  *
  * 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
@@ -26,6 +26,7 @@
 #include <linux/limits.h>
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
+#include <linux/perf_event.h>
 #include <asm/system.h>
 #include <asm/alignment.h>
 #include <asm/fpu.h>
@@ -369,7 +370,8 @@ static inline int handle_delayslot(struct pt_regs *regs,
 #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
 
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int expected)
+                           struct mem_access *ma, int expected,
+                           unsigned long address)
 {
        u_int rm;
        int ret, index;
@@ -383,9 +385,18 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
        index = (instruction>>8)&15;    /* 0x0F00 */
        rm = regs->regs[index];
 
-       /* shout about fixups */
-       if (!expected)
+       /*
+        * Log the unexpected fixups, and then pass them on to perf.
+        *
+        * We intentionally don't report the expected cases to perf as
+        * otherwise the trapped I/O case will skew the results too much
+        * to be useful.
+        */
+       if (!expected) {
                unaligned_fixups_notify(current, instruction, regs);
+               perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0,
+                             regs, address);
+       }
 
        ret = -EFAULT;
        switch (instruction&0xF000) {
@@ -574,7 +585,8 @@ fixup:
 
                set_fs(USER_DS);
                tmp = handle_unaligned_access(instruction, regs,
-                                             &user_mem_access, 0);
+                                             &user_mem_access, 0,
+                                             address);
                set_fs(oldfs);
 
                if (tmp == 0)
@@ -607,8 +619,8 @@ uspace_segv:
 
                unaligned_fixups_notify(current, instruction, regs);
 
-               handle_unaligned_access(instruction, regs,
-                                       &user_mem_access, 0);
+               handle_unaligned_access(instruction, regs, &user_mem_access,
+                                       0, address);
                set_fs(oldfs);
        }
 }
@@ -802,6 +814,9 @@ void __cpuinit per_cpu_trap_init(void)
                     : /* no output */
                     : "r" (&vbr_base)
                     : "memory");
+
+       /* disable exception blocking now when the vbr has been setup */
+       clear_bl_bit();
 }
 
 void *set_exception_table_vec(unsigned int vec, void *handler)
index e67e140..6713ca9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/module.h>
+#include <linux/perf_event.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -50,7 +51,7 @@ asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
        do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \
 }
 
-spinlock_t die_lock;
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -433,6 +434,8 @@ static int misaligned_load(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -509,6 +512,8 @@ static int misaligned_store(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -583,6 +588,8 @@ static int misaligned_fpu_load(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -658,6 +665,8 @@ static int misaligned_fpu_store(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
index dab4d21..7b95f29 100644 (file)
@@ -30,4 +30,4 @@ lib-$(CONFIG_MMU)             += copy_page.o __clear_user.o
 lib-$(CONFIG_MCOUNT)           += mcount.o
 lib-y                          += $(memcpy-y) $(memset-y) $(udivsi3-y)
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index 1fcdb12..f76a509 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+#include <linux/perf_event.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -619,6 +620,8 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
        struct task_struct *tsk = current;
        struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+
        if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
                /* initialize once. */
                fpu_init(fpu);
index 1445ca6..0937039 100644 (file)
@@ -168,6 +168,10 @@ config IOREMAP_FIXED
 config UNCACHED_MAPPING
        bool
 
+config HAVE_SRAM_POOL
+       bool
+       select GENERIC_ALLOCATOR
+
 choice
        prompt "Kernel page size"
        default PAGE_SIZE_4KB
index 53f7c68..ab89ea4 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_PMB)             += pmb.o
 obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_IOREMAP_FIXED)    += ioremap_fixed.o
 obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o
+obj-$(CONFIG_HAVE_SRAM_POOL)   += sram.o
 
 # Special flags for fault_64.o.  This puts restrictions on the number of
 # caller-save registers that the compiler can target when building this file.
@@ -66,4 +67,4 @@ CFLAGS_fault_64.o += -ffixed-r7 \
        -ffixed-r60 -ffixed-r61 -ffixed-r62 \
        -fomit-frame-pointer
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index cd8c3bf..74c03ec 100644 (file)
@@ -63,7 +63,7 @@ static int __init asids_debugfs_init(void)
 {
        struct dentry *asids_dentry;
 
-       asids_dentry = debugfs_create_file("asids", S_IRUSR, sh_debugfs_root,
+       asids_dentry = debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir,
                                           NULL, &asids_debugfs_fops);
        if (!asids_dentry)
                return -ENOMEM;
index 690ed01..5241146 100644 (file)
@@ -126,25 +126,19 @@ static int __init cache_debugfs_init(void)
 {
        struct dentry *dcache_dentry, *icache_dentry;
 
-       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
+       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
                                            (unsigned int *)CACHE_TYPE_DCACHE,
                                            &cache_debugfs_fops);
        if (!dcache_dentry)
                return -ENOMEM;
-       if (IS_ERR(dcache_dentry))
-               return PTR_ERR(dcache_dentry);
 
-       icache_dentry = debugfs_create_file("icache", S_IRUSR, sh_debugfs_root,
+       icache_dentry = debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir,
                                            (unsigned int *)CACHE_TYPE_ICACHE,
                                            &cache_debugfs_fops);
        if (!icache_dentry) {
                debugfs_remove(dcache_dentry);
                return -ENOMEM;
        }
-       if (IS_ERR(icache_dentry)) {
-               debugfs_remove(dcache_dentry);
-               return PTR_ERR(icache_dentry);
-       }
 
        return 0;
 }
index c86a085..0387932 100644 (file)
@@ -38,11 +38,12 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
        void *ret, *ret_nocache;
        int order = get_order(size);
 
+       gfp |= __GFP_ZERO;
+
        ret = (void *)__get_free_pages(gfp, order);
        if (!ret)
                return NULL;
 
-       memset(ret, 0, size);
        /*
         * Pages from the page allocator may have data present in
         * cache. So flush the cache before using uncached memory.
index 552bea5..3385b28 100644 (file)
@@ -47,7 +47,6 @@ static pte_t *__get_pte_phys(unsigned long addr)
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
 
        pgd = pgd_offset_k(addr);
        if (pgd_none(*pgd)) {
@@ -67,8 +66,7 @@ static pte_t *__get_pte_phys(unsigned long addr)
                return NULL;
        }
 
-       pte = pte_offset_kernel(pmd, addr);
-       return pte;
+       return pte_offset_kernel(pmd, addr);
 }
 
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
@@ -125,13 +123,45 @@ void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
        clear_pte_phys(address, prot);
 }
 
+static pmd_t * __init one_md_table_init(pud_t *pud)
+{
+       if (pud_none(*pud)) {
+               pmd_t *pmd;
+
+               pmd = alloc_bootmem_pages(PAGE_SIZE);
+               pud_populate(&init_mm, pud, pmd);
+               BUG_ON(pmd != pmd_offset(pud, 0));
+       }
+
+       return pmd_offset(pud, 0);
+}
+
+static pte_t * __init one_page_table_init(pmd_t *pmd)
+{
+       if (pmd_none(*pmd)) {
+               pte_t *pte;
+
+               pte = alloc_bootmem_pages(PAGE_SIZE);
+               pmd_populate_kernel(&init_mm, pmd, pte);
+               BUG_ON(pte != pte_offset_kernel(pmd, 0));
+       }
+
+       return pte_offset_kernel(pmd, 0);
+}
+
+static pte_t * __init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
+                                           unsigned long vaddr, pte_t *lastpte)
+{
+       return pte;
+}
+
 void __init page_table_range_init(unsigned long start, unsigned long end,
                                         pgd_t *pgd_base)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
+       pte_t *pte = NULL;
        int i, j, k;
        unsigned long vaddr;
 
@@ -144,19 +174,13 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
        for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
                pud = (pud_t *)pgd;
                for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
-#ifdef __PAGETABLE_PMD_FOLDED
-                       pmd = (pmd_t *)pud;
-#else
-                       pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
-                       pud_populate(&init_mm, pud, pmd);
+                       pmd = one_md_table_init(pud);
+#ifndef __PAGETABLE_PMD_FOLDED
                        pmd += k;
 #endif
                        for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
-                               if (pmd_none(*pmd)) {
-                                       pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-                                       pmd_populate_kernel(&init_mm, pmd, pte);
-                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
-                               }
+                               pte = page_table_kmap_check(one_page_table_init(pmd),
+                                                           pmd, vaddr, pte);
                                vaddr += PMD_SIZE;
                        }
                        k = 0;
index 7694f50..36312d2 100644 (file)
@@ -67,6 +67,10 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        BUG();
 }
 
+void __flush_tlb_global(void)
+{
+}
+
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 }
index 6379091..b20b1b3 100644 (file)
@@ -40,7 +40,7 @@ struct pmb_entry {
        unsigned long flags;
        unsigned long size;
 
-       spinlock_t lock;
+       raw_spinlock_t lock;
 
        /*
         * 0 .. NR_PMB_ENTRIES for specific entry selection, or
@@ -265,7 +265,7 @@ static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
 
        memset(pmbe, 0, sizeof(struct pmb_entry));
 
-       spin_lock_init(&pmbe->lock);
+       raw_spin_lock_init(&pmbe->lock);
 
        pmbe->vpn       = vpn;
        pmbe->ppn       = ppn;
@@ -327,9 +327,9 @@ static void set_pmb_entry(struct pmb_entry *pmbe)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&pmbe->lock, flags);
+       raw_spin_lock_irqsave(&pmbe->lock, flags);
        __set_pmb_entry(pmbe);
-       spin_unlock_irqrestore(&pmbe->lock, flags);
+       raw_spin_unlock_irqrestore(&pmbe->lock, flags);
 }
 #endif /* CONFIG_PM */
 
@@ -368,7 +368,7 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                                return PTR_ERR(pmbe);
                        }
 
-                       spin_lock_irqsave(&pmbe->lock, flags);
+                       raw_spin_lock_irqsave(&pmbe->lock, flags);
 
                        pmbe->size = pmb_sizes[i].size;
 
@@ -383,9 +383,10 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                         * entries for easier tear-down.
                         */
                        if (likely(pmbp)) {
-                               spin_lock(&pmbp->lock);
+                               raw_spin_lock_nested(&pmbp->lock,
+                                                    SINGLE_DEPTH_NESTING);
                                pmbp->link = pmbe;
-                               spin_unlock(&pmbp->lock);
+                               raw_spin_unlock(&pmbp->lock);
                        }
 
                        pmbp = pmbe;
@@ -398,7 +399,7 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                        i--;
                        mapped++;
 
-                       spin_unlock_irqrestore(&pmbe->lock, flags);
+                       raw_spin_unlock_irqrestore(&pmbe->lock, flags);
                }
        } while (size >= SZ_16M);
 
@@ -627,15 +628,14 @@ static void __init pmb_synchronize(void)
                        continue;
                }
 
-               spin_lock_irqsave(&pmbe->lock, irqflags);
+               raw_spin_lock_irqsave(&pmbe->lock, irqflags);
 
                for (j = 0; j < ARRAY_SIZE(pmb_sizes); j++)
                        if (pmb_sizes[j].flag == size)
                                pmbe->size = pmb_sizes[j].size;
 
                if (pmbp) {
-                       spin_lock(&pmbp->lock);
-
+                       raw_spin_lock_nested(&pmbp->lock, SINGLE_DEPTH_NESTING);
                        /*
                         * Compare the previous entry against the current one to
                         * see if the entries span a contiguous mapping. If so,
@@ -644,13 +644,12 @@ static void __init pmb_synchronize(void)
                         */
                        if (pmb_can_merge(pmbp, pmbe))
                                pmbp->link = pmbe;
-
-                       spin_unlock(&pmbp->lock);
+                       raw_spin_unlock(&pmbp->lock);
                }
 
                pmbp = pmbe;
 
-               spin_unlock_irqrestore(&pmbe->lock, irqflags);
+               raw_spin_unlock_irqrestore(&pmbe->lock, irqflags);
        }
 }
 
@@ -757,7 +756,7 @@ static void __init pmb_resize(void)
                /*
                 * Found it, now resize it.
                 */
-               spin_lock_irqsave(&pmbe->lock, flags);
+               raw_spin_lock_irqsave(&pmbe->lock, flags);
 
                pmbe->size = SZ_16M;
                pmbe->flags &= ~PMB_SZ_MASK;
@@ -767,7 +766,7 @@ static void __init pmb_resize(void)
 
                __set_pmb_entry(pmbe);
 
-               spin_unlock_irqrestore(&pmbe->lock, flags);
+               raw_spin_unlock_irqrestore(&pmbe->lock, flags);
        }
 
        read_unlock(&pmb_rwlock);
@@ -866,11 +865,9 @@ static int __init pmb_debugfs_init(void)
        struct dentry *dentry;
 
        dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
-                                    sh_debugfs_root, NULL, &pmb_debugfs_fops);
+                                    arch_debugfs_dir, NULL, &pmb_debugfs_fops);
        if (!dentry)
                return -ENOMEM;
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
 
        return 0;
 }
diff --git a/arch/sh/mm/sram.c b/arch/sh/mm/sram.c
new file mode 100644 (file)
index 0000000..bc156ec
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SRAM pool for tiny memories not otherwise managed.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/sram.h>
+
+/*
+ * This provides a standard SRAM pool for tiny memories that can be
+ * added either by the CPU or the platform code. Typical SRAM sizes
+ * to be inserted in to the pool will generally be less than the page
+ * size, with anything more reasonably sized handled as a NUMA memory
+ * node.
+ */
+struct gen_pool *sram_pool;
+
+static int __init sram_pool_init(void)
+{
+       /*
+        * This is a global pool, we don't care about node locality.
+        */
+       sram_pool = gen_pool_create(1, -1);
+       if (unlikely(!sram_pool))
+               return -ENOMEM;
+
+       return 0;
+}
+core_initcall(sram_pool_init);
index 229bf75..dea637a 100644 (file)
@@ -151,15 +151,13 @@ static int __init tlb_debugfs_init(void)
 {
        struct dentry *itlb, *utlb;
 
-       itlb = debugfs_create_file("itlb", S_IRUSR, sh_debugfs_root,
+       itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
                                   (unsigned int *)TLB_TYPE_ITLB,
                                   &tlb_debugfs_fops);
        if (unlikely(!itlb))
                return -ENOMEM;
-       if (IS_ERR(itlb))
-               return PTR_ERR(itlb);
 
-       utlb = debugfs_create_file("utlb", S_IRUSR, sh_debugfs_root,
+       utlb = debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
                                   (unsigned int *)TLB_TYPE_UTLB,
                                   &tlb_debugfs_fops);
        if (unlikely(!utlb)) {
@@ -167,11 +165,6 @@ static int __init tlb_debugfs_init(void)
                return -ENOMEM;
        }
 
-       if (IS_ERR(utlb)) {
-               debugfs_remove(itlb);
-               return PTR_ERR(utlb);
-       }
-
        return 0;
 }
 module_init(tlb_debugfs_init);
index 3fbe03c..a6a20d6 100644 (file)
@@ -119,3 +119,19 @@ void local_flush_tlb_mm(struct mm_struct *mm)
                local_irq_restore(flags);
        }
 }
+
+void __flush_tlb_global(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       /*
+        * This is the most destructive of the TLB flushing options,
+        * and will tear down all of the UTLB/ITLB mappings, including
+        * wired entries.
+        */
+       __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
+
+       local_irq_restore(flags);
+}
index 03db41c..7f5810f 100644 (file)
@@ -455,6 +455,11 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
         flush_tlb_all();
 }
 
+void __flush_tlb_global(void)
+{
+       flush_tlb_all();
+}
+
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 }
index b25aa55..9f56eb9 100644 (file)
@@ -52,6 +52,8 @@ MIGOR                 SH_MIGOR
 RSK7201                        SH_RSK7201
 RSK7203                        SH_RSK7203
 AP325RXA               SH_AP325RXA
+SH2007                 SH_SH2007
+SH7757LCR              SH_SH7757LCR
 SH7763RDP              SH_SH7763RDP
 SH7785LCR              SH_SH7785LCR
 SH7785LCR_PT           SH_SH7785LCR_PT
index 3e9d314..8e7bafc 100644 (file)
@@ -19,6 +19,7 @@ config SPARC
        bool
        default y
        select OF
+       select OF_PROMTREE
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB if !SMP || SPARC64
index deeb0fb..3c93f08 100644 (file)
@@ -7,7 +7,6 @@ header-y += display7seg.h
 header-y += envctrl.h
 header-y += fbio.h
 header-y += jsflash.h
-header-y += openprom.h
 header-y += openpromio.h
 header-y += perfctr.h
 header-y += psrcompat.h
index c792830..86666f7 100644 (file)
@@ -304,7 +304,8 @@ static struct linux_prom_registers fd_regs[2];
 static int sun_floppy_init(void)
 {
        char state[128];
-       int tnode, fd_node, num_regs;
+       phandle tnode, fd_node;
+       int num_regs;
        struct resource r;
 
        use_virtual_dma = 1;
index 963e1a4..81cd434 100644 (file)
@@ -11,6 +11,8 @@
 #define LINUX_OPPROM_MAGIC      0x10010407
 
 #ifndef __ASSEMBLY__
+#include <linux/of.h>
+
 /* V0 prom device operations. */
 struct linux_dev_v0_funcs {
        int (*v0_devopen)(char *device_str);
@@ -26,7 +28,7 @@ struct linux_dev_v0_funcs {
 
 /* V2 and later prom device operations. */
 struct linux_dev_v2_funcs {
-       int (*v2_inst2pkg)(int d);      /* Convert ihandle to phandle */
+       phandle (*v2_inst2pkg)(int d);  /* Convert ihandle to phandle */
        char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
        void (*v2_dumb_mem_free)(char *va, unsigned sz);
 
@@ -168,12 +170,12 @@ struct linux_romvec {
 
 /* Routines for traversing the prom device tree. */
 struct linux_nodeops {
-       int (*no_nextnode)(int node);
-       int (*no_child)(int node);
-       int (*no_proplen)(int node, const char *name);
-       int (*no_getprop)(int node, const char *name, char *val);
-       int (*no_setprop)(int node, const char *name, char *val, int len);
-       char * (*no_nextprop)(int node, char *name);
+       phandle (*no_nextnode)(phandle node);
+       phandle (*no_child)(phandle node);
+       int (*no_proplen)(phandle node, const char *name);
+       int (*no_getprop)(phandle node, const char *name, char *val);
+       int (*no_setprop)(phandle node, const char *name, char *val, int len);
+       char * (*no_nextprop)(phandle node, char *name);
 };
 
 /* More fun PROM structures for device probing. */
index 33e31ce..51296a6 100644 (file)
@@ -30,7 +30,7 @@ extern unsigned int prom_rev, prom_prev;
 /* Root node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_root_node;
+extern phandle prom_root_node;
 
 /* Pointer to prom structure containing the device tree traversal
  * and usage utility functions.  Only prom-lib should use these,
@@ -178,68 +178,68 @@ extern void prom_putsegment(int context, unsigned long virt_addr,
 /* PROM device tree traversal functions... */
 
 /* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
+extern phandle prom_getchild(phandle parent_node);
 
 /* Get the next sibling node of the given node, or zero if no further
  * siblings exist.
  */
-extern int prom_getsibling(int node);
+extern phandle prom_getsibling(phandle node);
 
 /* Get the length, at the passed node, of the given property type.
  * Returns -1 on error (ie. no such property at this node).
  */
-extern int prom_getproplen(int thisnode, const char *property);
+extern int prom_getproplen(phandle thisnode, const char *property);
 
 /* Fetch the requested property using the given buffer.  Returns
  * the number of bytes the prom put into your buffer or -1 on error.
  */
-extern int __must_check prom_getproperty(int thisnode, const char *property,
+extern int __must_check prom_getproperty(phandle thisnode, const char *property,
                                         char *prop_buffer, int propbuf_size);
 
 /* Acquire an integer property. */
-extern int prom_getint(int node, char *property);
+extern int prom_getint(phandle node, char *property);
 
 /* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, char *property, int defval);
+extern int prom_getintdefault(phandle node, char *property, int defval);
 
 /* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, char *prop);
+extern int prom_getbool(phandle node, char *prop);
 
 /* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
+extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
 
 /* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, char *name);
+extern int prom_nodematch(phandle thisnode, char *name);
 
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
-extern int prom_searchsiblings(int node_start, char *name);
+extern phandle prom_searchsiblings(phandle node_start, char *name);
 
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error.
  */
-extern char *prom_firstprop(int node, char *buffer);
+extern char *prom_firstprop(phandle node, char *buffer);
 
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure.
  */
-extern char *prom_nextprop(int node, char *prev_property, char *buffer);
+extern char *prom_nextprop(phandle node, char *prev_property, char *buffer);
 
 /* Returns phandle of the path specified */
-extern int prom_finddevice(char *name);
+extern phandle prom_finddevice(char *name);
 
 /* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, char *property);
+extern int prom_node_has_property(phandle node, char *property);
 
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
-extern int prom_setprop(int node, const char *prop_name, char *prop_value,
+extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern int prom_pathtoinode(char *path);
-extern int prom_inst2pkg(int);
+extern phandle prom_pathtoinode(char *path);
+extern phandle prom_inst2pkg(int);
 
 /* Dorking with Bus ranges... */
 
@@ -247,13 +247,13 @@ extern int prom_inst2pkg(int);
 extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
 
 /* Apply ranges of any prom node (and optionally parent node as well) to registers. */
-extern void prom_apply_generic_ranges(int node, int parent,
+extern void prom_apply_generic_ranges(phandle node, phandle parent,
                                      struct linux_prom_registers *sbusregs, int nregs);
 
 /* CPU probing helpers.  */
-int cpu_find_by_instance(int instance, int *prom_node, int *mid);
-int cpu_find_by_mid(int mid, int *prom_node);
-int cpu_get_hwmid(int prom_node);
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
+int cpu_find_by_mid(int mid, phandle *prom_node);
+int cpu_get_hwmid(phandle prom_node);
 
 extern spinlock_t prom_lock;
 
index 3e0b2d6..c9cc078 100644 (file)
@@ -16,7 +16,7 @@ extern char prom_version[];
 /* Root node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_root_node;
+extern phandle prom_root_node;
 
 /* PROM stdin and stdout */
 extern int prom_stdin, prom_stdout;
@@ -24,7 +24,7 @@ extern int prom_stdin, prom_stdout;
 /* /chosen node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_chosen_node;
+extern phandle prom_chosen_node;
 
 /* Helper values and strings in arch/sparc64/kernel/head.S */
 extern const char prom_peer_name[];
@@ -218,68 +218,69 @@ extern void prom_unmap(unsigned long size, unsigned long vaddr);
 /* PROM device tree traversal functions... */
 
 /* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
+extern phandle prom_getchild(phandle parent_node);
 
 /* Get the next sibling node of the given node, or zero if no further
  * siblings exist.
  */
-extern int prom_getsibling(int node);
+extern phandle prom_getsibling(phandle node);
 
 /* Get the length, at the passed node, of the given property type.
  * Returns -1 on error (ie. no such property at this node).
  */
-extern int prom_getproplen(int thisnode, const char *property);
+extern int prom_getproplen(phandle thisnode, const char *property);
 
 /* Fetch the requested property using the given buffer.  Returns
  * the number of bytes the prom put into your buffer or -1 on error.
  */
-extern int prom_getproperty(int thisnode, const char *property,
+extern int prom_getproperty(phandle thisnode, const char *property,
                            char *prop_buffer, int propbuf_size);
 
 /* Acquire an integer property. */
-extern int prom_getint(int node, const char *property);
+extern int prom_getint(phandle node, const char *property);
 
 /* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, const char *property, int defval);
+extern int prom_getintdefault(phandle node, const char *property, int defval);
 
 /* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, const char *prop);
+extern int prom_getbool(phandle node, const char *prop);
 
 /* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
+extern void prom_getstring(phandle node, const char *prop, char *buf,
+                          int bufsize);
 
 /* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, const char *name);
+extern int prom_nodematch(phandle thisnode, const char *name);
 
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
-extern int prom_searchsiblings(int node_start, const char *name);
+extern phandle prom_searchsiblings(phandle node_start, const char *name);
 
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error. Buffer should be at least 32B long.
  */
-extern char *prom_firstprop(int node, char *buffer);
+extern char *prom_firstprop(phandle node, char *buffer);
 
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure. Buffer should be at least 32B long.
  */
-extern char *prom_nextprop(int node, const char *prev_property, char *buffer);
+extern char *prom_nextprop(phandle node, const char *prev_property, char *buf);
 
 /* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, const char *property);
+extern int prom_node_has_property(phandle node, const char *property);
 
 /* Returns phandle of the path specified */
-extern int prom_finddevice(const char *name);
+extern phandle prom_finddevice(const char *name);
 
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
-extern int prom_setprop(int node, const char *prop_name, char *prop_value,
+extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern int prom_pathtoinode(const char *path);
-extern int prom_inst2pkg(int);
+extern phandle prom_pathtoinode(const char *path);
+extern phandle prom_inst2pkg(int);
 extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
index 291f125..56bbaad 100644 (file)
@@ -18,6 +18,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
+#include <linux/of_pdt.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
 #include <asm/atomic.h>
@@ -67,8 +68,8 @@ extern struct device_node *of_console_device;
 extern char *of_console_path;
 extern char *of_console_options;
 
-extern void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
-extern char *build_full_name(struct device_node *dp);
+extern void irq_trans_init(struct device_node *dp);
+extern char *build_path_component(struct device_node *dp);
 
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index ee8d214..35f4883 100644 (file)
@@ -23,7 +23,7 @@ static DEFINE_SPINLOCK(auxio_lock);
 
 void __init auxio_probe(void)
 {
-       int node, auxio_nd;
+       phandle node, auxio_nd;
        struct linux_prom_registers auxregs[1];
        struct resource r;
 
@@ -113,7 +113,7 @@ volatile unsigned char * auxio_power_register = NULL;
 void __init auxio_power_probe(void)
 {
        struct linux_prom_registers regs;
-       int node;
+       phandle node;
        struct resource r;
 
        /* Attempt to find the sun4m power control node. */
index 8cc2d56..89aa4eb 100644 (file)
@@ -40,7 +40,7 @@ static unsigned char *dispDeviceBase __force_data;
 
 static unsigned char vga_font[cmapsz];
 
-static int __init btext_initialize(unsigned int node)
+static int __init btext_initialize(phandle node)
 {
        unsigned int width, height, depth, pitch;
        unsigned long address = 0;
@@ -309,7 +309,7 @@ static struct console btext_console = {
 
 int __init btext_find_display(void)
 {
-       unsigned int node;
+       phandle node;
        char type[32];
        int ret;
 
index 62dc7a0..d2eddd6 100644 (file)
@@ -31,9 +31,9 @@ static char *cpu_mid_prop(void)
        return "mid";
 }
 
-static int check_cpu_node(int nd, int *cur_inst,
-                         int (*compare)(int, int, void *), void *compare_arg,
-                         int *prom_node, int *mid)
+static int check_cpu_node(phandle nd, int *cur_inst,
+               int (*compare)(phandle, int, void *), void *compare_arg,
+               phandle *prom_node, int *mid)
 {
        if (!compare(nd, *cur_inst, compare_arg)) {
                if (prom_node)
@@ -51,8 +51,8 @@ static int check_cpu_node(int nd, int *cur_inst,
        return -ENODEV;
 }
 
-static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
-                        int *prom_node, int *mid)
+static int __cpu_find_by(int (*compare)(phandle, int, void *),
+               void *compare_arg, phandle *prom_node, int *mid)
 {
        struct device_node *dp;
        int cur_inst;
@@ -71,7 +71,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
        return -ENODEV;
 }
 
-static int cpu_instance_compare(int nd, int instance, void *_arg)
+static int cpu_instance_compare(phandle nd, int instance, void *_arg)
 {
        int desired_instance = (int) _arg;
 
@@ -80,13 +80,13 @@ static int cpu_instance_compare(int nd, int instance, void *_arg)
        return -ENODEV;
 }
 
-int cpu_find_by_instance(int instance, int *prom_node, int *mid)
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid)
 {
        return __cpu_find_by(cpu_instance_compare, (void *)instance,
                             prom_node, mid);
 }
 
-static int cpu_mid_compare(int nd, int instance, void *_arg)
+static int cpu_mid_compare(phandle nd, int instance, void *_arg)
 {
        int desired_mid = (int) _arg;
        int this_mid;
@@ -98,7 +98,7 @@ static int cpu_mid_compare(int nd, int instance, void *_arg)
        return -ENODEV;
 }
 
-int cpu_find_by_mid(int mid, int *prom_node)
+int cpu_find_by_mid(int mid, phandle *prom_node)
 {
        return __cpu_find_by(cpu_mid_compare, (void *)mid,
                             prom_node, NULL);
@@ -108,7 +108,7 @@ int cpu_find_by_mid(int mid, int *prom_node)
  * address (0-3).  This gives us the true hardware mid, which might have
  * some other bits set.  On 4d hardware and software mids are the same.
  */
-int cpu_get_hwmid(int prom_node)
+int cpu_get_hwmid(phandle prom_node)
 {
        return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV);
 }
@@ -119,7 +119,8 @@ void __init device_scan(void)
 
 #ifndef CONFIG_SMP
        {
-               int err, cpu_node;
+               phandle cpu_node;
+               int err;
                err = cpu_find_by_instance(0, &cpu_node, NULL);
                if (err) {
                        /* Probably a sun4e, Sun is trying to trick us ;-) */
index 6a7b4db..2d51527 100644 (file)
@@ -282,5 +282,5 @@ void __init leon_init_IRQ(void)
 
 void __init leon_init(void)
 {
-       prom_build_more = &leon_node_init;
+       of_pdt_build_more = &leon_node_init;
 }
index d36a8d3..aeaa09a 100644 (file)
@@ -284,7 +284,7 @@ int __init pcic_probe(void)
        struct linux_prom_registers regs[PROMREG_MAX];
        struct linux_pbm_info* pbm;
        char namebuf[64];
-       int node;
+       phandle node;
        int err;
 
        if (pcic0_up) {
@@ -440,7 +440,7 @@ static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm,
 {
        struct linux_prom_pci_registers regs[PROMREG_MAX];
        int err;
-       int node = prom_getchild(pbm->prom_node);
+       phandle node = prom_getchild(pbm->prom_node);
 
        while(node) {
                err = prom_getproperty(node, "reg", 
index eeb04a7..cf5fe1c 100644 (file)
@@ -4,12 +4,6 @@
 #include <linux/spinlock.h>
 #include <asm/prom.h>
 
-extern void * prom_early_alloc(unsigned long size);
-extern void irq_trans_init(struct device_node *dp);
-
-extern unsigned int prom_unique_id;
-
-extern char *build_path_component(struct device_node *dp);
 extern void of_console_init(void);
 
 extern unsigned int prom_early_allocated;
index 1f830da..ed25834 100644 (file)
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_pdt.h>
 #include <asm/prom.h>
 #include <asm/oplib.h>
 #include <asm/leon.h>
 
 #include "prom.h"
 
-void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
-
 struct device_node *of_console_device;
 EXPORT_SYMBOL(of_console_device);
 
@@ -119,192 +118,47 @@ int of_find_in_proplist(const char *list, const char *match, int len)
 }
 EXPORT_SYMBOL(of_find_in_proplist);
 
-unsigned int prom_unique_id;
-
-static struct property * __init build_one_prop(phandle node, char *prev,
-                                              char *special_name,
-                                              void *special_val,
-                                              int special_len)
+/*
+ * SPARC32 and SPARC64's prom_nextprop() do things differently
+ * here, despite sharing the same interface.  SPARC32 doesn't fill in 'buf',
+ * returning NULL on an error.  SPARC64 fills in 'buf', but sets it to an
+ * empty string upon error.
+ */
+static int __init handle_nextprop_quirks(char *buf, const char *name)
 {
-       static struct property *tmp = NULL;
-       struct property *p;
-       const char *name;
-
-       if (tmp) {
-               p = tmp;
-               memset(p, 0, sizeof(*p) + 32);
-               tmp = NULL;
-       } else {
-               p = prom_early_alloc(sizeof(struct property) + 32);
-               p->unique_id = prom_unique_id++;
-       }
-
-       p->name = (char *) (p + 1);
-       if (special_name) {
-               strcpy(p->name, special_name);
-               p->length = special_len;
-               p->value = prom_early_alloc(special_len);
-               memcpy(p->value, special_val, special_len);
-       } else {
-               if (prev == NULL) {
-                       name = prom_firstprop(node, p->name);
-               } else {
-                       name = prom_nextprop(node, prev, p->name);
-               }
+       if (!name || strlen(name) == 0)
+               return -1;
 
-               if (!name || strlen(name) == 0) {
-                       tmp = p;
-                       return NULL;
-               }
 #ifdef CONFIG_SPARC32
-               strcpy(p->name, name);
+       strcpy(buf, name);
 #endif
-               p->length = prom_getproplen(node, p->name);
-               if (p->length <= 0) {
-                       p->length = 0;
-               } else {
-                       int len;
-
-                       p->value = prom_early_alloc(p->length + 1);
-                       len = prom_getproperty(node, p->name, p->value,
-                                              p->length);
-                       if (len <= 0)
-                               p->length = 0;
-                       ((unsigned char *)p->value)[p->length] = '\0';
-               }
-       }
-       return p;
-}
-
-static struct property * __init build_prop_list(phandle node)
-{
-       struct property *head, *tail;
-
-       head = tail = build_one_prop(node, NULL,
-                                    ".node", &node, sizeof(node));
-
-       tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
-       tail = tail->next;
-       while(tail) {
-               tail->next = build_one_prop(node, tail->name,
-                                           NULL, NULL, 0);
-               tail = tail->next;
-       }
-
-       return head;
-}
-
-static char * __init get_one_property(phandle node, const char *name)
-{
-       char *buf = "<NULL>";
-       int len;
-
-       len = prom_getproplen(node, name);
-       if (len > 0) {
-               buf = prom_early_alloc(len);
-               len = prom_getproperty(node, name, buf, len);
-       }
-
-       return buf;
-}
-
-static struct device_node * __init prom_create_node(phandle node,
-                                                   struct device_node *parent)
-{
-       struct device_node *dp;
-
-       if (!node)
-               return NULL;
-
-       dp = prom_early_alloc(sizeof(*dp));
-       dp->unique_id = prom_unique_id++;
-       dp->parent = parent;
-
-       kref_init(&dp->kref);
-
-       dp->name = get_one_property(node, "name");
-       dp->type = get_one_property(node, "device_type");
-       dp->phandle = node;
-
-       dp->properties = build_prop_list(node);
-
-       irq_trans_init(dp);
-
-       return dp;
-}
-
-char * __init build_full_name(struct device_node *dp)
-{
-       int len, ourlen, plen;
-       char *n;
-
-       plen = strlen(dp->parent->full_name);
-       ourlen = strlen(dp->path_component_name);
-       len = ourlen + plen + 2;
-
-       n = prom_early_alloc(len);
-       strcpy(n, dp->parent->full_name);
-       if (!of_node_is_root(dp->parent)) {
-               strcpy(n + plen, "/");
-               plen++;
-       }
-       strcpy(n + plen, dp->path_component_name);
-
-       return n;
+       return 0;
 }
 
-static struct device_node * __init prom_build_tree(struct device_node *parent,
-                                                  phandle node,
-                                                  struct device_node ***nextp)
+static int __init prom_common_nextprop(phandle node, char *prev, char *buf)
 {
-       struct device_node *ret = NULL, *prev_sibling = NULL;
-       struct device_node *dp;
-
-       while (1) {
-               dp = prom_create_node(node, parent);
-               if (!dp)
-                       break;
-
-               if (prev_sibling)
-                       prev_sibling->sibling = dp;
-
-               if (!ret)
-                       ret = dp;
-               prev_sibling = dp;
-
-               *(*nextp) = dp;
-               *nextp = &dp->allnext;
-
-               dp->path_component_name = build_path_component(dp);
-               dp->full_name = build_full_name(dp);
-
-               dp->child = prom_build_tree(dp, prom_getchild(node), nextp);
-
-               if (prom_build_more)
-                       prom_build_more(dp, nextp);
-
-               node = prom_getsibling(node);
-       }
+       const char *name;
 
-       return ret;
+       buf[0] = '\0';
+       name = prom_nextprop(node, prev, buf);
+       return handle_nextprop_quirks(buf, name);
 }
 
 unsigned int prom_early_allocated __initdata;
 
+static struct of_pdt_ops prom_sparc_ops __initdata = {
+       .nextprop = prom_common_nextprop,
+       .getproplen = prom_getproplen,
+       .getproperty = prom_getproperty,
+       .getchild = prom_getchild,
+       .getsibling = prom_getsibling,
+};
+
 void __init prom_build_devicetree(void)
 {
-       struct device_node **nextp;
-
-       allnodes = prom_create_node(prom_root_node, NULL);
-       allnodes->path_component_name = "";
-       allnodes->full_name = "/";
-
-       nextp = &allnodes->allnext;
-       allnodes->child = prom_build_tree(allnodes,
-                                         prom_getchild(allnodes->phandle),
-                                         &nextp);
+       of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops);
        of_console_init();
 
-       printk("PROM: Built device tree with %u bytes of memory.\n",
-              prom_early_allocated);
+       pr_info("PROM: Built device tree with %u bytes of memory.\n",
+                       prom_early_allocated);
 }
index 5f72de6..29bafe0 100644 (file)
@@ -315,7 +315,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_IP_PNP
        if (!ic_set_manually) {
-               int chosen = prom_finddevice ("/chosen");
+               phandle chosen = prom_finddevice("/chosen");
                u32 cl, sv, gw;
                
                cl = prom_getintdefault (chosen, "client-ip", 0);
index 060d0f3..a4446c0 100644 (file)
@@ -23,7 +23,7 @@ int this_is_starfire = 0;
 
 void check_if_starfire(void)
 {
-       int ssnode = prom_finddevice("/ssp-serial");
+       phandle ssnode = prom_finddevice("/ssp-serial");
        if (ssnode != 0 && ssnode != -1)
                this_is_starfire = 1;
 }
index f476a5f..9aba8bd 100644 (file)
@@ -100,7 +100,7 @@ static void swift_clockstop(void)
 
 void __init clock_stop_probe(void)
 {
-       unsigned int node, clk_nd;
+       phandle node, clk_nd;
        char name[20];
     
        prom_getstring(prom_root_node, "name", name, sizeof(name));
index 4c25727..2f6ae1d 100644 (file)
@@ -88,7 +88,7 @@ static void __init read_obp_memory(const char *property,
                                   struct linux_prom64_registers *regs,
                                   int *num_ents)
 {
-       int node = prom_finddevice("/memory");
+       phandle node = prom_finddevice("/memory");
        int prop_size = prom_getproplen(node, property);
        int ents, ret, i;
 
index b0b43aa..92319aa 100644 (file)
@@ -1262,7 +1262,8 @@ extern unsigned long bootmem_init(unsigned long *pages_avail);
 
 void __init srmmu_paging_init(void)
 {
-       int i, cpunode;
+       int i;
+       phandle cpunode;
        char node_str[128];
        pgd_t *pgd;
        pmd_t *pmd;
@@ -1398,7 +1399,8 @@ static void __init srmmu_is_bad(void)
 
 static void __init init_vac_layout(void)
 {
-       int nd, cache_lines;
+       phandle nd;
+       int cache_lines;
        char node_str[128];
 #ifdef CONFIG_SMP
        int cpu = 0;
@@ -2082,7 +2084,7 @@ static void __init get_srmmu_type(void)
 
        /* Next check for Fujitsu Swift. */
        if(psr_typ == 0 && psr_vers == 4) {
-               int cpunode;
+               phandle cpunode;
                char node_str[128];
 
                /* Look if it is not a TurboSparc emulating Swift... */
index 4289f90..ddd0d86 100644 (file)
@@ -420,7 +420,7 @@ volatile unsigned long __iomem *sun4c_memerr_reg = NULL;
 
 void __init sun4c_probe_memerr_reg(void)
 {
-       int node;
+       phandle node;
        struct linux_prom_registers regs[1];
 
        node = prom_getchild(prom_root_node);
index ccb36c7..d342dba 100644 (file)
@@ -20,7 +20,7 @@ enum prom_major_version prom_vers;
 unsigned int prom_rev, prom_prev;
 
 /* The root node of the prom device tree. */
-int prom_root_node;
+phandle prom_root_node;
 EXPORT_SYMBOL(prom_root_node);
 
 /* Pointer to the device tree operations structure. */
index 7b00f89..3ff911e 100644 (file)
@@ -19,7 +19,7 @@ char prom_version[80];
 
 /* The root node of the prom device tree. */
 int prom_stdin, prom_stdout;
-int prom_chosen_node;
+phandle prom_chosen_node;
 
 /* You must call prom_init() before you attempt to use any of the
  * routines in the prom library.  It returns 0 on success, 1 on
@@ -30,7 +30,7 @@ extern void prom_cif_init(void *, void *);
 
 void __init prom_init(void *cif_handler, void *cif_stack)
 {
-       int node;
+       phandle node;
 
        prom_cif_init(cif_handler, cif_stack);
 
index fac7899..3f263a6 100644 (file)
@@ -31,7 +31,8 @@ static int __init prom_meminit_v0(void)
 static int __init prom_meminit_v2(void)
 {
        struct linux_prom_registers reg[64];
-       int node, size, num_ents, i;
+       phandle node;
+       int size, num_ents, i;
 
        node = prom_searchsiblings(prom_getchild(prom_root_node), "memory");
        size = prom_getproperty(node, "available", (char *) reg, sizeof(reg));
index 6cb1581..d24bc44 100644 (file)
@@ -183,7 +183,8 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes)
 
 int prom_get_mmu_ihandle(void)
 {
-       int node, ret;
+       phandle node;
+       int ret;
 
        if (prom_mmu_ihandle_cache != 0)
                return prom_mmu_ihandle_cache;
@@ -201,7 +202,8 @@ int prom_get_mmu_ihandle(void)
 static int prom_get_memory_ihandle(void)
 {
        static int memory_ihandle_cache;
-       int node, ret;
+       phandle node;
+       int ret;
 
        if (memory_ihandle_cache != 0)
                return memory_ihandle_cache;
index aeff43e..541fc82 100644 (file)
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(prom_apply_obio_ranges);
 
 void __init prom_ranges_init(void)
 {
-       int node, obio_node;
+       phandle node, obio_node;
        int success;
 
        num_obio_ranges = 0;
@@ -89,8 +89,8 @@ void __init prom_ranges_init(void)
                prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges);
 }
 
-void
-prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs)
+void prom_apply_generic_ranges(phandle node, phandle parent,
+               struct linux_prom_registers *regs, int nregs)
 {
        int success;
        int num_ranges;
index b21592f..63e08e1 100644 (file)
@@ -20,10 +20,10 @@ extern void restore_current(void);
 static char promlib_buf[128];
 
 /* Internal version of prom_getchild that does not alter return values. */
-int __prom_getchild(int node)
+phandle __prom_getchild(phandle node)
 {
        unsigned long flags;
-       int cnode;
+       phandle cnode;
 
        spin_lock_irqsave(&prom_lock, flags);
        cnode = prom_nodeops->no_child(node);
@@ -36,9 +36,9 @@ int __prom_getchild(int node)
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
-int prom_getchild(int node)
+phandle prom_getchild(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -52,10 +52,10 @@ int prom_getchild(int node)
 EXPORT_SYMBOL(prom_getchild);
 
 /* Internal version of prom_getsibling that does not alter return values. */
-int __prom_getsibling(int node)
+phandle __prom_getsibling(phandle node)
 {
        unsigned long flags;
-       int cnode;
+       phandle cnode;
 
        spin_lock_irqsave(&prom_lock, flags);
        cnode = prom_nodeops->no_nextnode(node);
@@ -68,9 +68,9 @@ int __prom_getsibling(int node)
 /* Return the next sibling of node 'node' or zero if no more siblings
  * at this level of depth in the tree.
  */
-int prom_getsibling(int node)
+phandle prom_getsibling(phandle node)
 {
-       int sibnode;
+       phandle sibnode;
 
        if (node == -1)
                return 0;
@@ -86,7 +86,7 @@ EXPORT_SYMBOL(prom_getsibling);
 /* Return the length in bytes of property 'prop' at node 'node'.
  * Return -1 on error.
  */
-int prom_getproplen(int node, const char *prop)
+int prom_getproplen(phandle node, const char *prop)
 {
        int ret;
        unsigned long flags;
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(prom_getproplen);
  * 'buffer' which has a size of 'bufsize'.  If the acquisition
  * was successful the length will be returned, else -1 is returned.
  */
-int prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
+int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize)
 {
        int plen, ret;
        unsigned long flags;
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(prom_getproperty);
 /* Acquire an integer property and return its value.  Returns -1
  * on failure.
  */
-int prom_getint(int node, char *prop)
+int prom_getint(phandle node, char *prop)
 {
        static int intprop;
 
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(prom_getint);
 /* Acquire an integer property, upon error return the passed default
  * integer.
  */
-int prom_getintdefault(int node, char *property, int deflt)
+int prom_getintdefault(phandle node, char *property, int deflt)
 {
        int retval;
 
@@ -152,7 +152,7 @@ int prom_getintdefault(int node, char *property, int deflt)
 EXPORT_SYMBOL(prom_getintdefault);
 
 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, char *prop)
+int prom_getbool(phandle node, char *prop)
 {
        int retval;
 
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(prom_getbool);
  * string on error.  The char pointer is the user supplied string
  * buffer.
  */
-void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size)
 {
        int len;
 
@@ -180,7 +180,7 @@ EXPORT_SYMBOL(prom_getstring);
 /* Does the device at node 'node' have name 'name'?
  * YES = 1   NO = 0
  */
-int prom_nodematch(int node, char *name)
+int prom_nodematch(phandle node, char *name)
 {
        int error;
 
@@ -194,10 +194,11 @@ int prom_nodematch(int node, char *name)
 /* Search siblings at 'node_start' for a node with name
  * 'nodename'.  Return node if successful, zero if not.
  */
-int prom_searchsiblings(int node_start, char *nodename)
+phandle prom_searchsiblings(phandle node_start, char *nodename)
 {
 
-       int thisnode, error;
+       phandle thisnode;
+       int error;
 
        for(thisnode = node_start; thisnode;
            thisnode=prom_getsibling(thisnode)) {
@@ -213,7 +214,7 @@ int prom_searchsiblings(int node_start, char *nodename)
 EXPORT_SYMBOL(prom_searchsiblings);
 
 /* Interal version of nextprop that does not alter return values. */
-char * __prom_nextprop(int node, char * oprop)
+char *__prom_nextprop(phandle node, char * oprop)
 {
        unsigned long flags;
        char *prop;
@@ -228,7 +229,7 @@ char * __prom_nextprop(int node, char * oprop)
 
 /* Return the first property name for node 'node'. */
 /* buffer is unused argument, but as v9 uses it, we need to have the same interface */
-char * prom_firstprop(int node, char *bufer)
+char *prom_firstprop(phandle node, char *bufer)
 {
        if (node == 0 || node == -1)
                return "";
@@ -241,7 +242,7 @@ EXPORT_SYMBOL(prom_firstprop);
  * at node 'node' .  Returns empty string if no more
  * property types for this node.
  */
-char * prom_nextprop(int node, char *oprop, char *buffer)
+char *prom_nextprop(phandle node, char *oprop, char *buffer)
 {
        if (node == 0 || node == -1)
                return "";
@@ -250,11 +251,11 @@ char * prom_nextprop(int node, char *oprop, char *buffer)
 }
 EXPORT_SYMBOL(prom_nextprop);
 
-int prom_finddevice(char *name)
+phandle prom_finddevice(char *name)
 {
        char nbuf[128];
        char *s = name, *d;
-       int node = prom_root_node, node2;
+       phandle node = prom_root_node, node2;
        unsigned int which_io, phys_addr;
        struct linux_prom_registers reg[PROMREG_MAX];
 
@@ -298,7 +299,7 @@ int prom_finddevice(char *name)
 }
 EXPORT_SYMBOL(prom_finddevice);
 
-int prom_node_has_property(int node, char *prop)
+int prom_node_has_property(phandle node, char *prop)
 {
        char *current_property = "";
 
@@ -314,7 +315,7 @@ EXPORT_SYMBOL(prom_node_has_property);
 /* Set property 'pname' at node 'node' to value 'value' which has a length
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
-int prom_setprop(int node, const char *pname, char *value, int size)
+int prom_setprop(phandle node, const char *pname, char *value, int size)
 {
        unsigned long flags;
        int ret;
@@ -329,9 +330,9 @@ int prom_setprop(int node, const char *pname, char *value, int size)
 }
 EXPORT_SYMBOL(prom_setprop);
 
-int prom_inst2pkg(int inst)
+phandle prom_inst2pkg(int inst)
 {
-       int node;
+       phandle node;
        unsigned long flags;
        
        spin_lock_irqsave(&prom_lock, flags);
@@ -345,9 +346,10 @@ int prom_inst2pkg(int inst)
 /* Return 'node' assigned to a particular prom 'path'
  * FIXME: Should work for v0 as well
  */
-int prom_pathtoinode(char *path)
+phandle prom_pathtoinode(char *path)
 {
-       int node, inst;
+       phandle node;
+       int inst;
        
        inst = prom_devopen (path);
        if (inst == -1) return 0;
index 9d3f913..691be68 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/oplib.h>
 #include <asm/ldc.h>
 
-static int prom_node_to_node(const char *type, int node)
+static phandle prom_node_to_node(const char *type, phandle node)
 {
        unsigned long args[5];
 
@@ -28,20 +28,20 @@ static int prom_node_to_node(const char *type, int node)
 
        p1275_cmd_direct(args);
 
-       return (int) args[4];
+       return (phandle) args[4];
 }
 
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
-inline int __prom_getchild(int node)
+inline phandle __prom_getchild(phandle node)
 {
        return prom_node_to_node("child", node);
 }
 
-inline int prom_getchild(int node)
+inline phandle prom_getchild(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -52,9 +52,9 @@ inline int prom_getchild(int node)
 }
 EXPORT_SYMBOL(prom_getchild);
 
-inline int prom_getparent(int node)
+inline phandle prom_getparent(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -67,14 +67,14 @@ inline int prom_getparent(int node)
 /* Return the next sibling of node 'node' or zero if no more siblings
  * at this level of depth in the tree.
  */
-inline int __prom_getsibling(int node)
+inline phandle __prom_getsibling(phandle node)
 {
        return prom_node_to_node(prom_peer_name, node);
 }
 
-inline int prom_getsibling(int node)
+inline phandle prom_getsibling(phandle node)
 {
-       int sibnode;
+       phandle sibnode;
 
        if (node == -1)
                return 0;
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(prom_getsibling);
 /* Return the length in bytes of property 'prop' at node 'node'.
  * Return -1 on error.
  */
-inline int prom_getproplen(int node, const char *prop)
+inline int prom_getproplen(phandle node, const char *prop)
 {
        unsigned long args[6];
 
@@ -113,7 +113,7 @@ EXPORT_SYMBOL(prom_getproplen);
  * 'buffer' which has a size of 'bufsize'.  If the acquisition
  * was successful the length will be returned, else -1 is returned.
  */
-inline int prom_getproperty(int node, const char *prop,
+inline int prom_getproperty(phandle node, const char *prop,
                            char *buffer, int bufsize)
 {
        unsigned long args[8];
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(prom_getproperty);
 /* Acquire an integer property and return its value.  Returns -1
  * on failure.
  */
-inline int prom_getint(int node, const char *prop)
+inline int prom_getint(phandle node, const char *prop)
 {
        int intprop;
 
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(prom_getint);
  * integer.
  */
 
-int prom_getintdefault(int node, const char *property, int deflt)
+int prom_getintdefault(phandle node, const char *property, int deflt)
 {
        int retval;
 
@@ -169,7 +169,7 @@ int prom_getintdefault(int node, const char *property, int deflt)
 EXPORT_SYMBOL(prom_getintdefault);
 
 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, const char *prop)
+int prom_getbool(phandle node, const char *prop)
 {
        int retval;
 
@@ -184,7 +184,8 @@ EXPORT_SYMBOL(prom_getbool);
  * string on error.  The char pointer is the user supplied string
  * buffer.
  */
-void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(phandle node, const char *prop, char *user_buf,
+               int ubuf_size)
 {
        int len;
 
@@ -198,7 +199,7 @@ EXPORT_SYMBOL(prom_getstring);
 /* Does the device at node 'node' have name 'name'?
  * YES = 1   NO = 0
  */
-int prom_nodematch(int node, const char *name)
+int prom_nodematch(phandle node, const char *name)
 {
        char namebuf[128];
        prom_getproperty(node, "name", namebuf, sizeof(namebuf));
@@ -210,10 +211,10 @@ int prom_nodematch(int node, const char *name)
 /* Search siblings at 'node_start' for a node with name
  * 'nodename'.  Return node if successful, zero if not.
  */
-int prom_searchsiblings(int node_start, const char *nodename)
+phandle prom_searchsiblings(phandle node_start, const char *nodename)
 {
-
-       int thisnode, error;
+       phandle thisnode;
+       int error;
        char promlib_buf[128];
 
        for(thisnode = node_start; thisnode;
@@ -234,7 +235,7 @@ static const char *prom_nextprop_name = "nextprop";
 /* Return the first property type for node 'node'.
  * buffer should be at least 32B in length
  */
-inline char *prom_firstprop(int node, char *buffer)
+inline char *prom_firstprop(phandle node, char *buffer)
 {
        unsigned long args[7];
 
@@ -260,7 +261,7 @@ EXPORT_SYMBOL(prom_firstprop);
  * at node 'node' .  Returns NULL string if no more
  * property types for this node.
  */
-inline char *prom_nextprop(int node, const char *oprop, char *buffer)
+inline char *prom_nextprop(phandle node, const char *oprop, char *buffer)
 {
        unsigned long args[7];
        char buf[32];
@@ -288,8 +289,7 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
 }
 EXPORT_SYMBOL(prom_nextprop);
 
-int
-prom_finddevice(const char *name)
+phandle prom_finddevice(const char *name)
 {
        unsigned long args[5];
 
@@ -307,7 +307,7 @@ prom_finddevice(const char *name)
 }
 EXPORT_SYMBOL(prom_finddevice);
 
-int prom_node_has_property(int node, const char *prop)
+int prom_node_has_property(phandle node, const char *prop)
 {
        char buf [32];
         
@@ -325,7 +325,7 @@ EXPORT_SYMBOL(prom_node_has_property);
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
 int
-prom_setprop(int node, const char *pname, char *value, int size)
+prom_setprop(phandle node, const char *pname, char *value, int size)
 {
        unsigned long args[8];
 
@@ -355,10 +355,10 @@ prom_setprop(int node, const char *pname, char *value, int size)
 }
 EXPORT_SYMBOL(prom_setprop);
 
-inline int prom_inst2pkg(int inst)
+inline phandle prom_inst2pkg(int inst)
 {
        unsigned long args[5];
-       int node;
+       phandle node;
        
        args[0] = (unsigned long) "instance-to-package";
        args[1] = 1;
@@ -377,10 +377,10 @@ inline int prom_inst2pkg(int inst)
 /* Return 'node' assigned to a particular prom 'path'
  * FIXME: Should work for v0 as well
  */
-int
-prom_pathtoinode(const char *path)
+phandle prom_pathtoinode(const char *path)
 {
-       int node, inst;
+       phandle node;
+       int inst;
 
        inst = prom_devopen (path);
        if (inst == 0)
index 101229b..42a978c 100644 (file)
@@ -89,6 +89,8 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 /* EC commands */
 
 #define EC_FIRMWARE_REV                0x08
+#define EC_WLAN_ENTER_RESET    0x35
+#define EC_WLAN_LEAVE_RESET    0x25
 
 /* SCI source values */
 
index 74a8478..69fd72a 100644 (file)
@@ -15,7 +15,6 @@
 
 #ifdef CONFIG_X86_32
 #include <asm/pgtable.h>
-#include <asm/pgtable_32.h>
 #endif
 
 #include "realmode/wakeup.h"
index 881fe44..f0834e2 100644 (file)
@@ -64,15 +64,13 @@ static void drive_stat_acct(struct request *rq, int new_io)
                return;
 
        cpu = part_stat_lock();
+       part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
-       if (!new_io) {
-               part = rq->part;
+       if (!new_io)
                part_stat_inc(cpu, part, merges[rw]);
-       } else {
-               part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
+       else {
                part_round_stats(cpu, part);
                part_inc_in_flight(part, rw);
-               rq->part = part;
        }
 
        part_stat_unlock();
@@ -130,7 +128,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
        rq->ref_count = 1;
        rq->start_time = jiffies;
        set_start_time_ns(rq);
-       rq->part = NULL;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -805,16 +802,11 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
        rl->starved[is_sync] = 0;
 
        priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-       if (priv) {
+       if (priv)
                rl->elvpriv++;
 
-               /*
-                * Don't do stats for non-priv requests
-                */
-               if (blk_queue_io_stat(q))
-                       rw_flags |= REQ_IO_STAT;
-       }
-
+       if (blk_queue_io_stat(q))
+               rw_flags |= REQ_IO_STAT;
        spin_unlock_irq(q->queue_lock);
 
        rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -1791,7 +1783,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
                part_stat_add(cpu, part, sectors[rw], bytes >> 9);
                part_stat_unlock();
        }
@@ -1811,7 +1803,7 @@ static void blk_account_io_done(struct request *req)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
                part_stat_inc(cpu, part, ios[rw]);
                part_stat_add(cpu, part, ticks[rw], duration);
index 0a2fd8a..77b7c26 100644 (file)
@@ -351,7 +351,7 @@ static void blk_account_io_merge(struct request *req)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
                part_round_stats(cpu, part);
                part_dec_in_flight(part, rq_data_dir(req));
index 1e675e5..2db8f32 100644 (file)
@@ -116,6 +116,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);
 
 int blk_dev_init(void);
 
+void elv_quiesce_start(struct request_queue *q);
+void elv_quiesce_end(struct request_queue *q);
+
+
 /*
  * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
index a8adf96..5fa2b44 100644 (file)
@@ -929,15 +929,8 @@ static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
 {
        struct disk_part_tbl *ptbl =
                container_of(head, struct disk_part_tbl, rcu_head);
-       struct gendisk *disk = ptbl->disk;
-       struct request_queue *q = disk->queue;
-       unsigned long flags;
 
        kfree(ptbl);
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       elv_quiesce_end(q);
-       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -955,17 +948,11 @@ static void disk_replace_part_tbl(struct gendisk *disk,
                                  struct disk_part_tbl *new_ptbl)
 {
        struct disk_part_tbl *old_ptbl = disk->part_tbl;
-       struct request_queue *q = disk->queue;
 
        rcu_assign_pointer(disk->part_tbl, new_ptbl);
 
        if (old_ptbl) {
                rcu_assign_pointer(old_ptbl->last_lookup, NULL);
-
-               spin_lock_irq(q->queue_lock);
-               elv_quiesce_start(q);
-               spin_unlock_irq(q->queue_lock);
-
                call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
        }
 }
@@ -1006,7 +993,6 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno)
                return -ENOMEM;
 
        new_ptbl->len = target;
-       new_ptbl->disk = disk;
 
        for (i = 0; i < len; i++)
                rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
index a2aea53..14cf907 100644 (file)
@@ -51,7 +51,6 @@ obj-y                         += net/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_FUSION)           += message/
 obj-y                          += firewire/
-obj-y                          += ieee1394/
 obj-$(CONFIG_UIO)              += uio/
 obj-y                          += cdrom/
 obj-y                          += auxdisplay/
@@ -92,6 +91,7 @@ obj-$(CONFIG_EISA)            += eisa/
 obj-y                          += lguest/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_CPU_IDLE)         += cpuidle/
+obj-$(CONFIG_DMA_ENGINE)       += dma/
 obj-$(CONFIG_MMC)              += mmc/
 obj-$(CONFIG_MEMSTICK)         += memstick/
 obj-$(CONFIG_NEW_LEDS)         += leds/
@@ -104,7 +104,6 @@ obj-$(CONFIG_ARCH_SHMOBILE) += sh/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y                          += clocksource/
 endif
-obj-$(CONFIG_DMA_ENGINE)       += dma/
 obj-$(CONFIG_DCA)              += dca/
 obj-$(CONFIG_HID)              += hid/
 obj-$(CONFIG_PPC_PS3)          += ps3/
index 3966e62..f051cff 100644 (file)
@@ -147,6 +147,7 @@ static void platform_device_release(struct device *dev)
        struct platform_object *pa = container_of(dev, struct platform_object,
                                                  pdev.dev);
 
+       of_device_node_put(&pa->pdev.dev);
        kfree(pa->pdev.dev.platform_data);
        kfree(pa->pdev.resource);
        kfree(pa);
index 6e968cd..829161e 100644 (file)
@@ -1225,7 +1225,8 @@ ace_of_probe(struct platform_device *op, const struct of_device_id *match)
                bus_width = ACE_BUS_WIDTH_8;
 
        /* Call the bus-independant setup code */
-       return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width);
+       return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
+                                               physaddr, irq, bus_width);
 }
 
 static int __devexit ace_of_remove(struct platform_device *op)
index 7b01bc6..c3425bb 100644 (file)
@@ -1303,13 +1303,11 @@ static int __init hvc_iucv_init(void)
        if (rc) {
                pr_err("Registering IUCV handlers failed with error code=%d\n",
                        rc);
-               goto out_error_iucv;
+               goto out_error_hvc;
        }
 
        return 0;
 
-out_error_iucv:
-       iucv_unregister(&hvc_iucv_handler, 0);
 out_error_hvc:
        for (i = 0; i < hvc_iucv_devices; i++)
                if (hvc_iucv_table[i])
index a7ca752..e95d787 100644 (file)
@@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
  */
 
 struct getset_keycode_data {
-       unsigned int scancode;
-       unsigned int keycode;
+       struct input_keymap_entry ke;
        int error;
 };
 
@@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data)
 {
        struct getset_keycode_data *d = data;
 
-       d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode);
+       d->error = input_get_keycode(handle->dev, &d->ke);
 
        return d->error == 0; /* stop as soon as we successfully get one */
 }
 
 int getkeycode(unsigned int scancode)
 {
-       struct getset_keycode_data d = { scancode, 0, -ENODEV };
+       struct getset_keycode_data d = {
+               .ke     = {
+                       .flags          = 0,
+                       .len            = sizeof(scancode),
+                       .keycode        = 0,
+               },
+               .error  = -ENODEV,
+       };
+
+       memcpy(d.ke.scancode, &scancode, sizeof(scancode));
 
        input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
 
-       return d.error ?: d.keycode;
+       return d.error ?: d.ke.keycode;
 }
 
 static int setkeycode_helper(struct input_handle *handle, void *data)
 {
        struct getset_keycode_data *d = data;
 
-       d->error = input_set_keycode(handle->dev, d->scancode, d->keycode);
+       d->error = input_set_keycode(handle->dev, &d->ke);
 
        return d->error == 0; /* stop as soon as we successfully set one */
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-       struct getset_keycode_data d = { scancode, keycode, -ENODEV };
+       struct getset_keycode_data d = {
+               .ke     = {
+                       .flags          = 0,
+                       .len            = sizeof(scancode),
+                       .keycode        = keycode,
+               },
+               .error  = -ENODEV,
+       };
+
+       memcpy(d.ke.scancode, &scancode, sizeof(scancode));
 
        input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
 
index f3019f5..eaa5d3e 100644 (file)
@@ -566,10 +566,16 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] =
 static bool sysrq_down;
 static int sysrq_alt_use;
 static int sysrq_alt;
+static DEFINE_SPINLOCK(sysrq_event_lock);
 
 static bool sysrq_filter(struct input_handle *handle, unsigned int type,
                         unsigned int code, int value)
 {
+       bool suppress;
+
+       /* We are called with interrupts disabled, just take the lock */
+       spin_lock(&sysrq_event_lock);
+
        if (type != EV_KEY)
                goto out;
 
@@ -601,7 +607,10 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
        }
 
 out:
-       return sysrq_down;
+       suppress = sysrq_down;
+       spin_unlock(&sysrq_event_lock);
+
+       return suppress;
 }
 
 static int sysrq_connect(struct input_handler *handler,
@@ -652,8 +661,8 @@ static void sysrq_disconnect(struct input_handle *handle)
 }
 
 /*
- * We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all
- * keyboards have SysRq ikey predefined and so user may add it to keymap
+ * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all
+ * keyboards have SysRq key predefined and so user may add it to keymap
  * later, but we expect all such keyboards to have left alt.
  */
 static const struct input_device_id sysrq_ids[] = {
index 717305d..a446116 100644 (file)
@@ -308,7 +308,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
         * isr before we end up here.
         */
        if (p->flags & FLAG_CLOCKSOURCE)
-               p->total_cycles += p->match_value;
+               p->total_cycles += p->match_value + 1;
 
        if (!(p->flags & FLAG_REPROGRAM))
                p->next_match_value = p->max_match_value;
@@ -403,7 +403,7 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
        raw = sh_cmt_get_counter(p, &has_wrapped);
 
        if (unlikely(has_wrapped))
-               raw += p->match_value;
+               raw += p->match_value + 1;
        spin_unlock_irqrestore(&p->lock, flags);
 
        return value + raw;
@@ -445,7 +445,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
 
        /* clk_get_rate() needs an enabled clock */
        clk_enable(p->clk);
-       p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
+       p->rate = clk_get_rate(p->clk) / ((p->width == 16) ? 512 : 8);
        clk_disable(p->clk);
 
        /* TODO: calculate good shift from rate and counter bit width */
@@ -478,7 +478,7 @@ static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
        ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
 
        if (periodic)
-               sh_cmt_set_next(p, (p->rate + HZ/2) / HZ);
+               sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1);
        else
                sh_cmt_set_next(p, p->max_match_value);
 }
@@ -523,9 +523,9 @@ static int sh_cmt_clock_event_next(unsigned long delta,
 
        BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
        if (likely(p->flags & FLAG_IRQCONTEXT))
-               p->next_match_value = delta;
+               p->next_match_value = delta - 1;
        else
-               sh_cmt_set_next(p, delta);
+               sh_cmt_set_next(p, delta - 1);
 
        return 0;
 }
index fcf3ea2..40a222e 100644 (file)
@@ -3,9 +3,6 @@ menu "IEEE 1394 (FireWire) support"
        # firewire-core does not depend on PCI but is
        # not useful without PCI controller driver
 
-comment "You can enable one or both FireWire driver stacks."
-comment "The newer stack is recommended."
-
 config FIREWIRE
        tristate "FireWire driver stack"
        select CRC_ITU_T
@@ -64,8 +61,6 @@ config FIREWIRE_NET
          To compile this driver as a module, say M here:  The module will be
          called firewire-net.
 
-source "drivers/ieee1394/Kconfig"
-
 config FIREWIRE_NOSY
        tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"
        depends on PCI
index 3c6a7fb..e3870d5 100644 (file)
@@ -13,3 +13,4 @@ obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
 obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
 obj-$(CONFIG_FIREWIRE_NET)  += firewire-net.o
 obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o
+obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
similarity index 84%
rename from drivers/ieee1394/init_ohci1394_dma.c
rename to drivers/firewire/init_ohci1394_dma.c
index ddaab6e..a9a347a 100644 (file)
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <linux/interrupt.h>   /* for ohci1394.h */
 #include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/pci.h>         /* for PCI defines */
-#include <linux/init_ohci1394_dma.h>
+#include <linux/string.h>
+
 #include <asm/pci-direct.h>    /* for direct PCI config space access */
 #include <asm/fixmap.h>
 
-#include "ieee1394_types.h"
-#include "ohci1394.h"
+#include <linux/init_ohci1394_dma.h>
+#include "ohci.h"
 
 int __initdata init_ohci1394_dma_early;
 
+struct ohci {
+       void __iomem *registers;
+};
+
+static inline void reg_write(const struct ohci *ohci, int offset, u32 data)
+{
+       writel(data, ohci->registers + offset);
+}
+
+static inline u32 reg_read(const struct ohci *ohci, int offset)
+{
+       return readl(ohci->registers + offset);
+}
+
+#define OHCI_LOOP_COUNT                100     /* Number of loops for reg read waits */
+
 /* Reads a PHY register of an OHCI-1394 controller */
-static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
+static inline u8 __init get_phy_reg(struct ohci *ohci, u8 addr)
 {
        int i;
-       quadlet_t r;
+       u32 r;
 
        reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
 
@@ -63,22 +81,22 @@ static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
 }
 
 /* Writes to a PHY register of an OHCI-1394 controller */
-static inline void __init set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
+static inline void __init set_phy_reg(struct ohci *ohci, u8 addr, u8 data)
 {
        int i;
 
        reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
 
        for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               u32 r = reg_read(ohci, OHCI1394_PhyControl);
-               if (!(r & 0x00004000))
+               if (!(reg_read(ohci, OHCI1394_PhyControl) & 0x00004000))
                        break;
                mdelay(1);
        }
 }
 
 /* Resets an OHCI-1394 controller (for sane state before initialization) */
-static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
+static inline void __init init_ohci1394_soft_reset(struct ohci *ohci)
+{
        int i;
 
        reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
@@ -91,10 +109,14 @@ static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
        }
 }
 
+#define OHCI1394_MAX_AT_REQ_RETRIES    0xf
+#define OHCI1394_MAX_AT_RESP_RETRIES   0x2
+#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
+
 /* Basic OHCI-1394 register and port inititalization */
-static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
+static inline void __init init_ohci1394_initialize(struct ohci *ohci)
 {
-       quadlet_t bus_options;
+       u32 bus_options;
        int num_ports, i;
 
        /* Put some defaults to these undefined bus options */
@@ -116,7 +138,7 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
 
        /* enable phys */
        reg_write(ohci, OHCI1394_LinkControlSet,
-                       OHCI1394_LinkControl_RcvPhyPkt);
+                       OHCI1394_LinkControl_rcvPhyPkt);
 
        /* Don't accept phy packets into AR request context */
        reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
@@ -128,7 +150,7 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
        reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
 
        /* Accept asyncronous transfer requests from all nodes for now */
-       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
+       reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
 
        /* Specify asyncronous transfer retries */
        reg_write(ohci, OHCI1394_ATRetries,
@@ -137,7 +159,8 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
                  (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
 
        /* We don't want hardware swapping */
-       reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
+       reg_write(ohci, OHCI1394_HCControlClear,
+                 OHCI1394_HCControl_noByteSwapData);
 
        /* Enable link */
        reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
@@ -164,11 +187,11 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
  * has to be enabled after each bus reset when needed. We resort
  * to polling here because on early boot, we have no interrupts.
  */
-static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
+static inline void __init init_ohci1394_wait_for_busresets(struct ohci *ohci)
 {
        int i, events;
 
-       for (i=0; i < 9; i++) {
+       for (i = 0; i < 9; i++) {
                mdelay(200);
                events = reg_read(ohci, OHCI1394_IntEventSet);
                if (events & OHCI1394_busReset)
@@ -182,18 +205,18 @@ static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
  * This enables remote DMA access over IEEE1394 from every host for the low
  * 4GB of address space. DMA accesses above 4GB are not available currently.
  */
-static inline void __init init_ohci1394_enable_physical_dma(struct ti_ohci *hci)
+static inline void __init init_ohci1394_enable_physical_dma(struct ohci *ohci)
 {
-       reg_write(hci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
-       reg_write(hci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
-       reg_write(hci, OHCI1394_PhyUpperBound, 0xffff0000);
+       reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
+       reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
+       reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
 }
 
 /**
  * init_ohci1394_reset_and_init_dma - init controller and enable DMA
  * This initializes the given controller and enables physical DMA engine in it.
  */
-static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
+static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci)
 {
        /* Start off with a soft reset, clears everything to a sane state. */
        init_ohci1394_soft_reset(ohci);
@@ -225,7 +248,7 @@ static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
 static inline void __init init_ohci1394_controller(int num, int slot, int func)
 {
        unsigned long ohci_base;
-       struct ti_ohci ohci;
+       struct ohci ohci;
 
        printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
                         " at %02x:%02x.%x\n", num, slot, func);
@@ -235,7 +258,7 @@ static inline void __init init_ohci1394_controller(int num, int slot, int func)
 
        set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
 
-       ohci.registers = (void *)fix_to_virt(FIX_OHCI1394_BASE);
+       ohci.registers = (void __iomem *)fix_to_virt(FIX_OHCI1394_BASE);
 
        init_ohci1394_reset_and_init_dma(&ohci);
 }
@@ -247,6 +270,7 @@ static inline void __init init_ohci1394_controller(int num, int slot, int func)
 void __init init_ohci1394_dma_on_all_controllers(void)
 {
        int num, slot, func;
+       u32 class;
 
        if (!early_pci_allowed())
                return;
@@ -255,9 +279,9 @@ void __init init_ohci1394_dma_on_all_controllers(void)
        for (num = 0; num < 32; num++) {
                for (slot = 0; slot < 32; slot++) {
                        for (func = 0; func < 8; func++) {
-                               u32 class = read_pci_config(num,slot,func,
+                               class = read_pci_config(num, slot, func,
                                                        PCI_CLASS_REVISION);
-                               if ((class == 0xffffffff))
+                               if (class == 0xffffffff)
                                        continue; /* No device at this func */
 
                                if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
index 7096909..846fbd5 100644 (file)
@@ -171,13 +171,13 @@ static int __devinit xgpio_of_probe(struct device_node *np)
        /* Update GPIO state shadow register with default value */
        tree_info = of_get_property(np, "xlnx,dout-default", NULL);
        if (tree_info)
-               chip->gpio_state = *tree_info;
+               chip->gpio_state = be32_to_cpup(tree_info);
 
        /* Update GPIO direction shadow register with default value */
        chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
        tree_info = of_get_property(np, "xlnx,tri-default", NULL);
        if (tree_info)
-               chip->gpio_dir = *tree_info;
+               chip->gpio_dir = be32_to_cpup(tree_info);
 
        /* Check device node and parent device node for device width */
        chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
@@ -186,7 +186,7 @@ static int __devinit xgpio_of_probe(struct device_node *np)
                tree_info = of_get_property(np->parent,
                                            "xlnx,gpio-width", NULL);
        if (tree_info)
-               chip->mmchip.gc.ngpio = *tree_info;
+               chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
 
        spin_lock_init(&chip->gpio_lock);
 
index 7832b6e..515345b 100644 (file)
@@ -1780,6 +1780,11 @@ static bool hid_ignore(struct hid_device *hdev)
                    hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
                        return true;
                break;
+       case USB_VENDOR_ID_HANWANG:
+               if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST &&
+                   hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST)
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
index 3ee999d..3341baa 100644 (file)
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
 #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
 
+#define USB_VENDOR_ID_HANWANG          0x0b57
+#define USB_DEVICE_ID_HANWANG_TABLET_FIRST     0x5000
+#define USB_DEVICE_ID_HANWANG_TABLET_LAST      0x8fff
+
 #define USB_VENDOR_ID_HAPP             0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING     0x0010
 #define USB_DEVICE_ID_UGCI_FLYING      0x0020
index 834ef47..bb0b365 100644 (file)
@@ -68,39 +68,52 @@ static const struct {
 #define map_key_clear(c)       hid_map_usage_clear(hidinput, usage, &bit, \
                &max, EV_KEY, (c))
 
-static inline int match_scancode(unsigned int code, unsigned int scancode)
+static bool match_scancode(struct hid_usage *usage,
+                          unsigned int cur_idx, unsigned int scancode)
 {
-       if (scancode == 0)
-               return 1;
-
-       return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
+       return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
 }
 
-static inline int match_keycode(unsigned int code, unsigned int keycode)
+static bool match_keycode(struct hid_usage *usage,
+                         unsigned int cur_idx, unsigned int keycode)
 {
-       if (keycode == 0)
-               return 1;
+       /*
+        * We should exclude unmapped usages when doing lookup by keycode.
+        */
+       return (usage->type == EV_KEY && usage->code == keycode);
+}
 
-       return code == keycode;
+static bool match_index(struct hid_usage *usage,
+                       unsigned int cur_idx, unsigned int idx)
+{
+       return cur_idx == idx;
 }
 
+typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
+                               unsigned int cur_idx, unsigned int val);
+
 static struct hid_usage *hidinput_find_key(struct hid_device *hid,
-                                          unsigned int scancode,
-                                          unsigned int keycode)
+                                          hid_usage_cmp_t match,
+                                          unsigned int value,
+                                          unsigned int *usage_idx)
 {
-       int i, j, k;
+       unsigned int i, j, k, cur_idx = 0;
        struct hid_report *report;
        struct hid_usage *usage;
 
        for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
                list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
                        for (i = 0; i < report->maxfield; i++) {
-                               for ( j = 0; j < report->field[i]->maxusage; j++) {
+                               for (j = 0; j < report->field[i]->maxusage; j++) {
                                        usage = report->field[i]->usage + j;
-                                       if (usage->type == EV_KEY &&
-                                               match_scancode(usage->hid, scancode) &&
-                                               match_keycode(usage->code, keycode))
-                                               return usage;
+                                       if (usage->type == EV_KEY || usage->type == 0) {
+                                               if (match(usage, cur_idx, value)) {
+                                                       if (usage_idx)
+                                                               *usage_idx = cur_idx;
+                                                       return usage;
+                                               }
+                                               cur_idx++;
+                                       }
                                }
                        }
                }
@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
        return NULL;
 }
 
+static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
+                                       const struct input_keymap_entry *ke,
+                                       unsigned int *index)
+{
+       struct hid_usage *usage;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               usage = hidinput_find_key(hid, match_index, ke->index, index);
+       else if (input_scancode_to_scalar(ke, &scancode) == 0)
+               usage = hidinput_find_key(hid, match_scancode, scancode, index);
+       else
+               usage = NULL;
+
+       return usage;
+}
+
 static int hidinput_getkeycode(struct input_dev *dev,
-                              unsigned int scancode, unsigned int *keycode)
+                              struct input_keymap_entry *ke)
 {
        struct hid_device *hid = input_get_drvdata(dev);
        struct hid_usage *usage;
+       unsigned int scancode, index;
 
-       usage = hidinput_find_key(hid, scancode, 0);
+       usage = hidinput_locate_usage(hid, ke, &index);
        if (usage) {
-               *keycode = usage->code;
+               ke->keycode = usage->type == EV_KEY ?
+                               usage->code : KEY_RESERVED;
+               ke->index = index;
+               scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
+               ke->len = sizeof(scancode);
+               memcpy(ke->scancode, &scancode, sizeof(scancode));
                return 0;
        }
+
        return -EINVAL;
 }
 
 static int hidinput_setkeycode(struct input_dev *dev,
-                              unsigned int scancode, unsigned int keycode)
+                              const struct input_keymap_entry *ke,
+                              unsigned int *old_keycode)
 {
        struct hid_device *hid = input_get_drvdata(dev);
        struct hid_usage *usage;
-       int old_keycode;
 
-       usage = hidinput_find_key(hid, scancode, 0);
+       usage = hidinput_locate_usage(hid, ke, NULL);
        if (usage) {
-               old_keycode = usage->code;
-               usage->code = keycode;
+               *old_keycode = usage->type == EV_KEY ?
+                               usage->code : KEY_RESERVED;
+               usage->code = ke->keycode;
 
-               clear_bit(old_keycode, dev->keybit);
+               clear_bit(*old_keycode, dev->keybit);
                set_bit(usage->code, dev->keybit);
-               dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-               /* Set the keybit for the old keycode if the old keycode is used
-                * by another key */
-               if (hidinput_find_key (hid, 0, old_keycode))
-                       set_bit(old_keycode, dev->keybit);
+               dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
+                       usage->code, usage->hid);
+
+               /*
+                * Set the keybit for the old keycode if the old keycode is used
+                * by another key
+                */
+               if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
+                       set_bit(*old_keycode, dev->keybit);
 
                return 0;
        }
@@ -835,8 +877,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                        hid->ll_driver->hidinput_input_event;
                                input_dev->open = hidinput_open;
                                input_dev->close = hidinput_close;
-                               input_dev->setkeycode = hidinput_setkeycode;
-                               input_dev->getkeycode = hidinput_getkeycode;
+                               input_dev->setkeycode_new = hidinput_setkeycode;
+                               input_dev->getkeycode_new = hidinput_getkeycode;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
index 97499d0..c357c83 100644 (file)
@@ -399,6 +399,15 @@ config SENSORS_GL520SM
          This driver can also be built as a module.  If so, the module
          will be called gl520sm.
 
+config SENSORS_GPIO_FAN
+       tristate "GPIO fan"
+       depends on GENERIC_GPIO
+       help
+         If you say yes here you get support for fans connected to GPIO lines.
+
+         This driver can also be built as a module.  If so, the module
+         will be called gpio-fan.
+
 config SENSORS_CORETEMP
        tristate "Intel Core/Core2/Atom temperature sensor"
        depends on X86 && PCI && EXPERIMENTAL
@@ -654,6 +663,17 @@ config SENSORS_LTC4245
          This driver can also be built as a module. If so, the module will
          be called ltc4245.
 
+config SENSORS_LTC4261
+       tristate "Linear Technology LTC4261"
+       depends on I2C && EXPERIMENTAL
+       default n
+       help
+         If you say yes here you get support for Linear Technology LTC4261
+         Negative Voltage Hot Swap Controller I2C interface.
+
+         This driver can also be built as a module. If so, the module will
+         be called ltc4261.
+
 config SENSORS_LM95241
        tristate "National Semiconductor LM95241 sensor chip"
        depends on I2C
@@ -1088,26 +1108,6 @@ config SENSORS_ULTRA45
          This driver provides support for the Ultra45 workstation environmental
          sensors.
 
-config SENSORS_HDAPS
-       tristate "IBM Hard Drive Active Protection System (hdaps)"
-       depends on INPUT && X86
-       select INPUT_POLLDEV
-       default n
-       help
-         This driver provides support for the IBM Hard Drive Active Protection
-         System (hdaps), which provides an accelerometer and other misc. data.
-         ThinkPads starting with the R50, T41, and X40 are supported.  The
-         accelerometer data is readable via sysfs.
-
-         This driver also provides an absolute input class device, allowing
-         the laptop to act as a pinball machine-esque joystick.
-
-         If your ThinkPad is not recognized by the driver, please update to latest
-         BIOS. This is especially the case for some R52 ThinkPads.
-
-         Say Y here if you have an applicable laptop and want to experience
-         the awesome power of hdaps.
-
 config SENSORS_LIS3_SPI
        tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
        depends on !ACPI && SPI_MASTER && INPUT
index e3c2484..d30f0f6 100644 (file)
@@ -51,8 +51,8 @@ obj-$(CONFIG_SENSORS_FSCHMD)  += fschmd.o
 obj-$(CONFIG_SENSORS_G760A)    += g760a.o
 obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
+obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
 obj-$(CONFIG_SENSORS_ULTRA45)  += ultra45_env.o
-obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_SENSORS_I5K_AMB)  += i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)   += ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)   += ibmpex.o
@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM93)    += lm93.o
 obj-$(CONFIG_SENSORS_LM95241)  += lm95241.o
 obj-$(CONFIG_SENSORS_LTC4215)  += ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)  += ltc4245.o
+obj-$(CONFIG_SENSORS_LTC4261)  += ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)  += max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
index a23b17a..42de98d 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -280,11 +279,9 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
        case 0x1a:
                dev_warn(dev, "TjMax is assumed as 100 C!\n");
                return 100000;
-               break;
        case 0x17:
        case 0x1c:              /* Atom CPUs */
                return adjust_tjmax(c, id, dev);
-               break;
        default:
                dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
                        " using default TjMax of 100C.\n", c->x86_model);
@@ -292,6 +289,15 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
        }
 }
 
+static void __devinit get_ucode_rev_on_cpu(void *edx)
+{
+       u32 eax;
+
+       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+       sync_core();
+       rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
+}
+
 static int __devinit coretemp_probe(struct platform_device *pdev)
 {
        struct coretemp_data *data;
@@ -327,8 +333,15 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
 
        if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
                /* check for microcode update */
-               rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
-               if (edx < 0x39) {
+               err = smp_call_function_single(data->id, get_ucode_rev_on_cpu,
+                                              &edx, 1);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "Cannot determine microcode revision of "
+                               "CPU#%u (%d)!\n", data->id, err);
+                       err = -ENODEV;
+                       goto exit_free;
+               } else if (edx < 0x39) {
                        err = -ENODEV;
                        dev_err(&pdev->dev,
                                "Errata AE18 not fixed, update BIOS or "
@@ -490,7 +503,7 @@ exit:
        return err;
 }
 
-static void coretemp_device_remove(unsigned int cpu)
+static void __cpuinit coretemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p;
        unsigned int i;
@@ -569,9 +582,8 @@ exit:
 static void __exit coretemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&coretemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
new file mode 100644 (file)
index 0000000..aa701a1
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/hwmon.h>
+#include <linux/gpio.h>
+#include <linux/gpio-fan.h>
+
+struct gpio_fan_data {
+       struct platform_device  *pdev;
+       struct device           *hwmon_dev;
+       struct mutex            lock; /* lock GPIOs operations. */
+       int                     num_ctrl;
+       unsigned                *ctrl;
+       int                     num_speed;
+       struct gpio_fan_speed   *speed;
+       int                     speed_index;
+#ifdef CONFIG_PM
+       int                     resume_speed;
+#endif
+       bool                    pwm_enable;
+       struct gpio_fan_alarm   *alarm;
+       struct work_struct      alarm_work;
+};
+
+/*
+ * Alarm GPIO.
+ */
+
+static void fan_alarm_notify(struct work_struct *ws)
+{
+       struct gpio_fan_data *fan_data =
+               container_of(ws, struct gpio_fan_data, alarm_work);
+
+       sysfs_notify(&fan_data->pdev->dev.kobj, NULL, "fan1_alarm");
+       kobject_uevent(&fan_data->pdev->dev.kobj, KOBJ_CHANGE);
+}
+
+static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
+{
+       struct gpio_fan_data *fan_data = dev_id;
+
+       schedule_work(&fan_data->alarm_work);
+
+       return IRQ_NONE;
+}
+
+static ssize_t show_fan_alarm(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       struct gpio_fan_alarm *alarm = fan_data->alarm;
+       int value = gpio_get_value(alarm->gpio);
+
+       if (alarm->active_low)
+               value = !value;
+
+       return sprintf(buf, "%d\n", value);
+}
+
+static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
+
+static int fan_alarm_init(struct gpio_fan_data *fan_data,
+                         struct gpio_fan_alarm *alarm)
+{
+       int err;
+       int alarm_irq;
+       struct platform_device *pdev = fan_data->pdev;
+
+       fan_data->alarm = alarm;
+
+       err = gpio_request(alarm->gpio, "GPIO fan alarm");
+       if (err)
+               return err;
+
+       err = gpio_direction_input(alarm->gpio);
+       if (err)
+               goto err_free_gpio;
+
+       err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
+       if (err)
+               goto err_free_gpio;
+
+       /*
+        * If the alarm GPIO don't support interrupts, just leave
+        * without initializing the fail notification support.
+        */
+       alarm_irq = gpio_to_irq(alarm->gpio);
+       if (alarm_irq < 0)
+               return 0;
+
+       INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
+       set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
+       err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
+                         "GPIO fan alarm", fan_data);
+       if (err)
+               goto err_free_sysfs;
+
+       return 0;
+
+err_free_sysfs:
+       device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+err_free_gpio:
+       gpio_free(alarm->gpio);
+
+       return err;
+}
+
+static void fan_alarm_free(struct gpio_fan_data *fan_data)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int alarm_irq = gpio_to_irq(fan_data->alarm->gpio);
+
+       if (alarm_irq >= 0)
+               free_irq(alarm_irq, fan_data);
+       device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+       gpio_free(fan_data->alarm->gpio);
+}
+
+/*
+ * Control GPIOs.
+ */
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
+{
+       int i;
+
+       for (i = 0; i < fan_data->num_ctrl; i++)
+               gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1);
+}
+
+static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
+{
+       int i;
+       int ctrl_val = 0;
+
+       for (i = 0; i < fan_data->num_ctrl; i++) {
+               int value;
+
+               value = gpio_get_value(fan_data->ctrl[i]);
+               ctrl_val |= (value << i);
+       }
+       return ctrl_val;
+}
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
+{
+       if (fan_data->speed_index == speed_index)
+               return;
+
+       __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
+       fan_data->speed_index = speed_index;
+}
+
+static int get_fan_speed_index(struct gpio_fan_data *fan_data)
+{
+       int ctrl_val = __get_fan_ctrl(fan_data);
+       int i;
+
+       for (i = 0; i < fan_data->num_speed; i++)
+               if (fan_data->speed[i].ctrl_val == ctrl_val)
+                       return i;
+
+       dev_warn(&fan_data->pdev->dev,
+                "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
+
+       return -EINVAL;
+}
+
+static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
+{
+       struct gpio_fan_speed *speed = fan_data->speed;
+       int i;
+
+       for (i = 0; i < fan_data->num_speed; i++)
+               if (speed[i].rpm >= rpm)
+                       return i;
+
+       return fan_data->num_speed - 1;
+}
+
+static ssize_t show_pwm(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);
+
+       return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long pwm;
+       int speed_index;
+       int ret = count;
+
+       if (strict_strtoul(buf, 10, &pwm) || pwm > 255)
+               return -EINVAL;
+
+       mutex_lock(&fan_data->lock);
+
+       if (!fan_data->pwm_enable) {
+               ret = -EPERM;
+               goto exit_unlock;
+       }
+
+       speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
+       set_fan_speed(fan_data, speed_index);
+
+exit_unlock:
+       mutex_unlock(&fan_data->lock);
+
+       return ret;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->pwm_enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) || val > 1)
+               return -EINVAL;
+
+       if (fan_data->pwm_enable == val)
+               return count;
+
+       mutex_lock(&fan_data->lock);
+
+       fan_data->pwm_enable = val;
+
+       /* Disable manual control mode: set fan at full speed. */
+       if (val == 0)
+               set_fan_speed(fan_data, fan_data->num_speed - 1);
+
+       mutex_unlock(&fan_data->lock);
+
+       return count;
+}
+
+static ssize_t show_pwm_mode(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "0\n");
+}
+
+static ssize_t show_rpm_min(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->speed[0].rpm);
+}
+
+static ssize_t show_rpm_max(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n",
+                      fan_data->speed[fan_data->num_speed - 1].rpm);
+}
+
+static ssize_t show_rpm(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);
+}
+
+static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long rpm;
+       int ret = count;
+
+       if (strict_strtoul(buf, 10, &rpm))
+               return -EINVAL;
+
+       mutex_lock(&fan_data->lock);
+
+       if (!fan_data->pwm_enable) {
+               ret = -EPERM;
+               goto exit_unlock;
+       }
+
+       set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
+
+exit_unlock:
+       mutex_unlock(&fan_data->lock);
+
+       return ret;
+}
+
+static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
+static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+                  show_pwm_enable, set_pwm_enable);
+static DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL);
+static DEVICE_ATTR(fan1_min, S_IRUGO, show_rpm_min, NULL);
+static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
+static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
+static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
+
+static struct attribute *gpio_fan_ctrl_attributes[] = {
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm1_enable.attr,
+       &dev_attr_pwm1_mode.attr,
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan1_target.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan1_max.attr,
+       NULL
+};
+
+static const struct attribute_group gpio_fan_ctrl_group = {
+       .attrs = gpio_fan_ctrl_attributes,
+};
+
+static int fan_ctrl_init(struct gpio_fan_data *fan_data,
+                        struct gpio_fan_platform_data *pdata)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int num_ctrl = pdata->num_ctrl;
+       unsigned *ctrl = pdata->ctrl;
+       int i, err;
+
+       for (i = 0; i < num_ctrl; i++) {
+               err = gpio_request(ctrl[i], "GPIO fan control");
+               if (err)
+                       goto err_free_gpio;
+
+               err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i]));
+               if (err) {
+                       gpio_free(ctrl[i]);
+                       goto err_free_gpio;
+               }
+       }
+
+       err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+       if (err)
+               goto err_free_gpio;
+
+       fan_data->num_ctrl = num_ctrl;
+       fan_data->ctrl = ctrl;
+       fan_data->num_speed = pdata->num_speed;
+       fan_data->speed = pdata->speed;
+       fan_data->pwm_enable = true; /* Enable manual fan speed control. */
+       fan_data->speed_index = get_fan_speed_index(fan_data);
+       if (fan_data->speed_index < 0) {
+               err = -ENODEV;
+               goto err_free_gpio;
+       }
+
+       return 0;
+
+err_free_gpio:
+       for (i = i - 1; i >= 0; i--)
+               gpio_free(ctrl[i]);
+
+       return err;
+}
+
+static void fan_ctrl_free(struct gpio_fan_data *fan_data)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int i;
+
+       sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+       for (i = 0; i < fan_data->num_ctrl; i++)
+               gpio_free(fan_data->ctrl[i]);
+}
+
+/*
+ * Platform driver.
+ */
+
+static ssize_t show_name(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "gpio-fan\n");
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static int __devinit gpio_fan_probe(struct platform_device *pdev)
+{
+       int err;
+       struct gpio_fan_data *fan_data;
+       struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
+
+       if (!pdata)
+               return -EINVAL;
+
+       fan_data = kzalloc(sizeof(struct gpio_fan_data), GFP_KERNEL);
+       if (!fan_data)
+               return -ENOMEM;
+
+       fan_data->pdev = pdev;
+       platform_set_drvdata(pdev, fan_data);
+       mutex_init(&fan_data->lock);
+
+       /* Configure alarm GPIO if available. */
+       if (pdata->alarm) {
+               err = fan_alarm_init(fan_data, pdata->alarm);
+               if (err)
+                       goto err_free_data;
+       }
+
+       /* Configure control GPIOs if available. */
+       if (pdata->ctrl && pdata->num_ctrl > 0) {
+               if (!pdata->speed || pdata->num_speed <= 1) {
+                       err = -EINVAL;
+                       goto err_free_alarm;
+               }
+               err = fan_ctrl_init(fan_data, pdata);
+               if (err)
+                       goto err_free_alarm;
+       }
+
+       err = device_create_file(&pdev->dev, &dev_attr_name);
+       if (err)
+               goto err_free_ctrl;
+
+       /* Make this driver part of hwmon class. */
+       fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(fan_data->hwmon_dev)) {
+               err = PTR_ERR(fan_data->hwmon_dev);
+               goto err_remove_name;
+       }
+
+       dev_info(&pdev->dev, "GPIO fan initialized\n");
+
+       return 0;
+
+err_remove_name:
+       device_remove_file(&pdev->dev, &dev_attr_name);
+err_free_ctrl:
+       if (fan_data->ctrl)
+               fan_ctrl_free(fan_data);
+err_free_alarm:
+       if (fan_data->alarm)
+               fan_alarm_free(fan_data);
+err_free_data:
+       platform_set_drvdata(pdev, NULL);
+       kfree(fan_data);
+
+       return err;
+}
+
+static int __devexit gpio_fan_remove(struct platform_device *pdev)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(fan_data->hwmon_dev);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       if (fan_data->alarm)
+               fan_alarm_free(fan_data);
+       if (fan_data->ctrl)
+               fan_ctrl_free(fan_data);
+       kfree(fan_data);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_fan_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (fan_data->ctrl) {
+               fan_data->resume_speed = fan_data->speed_index;
+               set_fan_speed(fan_data, 0);
+       }
+
+       return 0;
+}
+
+static int gpio_fan_resume(struct platform_device *pdev)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (fan_data->ctrl)
+               set_fan_speed(fan_data, fan_data->resume_speed);
+
+       return 0;
+}
+#else
+#define gpio_fan_suspend NULL
+#define gpio_fan_resume NULL
+#endif
+
+static struct platform_driver gpio_fan_driver = {
+       .probe          = gpio_fan_probe,
+       .remove         = __devexit_p(gpio_fan_remove),
+       .suspend        = gpio_fan_suspend,
+       .resume         = gpio_fan_resume,
+       .driver = {
+               .name   = "gpio-fan",
+       },
+};
+
+static int __init gpio_fan_init(void)
+{
+       return platform_driver_register(&gpio_fan_driver);
+}
+
+static void __exit gpio_fan_exit(void)
+{
+       platform_driver_unregister(&gpio_fan_driver);
+}
+
+module_init(gpio_fan_init);
+module_exit(gpio_fan_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("GPIO FAN driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-fan");
index 36e9575..a56a784 100644 (file)
@@ -146,7 +146,7 @@ int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
 
 static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 {
-       lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data);
+       lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
        printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
 
        return 1;
@@ -154,16 +154,19 @@ static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 
 /* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
  * If the value is negative, the opposite of the hw value is used. */
-static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
-static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
+#define DEFINE_CONV(name, x, y, z)                           \
+       static union axis_conversion lis3lv02d_axis_##name = \
+               { .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
 
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {         \
        .ident = _ident,                                \
@@ -222,7 +225,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
        AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
        AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-       AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
@@ -299,7 +302,10 @@ static int lis3lv02d_add(struct acpi_device *device)
        lis3lv02d_enum_resources(device);
 
        /* If possible use a "standard" axes order */
-       if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+       if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+               printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
+                      lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+       } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
                printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
                                 "using default axes configuration\n");
                lis3_dev.ac = lis3lv02d_axis_normal;
index fc591ae..0cee73a 100644 (file)
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
+#include <linux/slab.h>
 #include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
 #include <asm/atomic.h>
 #include "lis3lv02d.h"
 
 #define MDPS_POLL_INTERVAL 50
 #define MDPS_POLL_MIN     0
 #define MDPS_POLL_MAX     2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK           0
+#define SELFTEST_FAIL         -1
+#define SELFTEST_IRQ          -2
+
+#define IRQ_LINE0             0
+#define IRQ_LINE1             1
+
 /*
  * The sensor can also generate interrupts (DRDY) but it's pretty pointless
  * because they are generated even if the data do not change. So it's better
 #define LIS3_SENSITIVITY_12B           ((LIS3_ACCURACY * 1000) / 1024)
 #define LIS3_SENSITIVITY_8B            (18 * LIS3_ACCURACY)
 
-#define LIS3_DEFAULT_FUZZ              3
-#define LIS3_DEFAULT_FLAT              3
+#define LIS3_DEFAULT_FUZZ_12B          3
+#define LIS3_DEFAULT_FLAT_12B          3
+#define LIS3_DEFAULT_FUZZ_8B           1
+#define LIS3_DEFAULT_FLAT_8B           1
 
 struct lis3lv02d lis3_dev = {
        .misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
@@ -75,6 +89,30 @@ struct lis3lv02d lis3_dev = {
 
 EXPORT_SYMBOL_GPL(lis3_dev);
 
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       if (!ret) {
+               int val = *(int *)kp->arg;
+               if (val < 0)
+                       val = -val;
+               if (!val || val > 3)
+                       return -EINVAL;
+       }
+       return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+       .set = param_set_axis,
+       .get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
 static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
 {
        s8 lo;
@@ -123,9 +161,24 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
        int position[3];
        int i;
 
-       position[0] = lis3->read_data(lis3, OUTX);
-       position[1] = lis3->read_data(lis3, OUTY);
-       position[2] = lis3->read_data(lis3, OUTZ);
+       if (lis3->blkread) {
+               if (lis3_dev.whoami == WAI_12B) {
+                       u16 data[3];
+                       lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s16)le16_to_cpu(data[i]);
+               } else {
+                       u8 data[5];
+                       /* Data: x, dummy, y, dummy, z */
+                       lis3->blkread(lis3, OUTX, 5, data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s8)data[i * 2];
+               }
+       } else {
+               position[0] = lis3->read_data(lis3, OUTX);
+               position[1] = lis3->read_data(lis3, OUTY);
+               position[2] = lis3->read_data(lis3, OUTZ);
+       }
 
        for (i = 0; i < 3; i++)
                position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
@@ -138,6 +191,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
 /* conversion btw sampling rate and the register values */
 static int lis3_12_rates[4] = {40, 160, 640, 2560};
 static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
 
 /* ODR is Output Data Rate */
 static int lis3lv02d_get_odr(void)
@@ -156,6 +210,9 @@ static int lis3lv02d_set_odr(int rate)
        u8 ctrl;
        int i, len, shift;
 
+       if (!rate)
+               return -EINVAL;
+
        lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
        ctrl &= ~lis3_dev.odr_mask;
        len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
@@ -172,19 +229,42 @@ static int lis3lv02d_set_odr(int rate)
 
 static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
 {
-       u8 reg;
+       u8 ctlreg, reg;
        s16 x, y, z;
        u8 selftest;
        int ret;
+       u8 ctrl_reg_data;
+       unsigned char irq_cfg;
 
        mutex_lock(&lis3->mutex);
-       if (lis3_dev.whoami == WAI_12B)
-               selftest = CTRL1_ST;
-       else
-               selftest = CTRL1_STP;
 
-       lis3->read(lis3, CTRL_REG1, &reg);
-       lis3->write(lis3, CTRL_REG1, (reg | selftest));
+       irq_cfg = lis3->irq_cfg;
+       if (lis3_dev.whoami == WAI_8B) {
+               lis3->data_ready_count[IRQ_LINE0] = 0;
+               lis3->data_ready_count[IRQ_LINE1] = 0;
+
+               /* Change interrupt cfg to data ready for selftest */
+               atomic_inc(&lis3_dev.wake_thread);
+               lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+               lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+               lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+                               ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+                               (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+       }
+
+       if (lis3_dev.whoami == WAI_3DC) {
+               ctlreg = CTRL_REG4;
+               selftest = CTRL4_ST0;
+       } else {
+               ctlreg = CTRL_REG1;
+               if (lis3_dev.whoami == WAI_12B)
+                       selftest = CTRL1_ST;
+               else
+                       selftest = CTRL1_STP;
+       }
+
+       lis3->read(lis3, ctlreg, &reg);
+       lis3->write(lis3, ctlreg, (reg | selftest));
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        /* Read directly to avoid axis remap */
@@ -193,7 +273,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
        z = lis3->read_data(lis3, OUTZ);
 
        /* back to normal settings */
-       lis3->write(lis3, CTRL_REG1, reg);
+       lis3->write(lis3, ctlreg, reg);
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        results[0] = x - lis3->read_data(lis3, OUTX);
@@ -201,13 +281,33 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
        results[2] = z - lis3->read_data(lis3, OUTZ);
 
        ret = 0;
+
+       if (lis3_dev.whoami == WAI_8B) {
+               /* Restore original interrupt configuration */
+               atomic_dec(&lis3_dev.wake_thread);
+               lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+               lis3->irq_cfg = irq_cfg;
+
+               if ((irq_cfg & LIS3_IRQ1_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE0] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+
+               if ((irq_cfg & LIS3_IRQ2_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE1] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+       }
+
        if (lis3->pdata) {
                int i;
                for (i = 0; i < 3; i++) {
                        /* Check against selftest acceptance limits */
                        if ((results[i] < lis3->pdata->st_min_limits[i]) ||
                            (results[i] > lis3->pdata->st_max_limits[i])) {
-                               ret = -EIO;
+                               ret = SELFTEST_FAIL;
                                goto fail;
                        }
                }
@@ -219,10 +319,46 @@ fail:
        return ret;
 }
 
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+                              FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+                              CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+                              CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+                              CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+                              FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+                              DD_THSE_L, DD_THSE_H,
+                              CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+       int i;
+       for (i = 0; i < lis3->regs_size; i++)
+               lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+       lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+       int i;
+       if (lis3->regs_stored)
+               for (i = 0; i < lis3->regs_size; i++)
+                       lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
 void lis3lv02d_poweroff(struct lis3lv02d *lis3)
 {
+       if (lis3->reg_ctrl)
+               lis3_context_save(lis3);
        /* disable X,Y,Z axis and power down */
        lis3->write(lis3, CTRL_REG1, 0x00);
+       if (lis3->reg_ctrl)
+               lis3->reg_ctrl(lis3, LIS3_REG_OFF);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
@@ -232,19 +368,24 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
 
        lis3->init(lis3);
 
-       /* LIS3 power on delay is quite long */
-       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
        /*
         * Common configuration
         * BDU: (12 bits sensors only) LSB and MSB values are not updated until
         *      both have been read. So the value read will always be correct.
+        * Set BOOT bit to refresh factory tuning values.
         */
-       if (lis3->whoami ==  WAI_12B) {
-               lis3->read(lis3, CTRL_REG2, &reg);
-               reg |= CTRL2_BDU;
-               lis3->write(lis3, CTRL_REG2, reg);
-       }
+       lis3->read(lis3, CTRL_REG2, &reg);
+       if (lis3->whoami ==  WAI_12B)
+               reg |= CTRL2_BDU | CTRL2_BOOT;
+       else
+               reg |= CTRL2_BOOT_8B;
+       lis3->write(lis3, CTRL_REG2, reg);
+
+       /* LIS3 power on delay is quite long */
+       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+       if (lis3->reg_ctrl)
+               lis3_context_restore(lis3);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
@@ -262,6 +403,27 @@ static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
        mutex_unlock(&lis3_dev.mutex);
 }
 
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
+       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+               atomic_set(&lis3_dev.wake_thread, 1);
+       /*
+        * Update coordinates for the case where poll interval is 0 and
+        * the chip in running purely under interrupt control
+        */
+       lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+       atomic_set(&lis3_dev.wake_thread, 0);
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
+}
+
 static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
 {
        if (!test_bit(0, &lis3_dev.misc_opened))
@@ -277,8 +439,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
        wake_up_interruptible(&lis3_dev.misc_wait);
        kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
 out:
-       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
-           lis3_dev.idev->input->users)
+       if (atomic_read(&lis3_dev.wake_thread))
                return IRQ_WAKE_THREAD;
        return IRQ_HANDLED;
 }
@@ -309,44 +470,41 @@ static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
        mutex_unlock(&lis3->mutex);
 }
 
-static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
 {
-       u8 wu1_src;
-       u8 wu2_src;
-
-       lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
-       lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
+       int dummy;
 
-       wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
-       wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
-
-       /* joystick poll is internally protected by the lis3->mutex. */
-       if (wu1_src || wu2_src)
-               lis3lv02d_joystick_poll(lis3_dev.idev);
+       /* Dummy read to ack interrupt */
+       lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+       lis3->data_ready_count[index]++;
 }
 
 static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
 {
-
        struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
 
-       if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
+       if (irq_cfg == LIS3_IRQ1_CLICK)
                lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE0);
        else
-               lis302dl_interrupt_handle_ff_wu(lis3);
+               lis3lv02d_joystick_poll(lis3->idev);
 
        return IRQ_HANDLED;
 }
 
 static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
 {
-
        struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
 
-       if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
+       if (irq_cfg == LIS3_IRQ2_CLICK)
                lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE1);
        else
-               lis302dl_interrupt_handle_ff_wu(lis3);
+               lis3lv02d_joystick_poll(lis3->idev);
 
        return IRQ_HANDLED;
 }
@@ -356,6 +514,9 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
        if (test_and_set_bit(0, &lis3_dev.misc_opened))
                return -EBUSY; /* already open */
 
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
        atomic_set(&lis3_dev.count, 0);
        return 0;
 }
@@ -364,6 +525,8 @@ static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
 {
        fasync_helper(-1, file, 0, &lis3_dev.async_queue);
        clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
        return 0;
 }
 
@@ -460,6 +623,8 @@ int lis3lv02d_joystick_enable(void)
                return -ENOMEM;
 
        lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+       lis3_dev.idev->open = lis3lv02d_joystick_open;
+       lis3_dev.idev->close = lis3lv02d_joystick_close;
        lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
        lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
        lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
@@ -473,8 +638,16 @@ int lis3lv02d_joystick_enable(void)
 
        set_bit(EV_ABS, input_dev->evbit);
        max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-       fuzz = (LIS3_DEFAULT_FUZZ * lis3_dev.scale) / LIS3_ACCURACY;
-       flat = (LIS3_DEFAULT_FLAT * lis3_dev.scale) / LIS3_ACCURACY;
+       if (lis3_dev.whoami == WAI_12B) {
+               fuzz = LIS3_DEFAULT_FUZZ_12B;
+               flat = LIS3_DEFAULT_FLAT_12B;
+       } else {
+               fuzz = LIS3_DEFAULT_FUZZ_8B;
+               flat = LIS3_DEFAULT_FLAT_8B;
+       }
+       fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+       flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
        input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
        input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
        input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
@@ -512,14 +685,47 @@ void lis3lv02d_joystick_disable(void)
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
 
 /* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+       /*
+        * SYSFS functions are fast visitors so put-call
+        * immediately after the get-call. However, keep
+        * chip running for a while and schedule delayed
+        * suspend. This way periodic sysfs calls doesn't
+        * suffer from relatively long power up time.
+        */
+
+       if (lis3->pm_dev) {
+               pm_runtime_get_sync(lis3->pm_dev);
+               pm_runtime_put_noidle(lis3->pm_dev);
+               pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+       }
+}
+
 static ssize_t lis3lv02d_selftest_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       int result;
        s16 values[3];
 
-       result = lis3lv02d_selftest(&lis3_dev, values);
-       return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
+       static const char ok[] = "OK";
+       static const char fail[] = "FAIL";
+       static const char irq[] = "FAIL_IRQ";
+       const char *res;
+
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       switch (lis3lv02d_selftest(&lis3_dev, values)) {
+       case SELFTEST_FAIL:
+               res = fail;
+               break;
+       case SELFTEST_IRQ:
+               res = irq;
+               break;
+       case SELFTEST_OK:
+       default:
+               res = ok;
+               break;
+       }
+       return sprintf(buf, "%s %d %d %d\n", res,
                values[0], values[1], values[2]);
 }
 
@@ -528,6 +734,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
 {
        int x, y, z;
 
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        mutex_lock(&lis3_dev.mutex);
        lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
        mutex_unlock(&lis3_dev.mutex);
@@ -537,6 +744,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
 static ssize_t lis3lv02d_rate_show(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        return sprintf(buf, "%d\n", lis3lv02d_get_odr());
 }
 
@@ -549,6 +757,7 @@ static ssize_t lis3lv02d_rate_set(struct device *dev,
        if (strict_strtoul(buf, 0, &rate))
                return -EINVAL;
 
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        if (lis3lv02d_set_odr(rate))
                return -EINVAL;
 
@@ -585,6 +794,18 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
 {
        sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
        platform_device_unregister(lis3->pdev);
+       if (lis3->pm_dev) {
+               /* Barrier after the sysfs remove */
+               pm_runtime_barrier(lis3->pm_dev);
+
+               /* SYSFS may have left chip running. Turn off if necessary */
+               if (!pm_runtime_suspended(lis3->pm_dev))
+                       lis3lv02d_poweroff(&lis3_dev);
+
+               pm_runtime_disable(lis3->pm_dev);
+               pm_runtime_set_suspended(lis3->pm_dev);
+       }
+       kfree(lis3->reg_cache);
        return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -616,16 +837,16 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
        if (p->wakeup_flags) {
                dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
                dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-               /* default to 2.5ms for now */
-               dev->write(dev, FF_WU_DURATION_1, 1);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
                ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
        }
 
        if (p->wakeup_flags2) {
                dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
                dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-               /* default to 2.5ms for now */
-               dev->write(dev, FF_WU_DURATION_2, 1);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
                ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
        }
        /* Configure hipass filters */
@@ -635,8 +856,8 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
                err = request_threaded_irq(p->irq2,
                                        NULL,
                                        lis302dl_interrupt_thread2_8b,
-                                       IRQF_TRIGGER_RISING |
-                                       IRQF_ONESHOT,
+                                       IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                                       (p->irq_flags2 & IRQF_TRIGGER_MASK),
                                        DRIVER_NAME, &lis3_dev);
                if (err < 0)
                        printk(KERN_ERR DRIVER_NAME
@@ -652,6 +873,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
 {
        int err;
        irq_handler_t thread_fn;
+       int irq_flags = 0;
 
        dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
 
@@ -664,6 +886,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                dev->odrs = lis3_12_rates;
                dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
                dev->scale = LIS3_SENSITIVITY_12B;
+               dev->regs = lis3_wai12_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
                break;
        case WAI_8B:
                printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
@@ -673,6 +897,17 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                dev->odrs = lis3_8_rates;
                dev->odr_mask = CTRL1_DR;
                dev->scale = LIS3_SENSITIVITY_8B;
+               dev->regs = lis3_wai8_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+               break;
+       case WAI_3DC:
+               printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
+               dev->read_data = lis3lv02d_read_8;
+               dev->mdps_max_val = 128;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+               dev->odrs = lis3_3dc_rates;
+               dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+               dev->scale = LIS3_SENSITIVITY_8B;
                break;
        default:
                printk(KERN_ERR DRIVER_NAME
@@ -680,11 +915,25 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                return -EINVAL;
        }
 
+       dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+                                    sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+       if (dev->reg_cache == NULL) {
+               printk(KERN_ERR DRIVER_NAME "out of memory\n");
+               return -ENOMEM;
+       }
+
        mutex_init(&dev->mutex);
+       atomic_set(&dev->wake_thread, 0);
 
        lis3lv02d_add_fs(dev);
        lis3lv02d_poweron(dev);
 
+       if (dev->pm_dev) {
+               pm_runtime_set_active(dev->pm_dev);
+               pm_runtime_enable(dev->pm_dev);
+       }
+
        if (lis3lv02d_joystick_enable())
                printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
 
@@ -696,8 +945,14 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                if (dev->whoami == WAI_8B)
                        lis3lv02d_8b_configure(dev, p);
 
+               irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+               dev->irq_cfg = p->irq_cfg;
                if (p->irq_cfg)
                        dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+               if (p->default_rate)
+                       lis3lv02d_set_odr(p->default_rate);
        }
 
        /* bail if we did not get an IRQ from the bus layer */
@@ -725,7 +980,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
 
        err = request_threaded_irq(dev->irq, lis302dl_interrupt,
                                thread_fn,
-                               IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                               IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                               irq_flags,
                                DRIVER_NAME, &lis3_dev);
 
        if (err < 0) {
index 8540913..a193958 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
 
 /*
  * This driver tries to support the "digital" accelerometer chips from
@@ -45,6 +46,7 @@ enum lis3_reg {
        CTRL_REG1       = 0x20,
        CTRL_REG2       = 0x21,
        CTRL_REG3       = 0x22,
+       CTRL_REG4       = 0x23,
        HP_FILTER_RESET = 0x23,
        STATUS_REG      = 0x27,
        OUTX_L          = 0x28,
@@ -93,6 +95,7 @@ enum lis3lv02d_reg {
 };
 
 enum lis3_who_am_i {
+       WAI_3DC         = 0x33, /* 8 bits: LIS3DC, HP3DC */
        WAI_12B         = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
        WAI_8B          = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
        WAI_6B          = 0x52, /* 6 bits: LIS331DLF - not supported */
@@ -118,6 +121,13 @@ enum lis3lv02d_ctrl1_8b {
        CTRL1_DR        = 0x80,
 };
 
+enum lis3lv02d_ctrl1_3dc {
+       CTRL1_ODR0      = 0x10,
+       CTRL1_ODR1      = 0x20,
+       CTRL1_ODR2      = 0x40,
+       CTRL1_ODR3      = 0x80,
+};
+
 enum lis3lv02d_ctrl2 {
        CTRL2_DAS       = 0x01,
        CTRL2_SIM       = 0x02,
@@ -129,9 +139,18 @@ enum lis3lv02d_ctrl2 {
        CTRL2_FS        = 0x80, /* Full Scale selection */
 };
 
+enum lis3lv02d_ctrl4_3dc {
+       CTRL4_SIM       = 0x01,
+       CTRL4_ST0       = 0x02,
+       CTRL4_ST1       = 0x04,
+       CTRL4_FS0       = 0x10,
+       CTRL4_FS1       = 0x20,
+};
+
 enum lis302d_ctrl2 {
        HP_FF_WU2       = 0x08,
        HP_FF_WU1       = 0x04,
+       CTRL2_BOOT_8B   = 0x40,
 };
 
 enum lis3lv02d_ctrl3 {
@@ -206,19 +225,33 @@ enum lis3lv02d_click_src_8b {
        CLICK_IA        = 0x40,
 };
 
-struct axis_conversion {
-       s8      x;
-       s8      y;
-       s8      z;
+enum lis3lv02d_reg_state {
+       LIS3_REG_OFF    = 0x00,
+       LIS3_REG_ON     = 0x01,
+};
+
+union axis_conversion {
+       struct {
+               int x, y, z;
+       };
+       int as_array[3];
+
 };
 
 struct lis3lv02d {
        void                    *bus_priv; /* used by the bus layer only */
+       struct device           *pm_dev; /* for pm_runtime purposes */
        int (*init) (struct lis3lv02d *lis3);
        int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
        int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+       int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+       int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
 
        int                     *odrs;     /* Supported output data rates */
+       u8                      *regs;     /* Regs to store / restore */
+       int                     regs_size;
+       u8                      *reg_cache;
+       bool                    regs_stored;
        u8                      odr_mask;  /* ODR bit mask */
        u8                      whoami;    /* indicates measurement precision */
        s16 (*read_data) (struct lis3lv02d *lis3, int reg);
@@ -231,14 +264,18 @@ struct lis3lv02d {
 
        struct input_polled_dev *idev;     /* input device */
        struct platform_device  *pdev;     /* platform device */
+       struct regulator_bulk_data regulators[2];
        atomic_t                count;     /* interrupt count after last read */
-       struct axis_conversion  ac;        /* hw -> logical axis */
+       union axis_conversion   ac;        /* hw -> logical axis */
        int                     mapped_btns[3];
 
        u32                     irq;       /* IRQ number */
        struct fasync_struct    *async_queue; /* queue for the misc device */
        wait_queue_head_t       misc_wait; /* Wait queue for the misc device */
        unsigned long           misc_opened; /* bit0: whether the device is open */
+       int                     data_ready_count[2];
+       atomic_t                wake_thread;
+       unsigned char           irq_cfg;
 
        struct lis3lv02d_platform_data *pdata;  /* for passing board config */
        struct mutex            mutex;     /* Serialize poll and selftest */
index 8e5933b..9f4bae0 100644 (file)
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
 #include "lis3lv02d.h"
 
 #define DRV_NAME       "lis3lv02d_i2c"
 
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+       int ret;
+       if (state == LIS3_REG_OFF) {
+               ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+       } else {
+               ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+               /* Chip needs time to wakeup. Not mentioned in datasheet */
+               usleep_range(10000, 20000);
+       }
+       return ret;
+}
+
 static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
 {
        struct i2c_client *c = lis3->bus_priv;
@@ -46,24 +66,38 @@ static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
        return 0;
 }
 
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+                               u8 *v)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+       return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
 static int lis3_i2c_init(struct lis3lv02d *lis3)
 {
        u8 reg;
        int ret;
 
+       if (lis3->reg_ctrl)
+               lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+       lis3->read(lis3, WHO_AM_I, &reg);
+       if (reg != lis3->whoami)
+               printk(KERN_ERR "lis3: power on failure\n");
+
        /* power up the device */
        ret = lis3->read(lis3, CTRL_REG1, &reg);
        if (ret < 0)
                return ret;
 
-       reg |= CTRL1_PD0;
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
        return lis3->write(lis3, CTRL_REG1, reg);
 }
 
 /* Default axis mapping but it can be overwritten by platform data */
-static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
-                                                    LIS3_DEV_Y,
-                                                    LIS3_DEV_Z };
+static union axis_conversion lis3lv02d_axis_map =
+       { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
 
 static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
@@ -72,6 +106,15 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
        struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
 
        if (pdata) {
+               /* Regulator control is optional */
+               if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+                       lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+               if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+                       (i2c_check_functionality(client->adapter,
+                                               I2C_FUNC_SMBUS_I2C_BLOCK)))
+                       lis3_dev.blkread  = lis3_i2c_blockread;
+
                if (pdata->axis_x)
                        lis3lv02d_axis_map.x = pdata->axis_x;
 
@@ -88,6 +131,16 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
                        goto fail;
        }
 
+       if (lis3_dev.reg_ctrl) {
+               lis3_dev.regulators[0].supply = reg_vdd;
+               lis3_dev.regulators[1].supply = reg_vdd_io;
+               ret = regulator_bulk_get(&client->dev,
+                                       ARRAY_SIZE(lis3_dev.regulators),
+                                       lis3_dev.regulators);
+               if (ret < 0)
+                       goto fail;
+       }
+
        lis3_dev.pdata    = pdata;
        lis3_dev.bus_priv = client;
        lis3_dev.init     = lis3_i2c_init;
@@ -95,10 +148,24 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
        lis3_dev.write    = lis3_i2c_write;
        lis3_dev.irq      = client->irq;
        lis3_dev.ac       = lis3lv02d_axis_map;
+       lis3_dev.pm_dev   = &client->dev;
 
        i2c_set_clientdata(client, &lis3_dev);
+
+       /* Provide power over the init call */
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
        ret = lis3lv02d_init_device(&lis3_dev);
+
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+       if (ret == 0)
+               return 0;
 fail:
+       if (pdata && pdata->release_resources)
+               pdata->release_resources();
        return ret;
 }
 
@@ -111,14 +178,18 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
                pdata->release_resources();
 
        lis3lv02d_joystick_disable();
-       lis3lv02d_poweroff(lis3);
+       lis3lv02d_remove_fs(&lis3_dev);
 
-       return lis3lv02d_remove_fs(&lis3_dev);
+       if (lis3_dev.reg_ctrl)
+               regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+                               lis3_dev.regulators);
+       return 0;
 }
 
 #ifdef CONFIG_PM
-static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lis3lv02d_i2c_suspend(struct device *dev)
 {
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
        if (!lis3->pdata || !lis3->pdata->wakeup_flags)
@@ -126,18 +197,21 @@ static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
        return 0;
 }
 
-static int lis3lv02d_i2c_resume(struct i2c_client *client)
+static int lis3lv02d_i2c_resume(struct device *dev)
 {
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+       /*
+        * pm_runtime documentation says that devices should always
+        * be powered on at resume. Pm_runtime turns them off after system
+        * wide resume is complete.
+        */
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+               pm_runtime_suspended(dev))
                lis3lv02d_poweron(lis3);
-       return 0;
-}
 
-static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
-{
-       lis3lv02d_i2c_suspend(client, PMSG_SUSPEND);
+       return 0;
 }
 #else
 #define lis3lv02d_i2c_suspend  NULL
@@ -145,6 +219,24 @@ static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
 #define lis3lv02d_i2c_shutdown NULL
 #endif
 
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweroff(lis3);
+       return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweron(lis3);
+       return 0;
+}
+
 static const struct i2c_device_id lis3lv02d_id[] = {
        {"lis3lv02d", 0 },
        {}
@@ -152,14 +244,20 @@ static const struct i2c_device_id lis3lv02d_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
 
+static const struct dev_pm_ops lis3_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+                               lis3lv02d_i2c_resume)
+       SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+                          lis3_i2c_runtime_resume,
+                          NULL)
+};
+
 static struct i2c_driver lis3lv02d_i2c_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .pm     = &lis3_pm_ops,
        },
-       .suspend = lis3lv02d_i2c_suspend,
-       .shutdown = lis3lv02d_i2c_shutdown,
-       .resume = lis3lv02d_i2c_resume,
        .probe  = lis3lv02d_i2c_probe,
        .remove = __devexit_p(lis3lv02d_i2c_remove),
        .id_table = lis3lv02d_id,
index b9be5e3..2549de1 100644 (file)
@@ -50,11 +50,12 @@ static int lis3_spi_init(struct lis3lv02d *lis3)
        if (ret < 0)
                return ret;
 
-       reg |= CTRL1_PD0;
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
        return lis3->write(lis3, CTRL_REG1, reg);
 }
 
-static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 };
+static union axis_conversion lis3lv02d_axis_normal =
+       { .as_array = { 1, 2, 3 } };
 
 static int __devinit lis302dl_spi_probe(struct spi_device *spi)
 {
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
new file mode 100644 (file)
index 0000000..2676261
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Driver for Linear Technology LTC4261 I2C Negative Voltage Hot Swap Controller
+ *
+ * Copyright (C) 2010 Ericsson AB.
+ *
+ * Derived from:
+ *
+ *  Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
+ *  Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * Datasheet: http://cds.linear.com/docs/Datasheet/42612fb.pdf
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* chip registers */
+#define LTC4261_STATUS 0x00    /* readonly */
+#define LTC4261_FAULT  0x01
+#define LTC4261_ALERT  0x02
+#define LTC4261_CONTROL        0x03
+#define LTC4261_SENSE_H        0x04
+#define LTC4261_SENSE_L        0x05
+#define LTC4261_ADIN2_H        0x06
+#define LTC4261_ADIN2_L        0x07
+#define LTC4261_ADIN_H 0x08
+#define LTC4261_ADIN_L 0x09
+
+/*
+ * Fault register bits
+ */
+#define FAULT_OV       (1<<0)
+#define FAULT_UV       (1<<1)
+#define FAULT_OC       (1<<2)
+
+struct ltc4261_data {
+       struct device *hwmon_dev;
+
+       struct mutex update_lock;
+       bool valid;
+       unsigned long last_updated;     /* in jiffies */
+
+       /* Registers */
+       u8 regs[10];
+};
+
+static struct ltc4261_data *ltc4261_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ltc4261_data *data = i2c_get_clientdata(client);
+       struct ltc4261_data *ret = data;
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ / 4) || !data->valid) {
+               int i;
+
+               /* Read registers -- 0x00 to 0x09 */
+               for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
+                       int val;
+
+                       val = i2c_smbus_read_byte_data(client, i);
+                       if (unlikely(val < 0)) {
+                               dev_dbg(dev,
+                                       "Failed to read ADC value: error %d",
+                                       val);
+                               ret = ERR_PTR(val);
+                               goto abort;
+                       }
+                       data->regs[i] = val;
+               }
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+abort:
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+/* Return the voltage from the given register in mV or mA */
+static int ltc4261_get_value(struct ltc4261_data *data, u8 reg)
+{
+       u32 val;
+
+       val = (data->regs[reg] << 2) + (data->regs[reg + 1] >> 6);
+
+       switch (reg) {
+       case LTC4261_ADIN_H:
+       case LTC4261_ADIN2_H:
+               /* 2.5mV resolution. Convert to mV. */
+               val = val * 25 / 10;
+               break;
+       case LTC4261_SENSE_H:
+               /*
+                * 62.5uV resolution. Convert to current as measured with
+                * an 1 mOhm sense resistor, in mA. If a different sense
+                * resistor is installed, calculate the actual current by
+                * dividing the reported current by the sense resistor value
+                * in mOhm.
+                */
+               val = val * 625 / 10;
+               break;
+       default:
+               /* If we get here, the developer messed up */
+               WARN_ON_ONCE(1);
+               val = 0;
+               break;
+       }
+
+       return val;
+}
+
+static ssize_t ltc4261_show_value(struct device *dev,
+                                 struct device_attribute *da, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct ltc4261_data *data = ltc4261_update_device(dev);
+       int value;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       value = ltc4261_get_value(data, attr->index);
+       return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t ltc4261_show_bool(struct device *dev,
+                                struct device_attribute *da, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ltc4261_data *data = ltc4261_update_device(dev);
+       u8 fault;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       fault = data->regs[LTC4261_FAULT] & attr->index;
+       if (fault)              /* Clear reported faults in chip register */
+               i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
+}
+
+/*
+ * These macros are used below in constructing device attribute objects
+ * for use with sysfs_create_group() to make a sysfs device file
+ * for each register.
+ */
+
+#define LTC4261_VALUE(name, ltc4261_cmd_idx) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+       ltc4261_show_value, NULL, ltc4261_cmd_idx)
+
+#define LTC4261_BOOL(name, mask) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+       ltc4261_show_bool, NULL, (mask))
+
+/*
+ * Input voltages.
+ */
+LTC4261_VALUE(in1_input, LTC4261_ADIN_H);
+LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
+
+/*
+ * Voltage alarms. The chip has only one set of voltage alarm status bits,
+ * triggered by input voltage alarms. In many designs, those alarms are
+ * associated with the ADIN2 sensor, due to the proximity of the ADIN2 pin
+ * to the OV pin. ADIN2 is, however, not available on all chip variants.
+ * To ensure that the alarm condition is reported to the user, report it
+ * with both voltage sensors.
+ */
+LTC4261_BOOL(in1_min_alarm, FAULT_UV);
+LTC4261_BOOL(in1_max_alarm, FAULT_OV);
+LTC4261_BOOL(in2_min_alarm, FAULT_UV);
+LTC4261_BOOL(in2_max_alarm, FAULT_OV);
+
+/* Currents (via sense resistor) */
+LTC4261_VALUE(curr1_input, LTC4261_SENSE_H);
+
+/* Overcurrent alarm */
+LTC4261_BOOL(curr1_max_alarm, FAULT_OC);
+
+static struct attribute *ltc4261_attributes[] = {
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_max_alarm.dev_attr.attr,
+
+       &sensor_dev_attr_curr1_input.dev_attr.attr,
+       &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+
+       NULL,
+};
+
+static const struct attribute_group ltc4261_group = {
+       .attrs = ltc4261_attributes,
+};
+
+static int ltc4261_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       struct ltc4261_data *data;
+       int ret;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
+
+       if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
+               dev_err(&client->dev, "Failed to read register %d:%02x:%02x\n",
+                       adapter->id, client->addr, LTC4261_STATUS);
+               return -ENODEV;
+       }
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               ret = -ENOMEM;
+               goto out_kzalloc;
+       }
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->update_lock);
+
+       /* Clear faults */
+       i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
+
+       /* Register sysfs hooks */
+       ret = sysfs_create_group(&client->dev.kobj, &ltc4261_group);
+       if (ret)
+               goto out_sysfs_create_group;
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               ret = PTR_ERR(data->hwmon_dev);
+               goto out_hwmon_device_register;
+       }
+
+       return 0;
+
+out_hwmon_device_register:
+       sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+out_sysfs_create_group:
+       kfree(data);
+out_kzalloc:
+       return ret;
+}
+
+static int ltc4261_remove(struct i2c_client *client)
+{
+       struct ltc4261_data *data = i2c_get_clientdata(client);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+
+       kfree(data);
+
+       return 0;
+}
+
+static const struct i2c_device_id ltc4261_id[] = {
+       {"ltc4261", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc4261_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4261_driver = {
+       .driver = {
+                  .name = "ltc4261",
+                  },
+       .probe = ltc4261_probe,
+       .remove = ltc4261_remove,
+       .id_table = ltc4261_id,
+};
+
+static int __init ltc4261_init(void)
+{
+       return i2c_add_driver(&ltc4261_driver);
+}
+
+static void __exit ltc4261_exit(void)
+{
+       i2c_del_driver(&ltc4261_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("LTC4261 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4261_init);
+module_exit(ltc4261_exit);
index f119039..0798210 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -35,6 +34,7 @@
 #include <linux/cpu.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/smp.h>
 
 #define DRVNAME        "pkgtemp"
 
@@ -339,8 +339,7 @@ exit:
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void pkgtemp_device_remove(unsigned int cpu)
+static void __cpuinit pkgtemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p;
        unsigned int i;
@@ -387,12 +386,10 @@ static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block pkgtemp_cpu_notifier __refdata = {
        .notifier_call = pkgtemp_cpu_callback,
 };
-#endif                         /* !CONFIG_HOTPLUG_CPU */
 
 static int __init pkgtemp_init(void)
 {
        int i, err = -ENODEV;
-       struct pdev_entry *p, *n;
 
        /* quick check if we run Intel */
        if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
@@ -402,31 +399,23 @@ static int __init pkgtemp_init(void)
        if (err)
                goto exit;
 
-       for_each_online_cpu(i) {
-               err = pkgtemp_device_add(i);
-               if (err)
-                       goto exit_devices_unreg;
-       }
+       for_each_online_cpu(i)
+               pkgtemp_device_add(i);
+
+#ifndef CONFIG_HOTPLUG_CPU
        if (list_empty(&pdev_list)) {
                err = -ENODEV;
                goto exit_driver_unreg;
        }
+#endif
 
-#ifdef CONFIG_HOTPLUG_CPU
        register_hotcpu_notifier(&pkgtemp_cpu_notifier);
-#endif
        return 0;
 
-exit_devices_unreg:
-       mutex_lock(&pdev_list_mutex);
-       list_for_each_entry_safe(p, n, &pdev_list, list) {
-               platform_device_unregister(p->pdev);
-               list_del(&p->list);
-               kfree(p);
-       }
-       mutex_unlock(&pdev_list_mutex);
+#ifndef CONFIG_HOTPLUG_CPU
 exit_driver_unreg:
        platform_driver_unregister(&pkgtemp_driver);
+#endif
 exit:
        return err;
 }
@@ -434,9 +423,8 @@ exit:
 static void __exit pkgtemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
index ffb793a..ec7fad7 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/jiffies.h>
 #include <linux/hwmon.h>
 #include <linux/sysfs.h>
 #include <linux/hwmon-sysfs.h>
@@ -237,8 +235,7 @@ exit:
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void via_cputemp_device_remove(unsigned int cpu)
+static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p, *n;
        mutex_lock(&pdev_list_mutex);
@@ -272,7 +269,6 @@ static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block via_cputemp_cpu_notifier __refdata = {
        .notifier_call = via_cputemp_cpu_callback,
 };
-#endif                         /* !CONFIG_HOTPLUG_CPU */
 
 static int __init via_cputemp_init(void)
 {
@@ -313,9 +309,7 @@ static int __init via_cputemp_init(void)
                goto exit_driver_unreg;
        }
 
-#ifdef CONFIG_HOTPLUG_CPU
        register_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
        return 0;
 
 exit_devices_unreg:
@@ -335,9 +329,8 @@ exit:
 static void __exit via_cputemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
index 6539ac2..8fcdfba 100644 (file)
@@ -396,6 +396,15 @@ config I2C_IMX
          This driver can also be built as a module.  If so, the module
          will be called i2c-imx.
 
+config I2C_INTEL_MID
+       tristate "Intel Moorestown/Medfield Platform I2C controller"
+       help
+         Say Y here if you have an Intel Moorestown/Medfield platform I2C
+         controller.
+
+         This support is also available as a module. If so, the module
+         will be called i2c-intel-mid.
+
 config I2C_IOP3XX
        tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
        depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
index 033ad41..84cb16a 100644 (file)
@@ -38,6 +38,7 @@ obj-$(CONFIG_I2C_GPIO)                += i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
 obj-$(CONFIG_I2C_IBM_IIC)      += i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IMX)          += i2c-imx.o
+obj-$(CONFIG_I2C_INTEL_MID)    += i2c-intel-mid.o
 obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
 obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
 obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
diff --git a/drivers/i2c/busses/i2c-intel-mid.c b/drivers/i2c/busses/i2c-intel-mid.c
new file mode 100644 (file)
index 0000000..80f70d3
--- /dev/null
@@ -0,0 +1,1135 @@
+/*
+ * Support for Moorestown/Medfield I2C chip
+ *
+ * Copyright (c) 2009 Intel Corporation.
+ * Copyright (c) 2009 Synopsys. Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License, version
+ * 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/io.h>
+
+#define DRIVER_NAME    "i2c-intel-mid"
+#define VERSION                "Version 0.5ac2"
+#define PLATFORM       "Moorestown/Medfield"
+
+/* Tables use: 0 Moorestown, 1 Medfield */
+#define NUM_PLATFORMS  2
+enum platform_enum {
+       MOORESTOWN = 0,
+       MEDFIELD = 1,
+};
+
+enum mid_i2c_status {
+       STATUS_IDLE = 0,
+       STATUS_READ_START,
+       STATUS_READ_IN_PROGRESS,
+       STATUS_READ_SUCCESS,
+       STATUS_WRITE_START,
+       STATUS_WRITE_SUCCESS,
+       STATUS_XFER_ABORT,
+       STATUS_STANDBY
+};
+
+/**
+ * struct intel_mid_i2c_private        - per device I²C context
+ * @adap: core i2c layer adapter information
+ * @dev: device reference for power management
+ * @base: register base
+ * @speed: speed mode for this port
+ * @complete: completion object for transaction wait
+ * @abort: reason for last abort
+ * @rx_buf: pointer into working receive buffer
+ * @rx_buf_len: receive buffer length
+ * @status: adapter state machine
+ * @msg: the message we are currently processing
+ * @platform: the MID device type we are part of
+ * @lock: transaction serialization
+ *
+ * We allocate one of these per device we discover, it holds the core
+ * i2c layer objects and the data we need to track privately.
+ */
+struct intel_mid_i2c_private {
+       struct i2c_adapter adap;
+       struct device *dev;
+       void __iomem *base;
+       int speed;
+       struct completion complete;
+       int abort;
+       u8 *rx_buf;
+       int rx_buf_len;
+       enum mid_i2c_status status;
+       struct i2c_msg *msg;
+       enum platform_enum platform;
+       struct mutex lock;
+};
+
+#define NUM_SPEEDS             3
+
+#define ACTIVE                 0
+#define STANDBY                        1
+
+
+/* Control register */
+#define IC_CON                 0x00
+#define SLV_DIS                        (1 << 6)        /* Disable slave mode */
+#define RESTART                        (1 << 5)        /* Send a Restart condition */
+#define        ADDR_10BIT              (1 << 4)        /* 10-bit addressing */
+#define        STANDARD_MODE           (1 << 1)        /* standard mode */
+#define FAST_MODE              (2 << 1)        /* fast mode */
+#define HIGH_MODE              (3 << 1)        /* high speed mode */
+#define        MASTER_EN               (1 << 0)        /* Master mode */
+
+/* Target address register */
+#define IC_TAR                 0x04
+#define IC_TAR_10BIT_ADDR      (1 << 12)       /* 10-bit addressing */
+#define IC_TAR_SPECIAL         (1 << 11)       /* Perform special I2C cmd */
+#define IC_TAR_GC_OR_START     (1 << 10)       /* 0: Gerneral Call Address */
+                                               /* 1: START BYTE */
+/* Slave Address Register */
+#define IC_SAR                 0x08            /* Not used in Master mode */
+
+/* High Speed Master Mode Code Address Register */
+#define IC_HS_MADDR            0x0c
+
+/* Rx/Tx Data Buffer and Command Register */
+#define IC_DATA_CMD            0x10
+#define IC_RD                  (1 << 8)        /* 1: Read 0: Write */
+
+/* Standard Speed Clock SCL High Count Register */
+#define IC_SS_SCL_HCNT         0x14
+
+/* Standard Speed Clock SCL Low Count Register */
+#define IC_SS_SCL_LCNT         0x18
+
+/* Fast Speed Clock SCL High Count Register */
+#define IC_FS_SCL_HCNT         0x1c
+
+/* Fast Spedd Clock SCL Low Count Register */
+#define IC_FS_SCL_LCNT         0x20
+
+/* High Speed Clock SCL High Count Register */
+#define IC_HS_SCL_HCNT         0x24
+
+/* High Speed Clock SCL Low Count Register */
+#define IC_HS_SCL_LCNT         0x28
+
+/* Interrupt Status Register */
+#define IC_INTR_STAT           0x2c            /* Read only */
+#define R_GEN_CALL             (1 << 11)
+#define R_START_DET            (1 << 10)
+#define R_STOP_DET             (1 << 9)
+#define R_ACTIVITY             (1 << 8)
+#define R_RX_DONE              (1 << 7)
+#define        R_TX_ABRT               (1 << 6)
+#define R_RD_REQ               (1 << 5)
+#define R_TX_EMPTY             (1 << 4)
+#define R_TX_OVER              (1 << 3)
+#define        R_RX_FULL               (1 << 2)
+#define        R_RX_OVER               (1 << 1)
+#define R_RX_UNDER             (1 << 0)
+
+/* Interrupt Mask Register */
+#define IC_INTR_MASK           0x30            /* Read and Write */
+#define M_GEN_CALL             (1 << 11)
+#define M_START_DET            (1 << 10)
+#define M_STOP_DET             (1 << 9)
+#define M_ACTIVITY             (1 << 8)
+#define M_RX_DONE              (1 << 7)
+#define        M_TX_ABRT               (1 << 6)
+#define M_RD_REQ               (1 << 5)
+#define M_TX_EMPTY             (1 << 4)
+#define M_TX_OVER              (1 << 3)
+#define        M_RX_FULL               (1 << 2)
+#define        M_RX_OVER               (1 << 1)
+#define M_RX_UNDER             (1 << 0)
+
+/* Raw Interrupt Status Register */
+#define IC_RAW_INTR_STAT       0x34            /* Read Only */
+#define GEN_CALL               (1 << 11)       /* General call */
+#define START_DET              (1 << 10)       /* (RE)START occured */
+#define STOP_DET               (1 << 9)        /* STOP occured */
+#define ACTIVITY               (1 << 8)        /* Bus busy */
+#define RX_DONE                        (1 << 7)        /* Not used in Master mode */
+#define        TX_ABRT                 (1 << 6)        /* Transmit Abort */
+#define RD_REQ                 (1 << 5)        /* Not used in Master mode */
+#define TX_EMPTY               (1 << 4)        /* TX FIFO <= threshold */
+#define TX_OVER                        (1 << 3)        /* TX FIFO overflow */
+#define        RX_FULL                 (1 << 2)        /* RX FIFO >= threshold */
+#define        RX_OVER                 (1 << 1)        /* RX FIFO overflow */
+#define RX_UNDER               (1 << 0)        /* RX FIFO empty */
+
+/* Receive FIFO Threshold Register */
+#define IC_RX_TL               0x38
+
+/* Transmit FIFO Treshold Register */
+#define IC_TX_TL               0x3c
+
+/* Clear Combined and Individual Interrupt Register */
+#define IC_CLR_INTR            0x40
+#define CLR_INTR               (1 << 0)
+
+/* Clear RX_UNDER Interrupt Register */
+#define IC_CLR_RX_UNDER                0x44
+#define CLR_RX_UNDER           (1 << 0)
+
+/* Clear RX_OVER Interrupt Register */
+#define IC_CLR_RX_OVER         0x48
+#define CLR_RX_OVER            (1 << 0)
+
+/* Clear TX_OVER Interrupt Register */
+#define IC_CLR_TX_OVER         0x4c
+#define CLR_TX_OVER            (1 << 0)
+
+#define IC_CLR_RD_REQ          0x50
+
+/* Clear TX_ABRT Interrupt Register */
+#define IC_CLR_TX_ABRT         0x54
+#define CLR_TX_ABRT            (1 << 0)
+#define IC_CLR_RX_DONE         0x58
+
+/* Clear ACTIVITY Interrupt Register */
+#define IC_CLR_ACTIVITY                0x5c
+#define CLR_ACTIVITY           (1 << 0)
+
+/* Clear STOP_DET Interrupt Register */
+#define IC_CLR_STOP_DET                0x60
+#define CLR_STOP_DET           (1 << 0)
+
+/* Clear START_DET Interrupt Register */
+#define IC_CLR_START_DET       0x64
+#define CLR_START_DET          (1 << 0)
+
+/* Clear GEN_CALL Interrupt Register */
+#define IC_CLR_GEN_CALL                0x68
+#define CLR_GEN_CALL           (1 << 0)
+
+/* Enable Register */
+#define IC_ENABLE              0x6c
+#define ENABLE                 (1 << 0)
+
+/* Status Register */
+#define IC_STATUS              0x70            /* Read Only */
+#define STAT_SLV_ACTIVITY      (1 << 6)        /* Slave not in idle */
+#define STAT_MST_ACTIVITY      (1 << 5)        /* Master not in idle */
+#define STAT_RFF               (1 << 4)        /* RX FIFO Full */
+#define STAT_RFNE              (1 << 3)        /* RX FIFO Not Empty */
+#define STAT_TFE               (1 << 2)        /* TX FIFO Empty */
+#define STAT_TFNF              (1 << 1)        /* TX FIFO Not Full */
+#define STAT_ACTIVITY          (1 << 0)        /* Activity Status */
+
+/* Transmit FIFO Level Register */
+#define IC_TXFLR               0x74            /* Read Only */
+#define TXFLR                  (1 << 0)        /* TX FIFO level */
+
+/* Receive FIFO Level Register */
+#define IC_RXFLR               0x78            /* Read Only */
+#define RXFLR                  (1 << 0)        /* RX FIFO level */
+
+/* Transmit Abort Source Register */
+#define IC_TX_ABRT_SOURCE      0x80
+#define ABRT_SLVRD_INTX                (1 << 15)
+#define ABRT_SLV_ARBLOST       (1 << 14)
+#define ABRT_SLVFLUSH_TXFIFO   (1 << 13)
+#define        ARB_LOST                (1 << 12)
+#define ABRT_MASTER_DIS                (1 << 11)
+#define ABRT_10B_RD_NORSTRT    (1 << 10)
+#define ABRT_SBYTE_NORSTRT     (1 << 9)
+#define ABRT_HS_NORSTRT                (1 << 8)
+#define ABRT_SBYTE_ACKDET      (1 << 7)
+#define ABRT_HS_ACKDET         (1 << 6)
+#define ABRT_GCALL_READ                (1 << 5)
+#define ABRT_GCALL_NOACK       (1 << 4)
+#define ABRT_TXDATA_NOACK      (1 << 3)
+#define ABRT_10ADDR2_NOACK     (1 << 2)
+#define ABRT_10ADDR1_NOACK     (1 << 1)
+#define ABRT_7B_ADDR_NOACK     (1 << 0)
+
+/* Enable Status Register */
+#define IC_ENABLE_STATUS       0x9c
+#define IC_EN                  (1 << 0)        /* I2C in an enabled state */
+
+/* Component Parameter Register 1*/
+#define IC_COMP_PARAM_1                0xf4
+#define APB_DATA_WIDTH         (0x3 << 0)
+
+/* added by xiaolin --begin */
+#define SS_MIN_SCL_HIGH         4000
+#define SS_MIN_SCL_LOW          4700
+#define FS_MIN_SCL_HIGH         600
+#define FS_MIN_SCL_LOW          1300
+#define HS_MIN_SCL_HIGH_100PF   60
+#define HS_MIN_SCL_LOW_100PF    120
+
+#define STANDARD               0
+#define FAST                   1
+#define HIGH                   2
+
+#define NUM_SPEEDS             3
+
+static int speed_mode[6] = {
+       FAST,
+       FAST,
+       FAST,
+       STANDARD,
+       FAST,
+       FAST
+};
+
+static int ctl_num = 6;
+module_param_array(speed_mode, int, &ctl_num, S_IRUGO);
+MODULE_PARM_DESC(speed_mode, "Set the speed of the i2c interface (0-2)");
+
+/**
+ * intel_mid_i2c_disable - Disable I2C controller
+ * @adap: struct pointer to i2c_adapter
+ *
+ * Return Value:
+ * 0           success
+ * -EBUSY      if device is busy
+ * -ETIMEDOUT  if i2c cannot be disabled within the given time
+ *
+ * I2C bus state should be checked prior to disabling the hardware. If bus is
+ * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable
+ * I2C controller.
+ */
+static int intel_mid_i2c_disable(struct i2c_adapter *adap)
+{
+       struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
+       int err = 0;
+       int count = 0;
+       int ret1, ret2;
+       static const u16 delay[NUM_SPEEDS] = {100, 25, 3};
+
+       /* Set IC_ENABLE to 0 */
+       writel(0, i2c->base + IC_ENABLE);
+
+       /* Check if device is busy */
+       dev_dbg(&adap->dev, "mrst i2c disable\n");
+       while ((ret1 = readl(i2c->base + IC_ENABLE_STATUS) & 0x1)
+               || (ret2 = readl(i2c->base + IC_STATUS) & 0x1)) {
+               udelay(delay[i2c->speed]);
+               writel(0, i2c->base + IC_ENABLE);
+               dev_dbg(&adap->dev, "i2c is busy, count is %d speed %d\n",
+                       count, i2c->speed);
+               if (count++ > 10) {
+                       err = -ETIMEDOUT;
+                       break;
+               }
+       }
+
+       /* Clear all interrupts */
+       readl(i2c->base + IC_CLR_INTR);
+       readl(i2c->base + IC_CLR_STOP_DET);
+       readl(i2c->base + IC_CLR_START_DET);
+       readl(i2c->base + IC_CLR_ACTIVITY);
+       readl(i2c->base + IC_CLR_TX_ABRT);
+       readl(i2c->base + IC_CLR_RX_OVER);
+       readl(i2c->base + IC_CLR_RX_UNDER);
+       readl(i2c->base + IC_CLR_TX_OVER);
+       readl(i2c->base + IC_CLR_RX_DONE);
+       readl(i2c->base + IC_CLR_GEN_CALL);
+
+       /* Disable all interupts */
+       writel(0x0000, i2c->base + IC_INTR_MASK);
+
+       return err;
+}
+
+/**
+ * intel_mid_i2c_hwinit - Initialize the I2C hardware registers
+ * @dev: pci device struct pointer
+ *
+ * This function will be called in intel_mid_i2c_probe() before device
+ * registration.
+ *
+ * Return Values:
+ * 0           success
+ * -EBUSY      i2c cannot be disabled
+ * -ETIMEDOUT  i2c cannot be disabled
+ * -EFAULT     If APB data width is not 32-bit wide
+ *
+ * I2C should be disabled prior to other register operation. If failed, an
+ * errno is returned. Mask and Clear all interrpts, this should be done at
+ * first.  Set common registers which will not be modified during normal
+ * transfers, including: controll register, FIFO threshold and clock freq.
+ * Check APB data width at last.
+ */
+static int intel_mid_i2c_hwinit(struct intel_mid_i2c_private *i2c)
+{
+       int err;
+
+       static const u16 hcnt[NUM_PLATFORMS][NUM_SPEEDS] = {
+               { 0x75,  0x15, 0x07 },
+               { 0x04c,  0x10, 0x06 }
+       };
+       static const u16 lcnt[NUM_PLATFORMS][NUM_SPEEDS] = {
+               { 0x7C,  0x21, 0x0E },
+               { 0x053, 0x19, 0x0F }
+       };
+
+       /* Disable i2c first */
+       err = intel_mid_i2c_disable(&i2c->adap);
+       if (err)
+               return err;
+
+       /*
+        * Setup clock frequency and speed mode
+        * Enable restart condition,
+        * enable master FSM, disable slave FSM,
+        * use target address when initiating transfer
+        */
+
+       writel((i2c->speed + 1) << 1 | SLV_DIS | RESTART | MASTER_EN,
+               i2c->base + IC_CON);
+       writel(hcnt[i2c->platform][i2c->speed],
+               i2c->base + (IC_SS_SCL_HCNT + (i2c->speed << 3)));
+       writel(lcnt[i2c->platform][i2c->speed],
+               i2c->base + (IC_SS_SCL_LCNT + (i2c->speed << 3)));
+
+       /* Set tranmit & receive FIFO threshold to zero */
+       writel(0x0, i2c->base + IC_RX_TL);
+       writel(0x0, i2c->base + IC_TX_TL);
+
+       return 0;
+}
+
+/**
+ * intel_mid_i2c_func - Return the supported three I2C operations.
+ * @adapter: i2c_adapter struct pointer
+ */
+static u32 intel_mid_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+/**
+ * intel_mid_i2c_address_neq - To check if the addresses for different i2c messages
+ * are equal.
+ * @p1: first i2c_msg
+ * @p2: second i2c_msg
+ *
+ * Return Values:
+ * 0    if addresses are equal
+ * 1    if not equal
+ *
+ * Within a single transfer, the I2C client may need to send its address more
+ * than once. So a check if the addresses match is needed.
+ */
+static inline bool intel_mid_i2c_address_neq(const struct i2c_msg *p1,
+                                      const struct i2c_msg *p2)
+{
+       if (p1->addr != p2->addr)
+               return 1;
+       if ((p1->flags ^ p2->flags) & I2C_M_TEN)
+               return 1;
+       return 0;
+}
+
+/**
+ * intel_mid_i2c_abort - To handle transfer abortions and print error messages.
+ * @adap: i2c_adapter struct pointer
+ *
+ * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
+ * distingushed. At present, no circumstances have been found out that
+ * multiple errors would be occured simutaneously, so we simply use the
+ * register value directly.
+ *
+ * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
+ * a few extra steps)
+ */
+static void intel_mid_i2c_abort(struct intel_mid_i2c_private *i2c)
+{
+       /* Read about source register */
+       int abort = i2c->abort;
+       struct i2c_adapter *adap = &i2c->adap;
+
+       /* Single transfer error check:
+        * According to databook, TX/RX FIFOs would be flushed when
+        * the abort interrupt occured.
+        */
+       if (abort & ABRT_MASTER_DIS)
+               dev_err(&adap->dev,
+               "initiate master operation with master mode disabled.\n");
+       if (abort & ABRT_10B_RD_NORSTRT)
+               dev_err(&adap->dev,
+       "RESTART disabled and master sent READ cmd in 10-bit addressing.\n");
+
+       if (abort & ABRT_SBYTE_NORSTRT) {
+               dev_err(&adap->dev,
+               "RESTART disabled and user is trying to send START byte.\n");
+               writel(~ABRT_SBYTE_NORSTRT, i2c->base + IC_TX_ABRT_SOURCE);
+               writel(RESTART, i2c->base + IC_CON);
+               writel(~IC_TAR_SPECIAL, i2c->base + IC_TAR);
+       }
+
+       if (abort & ABRT_SBYTE_ACKDET)
+               dev_err(&adap->dev,
+                       "START byte was not acknowledged.\n");
+       if (abort & ABRT_TXDATA_NOACK)
+               dev_dbg(&adap->dev,
+                       "No acknowledgement received from slave.\n");
+       if (abort & ABRT_10ADDR2_NOACK)
+               dev_dbg(&adap->dev,
+       "The 2nd address byte of the 10-bit address was not acknowledged.\n");
+       if (abort & ABRT_10ADDR1_NOACK)
+               dev_dbg(&adap->dev,
+       "The 1st address byte of 10-bit address was not acknowledged.\n");
+       if (abort & ABRT_7B_ADDR_NOACK)
+               dev_dbg(&adap->dev,
+                       "I2C slave device not acknowledged.\n");
+
+       /* Clear TX_ABRT bit */
+       readl(i2c->base + IC_CLR_TX_ABRT);
+       i2c->status = STATUS_XFER_ABORT;
+}
+
+/**
+ * xfer_read - Internal function to implement master read transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0           if the read transfer succeeds
+ * -ETIMEDOUT  if cannot read the "raw" interrupt register
+ * -EINVAL     if a transfer abort occurred
+ *
+ * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "read" operation will be performed if an RX_FULL
+ * interrupt occurred.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to separate between errors and actual data.
+ */
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+       struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
+       int i = length;
+       int err;
+
+       if (length >= 256) {
+               dev_err(&adap->dev,
+                       "I2C FIFO cannot support larger than 256 bytes\n");
+               return -EMSGSIZE;
+       }
+
+       INIT_COMPLETION(i2c->complete);
+
+       readl(i2c->base + IC_CLR_INTR);
+       writel(0x0044, i2c->base + IC_INTR_MASK);
+
+       i2c->status = STATUS_READ_START;
+
+       while (i--)
+               writel(IC_RD, i2c->base + IC_DATA_CMD);
+
+       i2c->status = STATUS_READ_START;
+       err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ);
+       if (!err) {
+               dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n");
+               intel_mid_i2c_hwinit(i2c);
+               return -ETIMEDOUT;
+       }
+       if (i2c->status == STATUS_READ_SUCCESS)
+               return 0;
+       else
+               return -EIO;
+}
+
+/**
+ * xfer_write - Internal function to implement master write transfer.
+ * @adap: i2c_adapter struct pointer
+ * @buf: buffer in i2c_msg
+ * @length: number of bytes to be read
+ *
+ * Return Values:
+ * 0   if the read transfer succeeds
+ * -ETIMEDOUT  if we cannot read the "raw" interrupt register
+ * -EINVAL     if a transfer abort occured
+ *
+ * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
+ * data transfer. The actual "write" operation will be performed when the
+ * RX_FULL interrupt signal occurs.
+ *
+ * Note there may be two interrupt signals captured, one should read
+ * IC_RAW_INTR_STAT to separate between errors and actual data.
+ */
+static int xfer_write(struct i2c_adapter *adap,
+                     unsigned char *buf, int length)
+{
+       struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
+       int i, err;
+
+       if (length >= 256) {
+               dev_err(&adap->dev,
+                       "I2C FIFO cannot support larger than 256 bytes\n");
+               return -EMSGSIZE;
+       }
+
+       INIT_COMPLETION(i2c->complete);
+
+       readl(i2c->base + IC_CLR_INTR);
+       writel(0x0050, i2c->base + IC_INTR_MASK);
+
+       i2c->status = STATUS_WRITE_START;
+       for (i = 0; i < length; i++)
+               writel((u16)(*(buf + i)), i2c->base + IC_DATA_CMD);
+
+       i2c->status = STATUS_WRITE_START;
+       err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ);
+       if (!err) {
+               dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n");
+               intel_mid_i2c_hwinit(i2c);
+               return -ETIMEDOUT;
+       } else {
+               if (i2c->status == STATUS_WRITE_SUCCESS)
+                       return 0;
+               else
+                       return -EIO;
+       }
+}
+
+static int intel_mid_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
+{
+       struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
+       int err;
+       u32 reg;
+       u32 bit_mask;
+       u32 mode;
+
+       /* Disable device first */
+       err = intel_mid_i2c_disable(adap);
+       if (err) {
+               dev_err(&adap->dev,
+                       "Cannot disable i2c controller, timeout\n");
+               return err;
+       }
+
+       mode = (1 + i2c->speed) << 1;
+       /* set the speed mode */
+       reg = readl(i2c->base + IC_CON);
+       if ((reg & 0x06) != mode) {
+               dev_dbg(&adap->dev, "set mode %d\n", i2c->speed);
+               writel((reg & ~0x6) | mode, i2c->base + IC_CON);
+       }
+
+       reg = readl(i2c->base + IC_CON);
+       /* use 7-bit addressing */
+       if (pmsg->flags & I2C_M_TEN) {
+               if ((reg & ADDR_10BIT) != ADDR_10BIT) {
+                       dev_dbg(&adap->dev, "set i2c 10 bit address mode\n");
+                       writel(reg | ADDR_10BIT, i2c->base + IC_CON);
+               }
+       } else {
+               if ((reg & ADDR_10BIT) != 0x0) {
+                       dev_dbg(&adap->dev, "set i2c 7 bit address mode\n");
+                       writel(reg & ~ADDR_10BIT, i2c->base + IC_CON);
+               }
+       }
+       /* enable restart conditions */
+       reg = readl(i2c->base + IC_CON);
+       if ((reg & RESTART) != RESTART) {
+               dev_dbg(&adap->dev, "enable restart conditions\n");
+               writel(reg | RESTART, i2c->base + IC_CON);
+       }
+
+       /* enable master FSM */
+       reg = readl(i2c->base + IC_CON);
+       dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg);
+       writel(reg | MASTER_EN, i2c->base + IC_CON);
+       if ((reg & SLV_DIS) != SLV_DIS) {
+               dev_dbg(&adap->dev, "enable master FSM\n");
+               writel(reg | SLV_DIS, i2c->base + IC_CON);
+               dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg);
+       }
+
+       /* use target address when initiating transfer */
+       reg = readl(i2c->base + IC_TAR);
+       bit_mask = IC_TAR_SPECIAL | IC_TAR_GC_OR_START;
+
+       if ((reg & bit_mask) != 0x0) {
+               dev_dbg(&adap->dev,
+        "WR: use target address when intiating transfer, i2c_tx_target\n");
+               writel(reg & ~bit_mask, i2c->base + IC_TAR);
+       }
+
+       /* set target address to the I2C slave address */
+       dev_dbg(&adap->dev,
+               "set target address to the I2C slave address, addr is %x\n",
+                       pmsg->addr);
+       writel(pmsg->addr | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0),
+               i2c->base + IC_TAR);
+
+       /* Enable I2C controller */
+       writel(ENABLE, i2c->base + IC_ENABLE);
+
+       return 0;
+}
+
+/**
+ * intel_mid_i2c_xfer - Main master transfer routine.
+ * @adap: i2c_adapter struct pointer
+ * @pmsg: i2c_msg struct pointer
+ * @num: number of i2c_msg
+ *
+ * Return Values:
+ * +           number of messages transfered
+ * -ETIMEDOUT  If cannot disable I2C controller or read IC_STATUS
+ * -EINVAL     If the address in i2c_msg is invalid
+ *
+ * This function will be registered in i2c-core and exposed to external
+ * I2C clients.
+ * 1. Disable I2C controller
+ * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT
+ * 3. Check if address in i2c_msg is valid
+ * 4. Enable I2C controller
+ * 5. Perform real transfer (call xfer_read or xfer_write)
+ * 6. Wait until the current transfer is finished (check bus state)
+ * 7. Mask and clear all interrupts
+ */
+static int intel_mid_i2c_xfer(struct i2c_adapter *adap,
+                        struct i2c_msg *pmsg,
+                        int num)
+{
+       struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap);
+       int i, err = 0;
+
+       /* if number of messages equal 0*/
+       if (num == 0)
+               return 0;
+
+       pm_runtime_get(i2c->dev);
+
+       mutex_lock(&i2c->lock);
+       dev_dbg(&adap->dev, "intel_mid_i2c_xfer, process %d msg(s)\n", num);
+       dev_dbg(&adap->dev, "slave address is %x\n", pmsg->addr);
+
+
+       if (i2c->status != STATUS_IDLE) {
+               dev_err(&adap->dev, "Adapter %d in transfer/standby\n",
+                                                               adap->nr);
+               mutex_unlock(&i2c->lock);
+               pm_runtime_put(i2c->dev);
+               return -1;
+       }
+
+
+       for (i = 1; i < num; i++) {
+               /* Message address equal? */
+               if (unlikely(intel_mid_i2c_address_neq(&pmsg[0], &pmsg[i]))) {
+                       dev_err(&adap->dev, "Invalid address in msg[%d]\n", i);
+                       mutex_unlock(&i2c->lock);
+                       pm_runtime_put(i2c->dev);
+                       return -EINVAL;
+               }
+       }
+
+       if (intel_mid_i2c_setup(adap, pmsg)) {
+               mutex_unlock(&i2c->lock);
+               pm_runtime_put(i2c->dev);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num; i++) {
+               i2c->msg = pmsg;
+               i2c->status = STATUS_IDLE;
+               /* Read or Write */
+               if (pmsg->flags & I2C_M_RD) {
+                       dev_dbg(&adap->dev, "I2C_M_RD\n");
+                       err = xfer_read(adap, pmsg->buf, pmsg->len);
+               } else {
+                       dev_dbg(&adap->dev, "I2C_M_WR\n");
+                       err = xfer_write(adap, pmsg->buf, pmsg->len);
+               }
+               if (err < 0)
+                       break;
+               dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i);
+               pmsg++;         /* next message */
+       }
+
+       /* Mask interrupts */
+       writel(0x0000, i2c->base + IC_INTR_MASK);
+       /* Clear all interrupts */
+       readl(i2c->base + IC_CLR_INTR);
+
+       i2c->status = STATUS_IDLE;
+       mutex_unlock(&i2c->lock);
+       pm_runtime_put(i2c->dev);
+
+       return err;
+}
+
+static int intel_mid_i2c_runtime_suspend(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev);
+       struct i2c_adapter *adap = to_i2c_adapter(dev);
+       int err;
+
+       if (i2c->status != STATUS_IDLE)
+               return -1;
+
+       intel_mid_i2c_disable(adap);
+
+       err = pci_save_state(pdev);
+       if (err) {
+               dev_err(dev, "pci_save_state failed\n");
+               return err;
+       }
+
+       err = pci_set_power_state(pdev, PCI_D3hot);
+       if (err) {
+               dev_err(dev, "pci_set_power_state failed\n");
+               return err;
+       }
+       i2c->status = STATUS_STANDBY;
+
+       return 0;
+}
+
+static int intel_mid_i2c_runtime_resume(struct device *dev)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev);
+       int err;
+
+       if (i2c->status != STATUS_STANDBY)
+               return 0;
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       err = pci_enable_device(pdev);
+       if (err) {
+               dev_err(dev, "pci_enable_device failed\n");
+               return err;
+       }
+
+       i2c->status = STATUS_IDLE;
+
+       intel_mid_i2c_hwinit(i2c);
+       return err;
+}
+
+static void i2c_isr_read(struct intel_mid_i2c_private *i2c)
+{
+       struct i2c_msg *msg = i2c->msg;
+       int rx_num;
+       u32 len;
+       u8 *buf;
+
+       if (!(msg->flags & I2C_M_RD))
+               return;
+
+       if (i2c->status != STATUS_READ_IN_PROGRESS) {
+               len = msg->len;
+               buf = msg->buf;
+       } else {
+               len = i2c->rx_buf_len;
+               buf = i2c->rx_buf;
+       }
+
+       rx_num = readl(i2c->base + IC_RXFLR);
+
+       for (; len > 0 && rx_num > 0; len--, rx_num--)
+               *buf++ = readl(i2c->base + IC_DATA_CMD);
+
+       if (len > 0) {
+               i2c->status = STATUS_READ_IN_PROGRESS;
+               i2c->rx_buf_len = len;
+               i2c->rx_buf = buf;
+       } else
+               i2c->status = STATUS_READ_SUCCESS;
+
+       return;
+}
+
+static irqreturn_t intel_mid_i2c_isr(int this_irq, void *dev)
+{
+       struct intel_mid_i2c_private *i2c = dev;
+       u32 stat = readl(i2c->base + IC_INTR_STAT);
+
+       if (!stat)
+               return IRQ_NONE;
+
+       dev_dbg(&i2c->adap.dev, "%s, stat = 0x%x\n", __func__, stat);
+       stat &= 0x54;
+
+       if (i2c->status != STATUS_WRITE_START &&
+           i2c->status != STATUS_READ_START &&
+           i2c->status != STATUS_READ_IN_PROGRESS)
+               goto err;
+
+       if (stat & TX_ABRT)
+               i2c->abort = readl(i2c->base + IC_TX_ABRT_SOURCE);
+
+       readl(i2c->base + IC_CLR_INTR);
+
+       if (stat & TX_ABRT) {
+               intel_mid_i2c_abort(i2c);
+               goto exit;
+       }
+
+       if (stat & RX_FULL) {
+               i2c_isr_read(i2c);
+               goto exit;
+       }
+
+       if (stat & TX_EMPTY) {
+               if (readl(i2c->base + IC_STATUS) & 0x4)
+                       i2c->status = STATUS_WRITE_SUCCESS;
+       }
+
+exit:
+       if (i2c->status == STATUS_READ_SUCCESS ||
+           i2c->status == STATUS_WRITE_SUCCESS ||
+           i2c->status == STATUS_XFER_ABORT) {
+               /* Clear all interrupts */
+               readl(i2c->base + IC_CLR_INTR);
+               /* Mask interrupts */
+               writel(0, i2c->base + IC_INTR_MASK);
+               complete(&i2c->complete);
+       }
+err:
+       return IRQ_HANDLED;
+}
+
+static struct i2c_algorithm intel_mid_i2c_algorithm = {
+       .master_xfer    = intel_mid_i2c_xfer,
+       .functionality  = intel_mid_i2c_func,
+};
+
+
+static const struct dev_pm_ops intel_mid_i2c_pm_ops = {
+       .runtime_suspend = intel_mid_i2c_runtime_suspend,
+       .runtime_resume = intel_mid_i2c_runtime_resume,
+};
+
+/**
+ * intel_mid_i2c_probe - I2C controller initialization routine
+ * @dev: pci device
+ * @id: device id
+ *
+ * Return Values:
+ * 0           success
+ * -ENODEV     If cannot allocate pci resource
+ * -ENOMEM     If the register base remapping failed, or
+ *             if kzalloc failed
+ *
+ * Initialization steps:
+ * 1. Request for PCI resource
+ * 2. Remap the start address of PCI resource to register base
+ * 3. Request for device memory region
+ * 4. Fill in the struct members of intel_mid_i2c_private
+ * 5. Call intel_mid_i2c_hwinit() for hardware initialization
+ * 6. Register I2C adapter in i2c-core
+ */
+static int __devinit intel_mid_i2c_probe(struct pci_dev *dev,
+                                   const struct pci_device_id *id)
+{
+       struct intel_mid_i2c_private *mrst;
+       unsigned long start, len;
+       int err, busnum;
+       void __iomem *base = NULL;
+
+       dev_dbg(&dev->dev, "Get into probe function for I2C\n");
+       err = pci_enable_device(dev);
+       if (err) {
+               dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n",
+                       err);
+               goto exit;
+       }
+
+       /* Determine the address of the I2C area */
+       start = pci_resource_start(dev, 0);
+       len = pci_resource_len(dev, 0);
+       if (!start || len == 0) {
+               dev_err(&dev->dev, "base address not set\n");
+               err = -ENODEV;
+               goto exit;
+       }
+       dev_dbg(&dev->dev, "%s i2c resource start 0x%lx, len=%ld\n",
+               PLATFORM, start, len);
+
+       err = pci_request_region(dev, 0, DRIVER_NAME);
+       if (err) {
+               dev_err(&dev->dev, "failed to request I2C region "
+                       "0x%lx-0x%lx\n", start,
+                       (unsigned long)pci_resource_end(dev, 0));
+               goto exit;
+       }
+
+       base = ioremap_nocache(start, len);
+       if (!base) {
+               dev_err(&dev->dev, "I/O memory remapping failed\n");
+               err = -ENOMEM;
+               goto fail0;
+       }
+
+       /* Allocate the per-device data structure, intel_mid_i2c_private */
+       mrst = kzalloc(sizeof(struct intel_mid_i2c_private), GFP_KERNEL);
+       if (mrst == NULL) {
+               dev_err(&dev->dev, "can't allocate interface\n");
+               err = -ENOMEM;
+               goto fail1;
+       }
+
+       /* Initialize struct members */
+       snprintf(mrst->adap.name, sizeof(mrst->adap.name),
+               "MRST/Medfield I2C at %lx", start);
+       mrst->adap.owner = THIS_MODULE;
+       mrst->adap.algo = &intel_mid_i2c_algorithm;
+       mrst->adap.dev.parent = &dev->dev;
+       mrst->dev = &dev->dev;
+       mrst->base = base;
+       mrst->speed = STANDARD;
+       mrst->abort = 0;
+       mrst->rx_buf_len = 0;
+       mrst->status = STATUS_IDLE;
+
+       pci_set_drvdata(dev, mrst);
+       i2c_set_adapdata(&mrst->adap, mrst);
+
+       mrst->adap.nr = busnum = id->driver_data;
+       if (dev->device <= 0x0804)
+               mrst->platform = MOORESTOWN;
+       else
+               mrst->platform = MEDFIELD;
+
+       dev_dbg(&dev->dev, "I2C%d\n", busnum);
+
+       if (ctl_num > busnum) {
+               if (speed_mode[busnum] < 0 || speed_mode[busnum] >= NUM_SPEEDS)
+                       dev_warn(&dev->dev, "invalid speed %d ignored.\n",
+                                                       speed_mode[busnum]);
+               else
+                       mrst->speed = speed_mode[busnum];
+       }
+
+       /* Initialize i2c controller */
+       err = intel_mid_i2c_hwinit(mrst);
+       if (err < 0) {
+               dev_err(&dev->dev, "I2C interface initialization failed\n");
+               goto fail2;
+       }
+
+       mutex_init(&mrst->lock);
+       init_completion(&mrst->complete);
+
+       /* Clear all interrupts */
+       readl(mrst->base + IC_CLR_INTR);
+       writel(0x0000, mrst->base + IC_INTR_MASK);
+
+       err = request_irq(dev->irq, intel_mid_i2c_isr, IRQF_SHARED,
+                                       mrst->adap.name, mrst);
+       if (err) {
+               dev_err(&dev->dev, "Failed to request IRQ for I2C controller: "
+                       "%s", mrst->adap.name);
+               goto fail2;
+       }
+
+       /* Adapter registration */
+       err = i2c_add_numbered_adapter(&mrst->adap);
+       if (err) {
+               dev_err(&dev->dev, "Adapter %s registration failed\n",
+                       mrst->adap.name);
+               goto fail3;
+       }
+
+       dev_dbg(&dev->dev, "%s I2C bus %d driver bind success.\n",
+               (mrst->platform == MOORESTOWN) ? "Moorestown" : "Medfield",
+               busnum);
+
+       pm_runtime_enable(&dev->dev);
+       return 0;
+
+fail3:
+       free_irq(dev->irq, mrst);
+fail2:
+       pci_set_drvdata(dev, NULL);
+       kfree(mrst);
+fail1:
+       iounmap(base);
+fail0:
+       pci_release_region(dev, 0);
+exit:
+       return err;
+}
+
+static void __devexit intel_mid_i2c_remove(struct pci_dev *dev)
+{
+       struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev);
+       intel_mid_i2c_disable(&mrst->adap);
+       if (i2c_del_adapter(&mrst->adap))
+               dev_err(&dev->dev, "Failed to delete i2c adapter");
+
+       free_irq(dev->irq, mrst);
+       pci_set_drvdata(dev, NULL);
+       iounmap(mrst->base);
+       kfree(mrst);
+       pci_release_region(dev, 0);
+}
+
+static struct pci_device_id intel_mid_i2c_ids[] = {
+       /* Moorestown */
+       { PCI_VDEVICE(INTEL, 0x0802), 0 },
+       { PCI_VDEVICE(INTEL, 0x0803), 1 },
+       { PCI_VDEVICE(INTEL, 0x0804), 2 },
+       /* Medfield */
+       { PCI_VDEVICE(INTEL, 0x0817), 3,},
+       { PCI_VDEVICE(INTEL, 0x0818), 4 },
+       { PCI_VDEVICE(INTEL, 0x0819), 5 },
+       { PCI_VDEVICE(INTEL, 0x082C), 0 },
+       { PCI_VDEVICE(INTEL, 0x082D), 1 },
+       { PCI_VDEVICE(INTEL, 0x082E), 2 },
+       { 0,}
+};
+MODULE_DEVICE_TABLE(pci, intel_mid_i2c_ids);
+
+static struct pci_driver intel_mid_i2c_driver = {
+       .name           = DRIVER_NAME,
+       .id_table       = intel_mid_i2c_ids,
+       .probe          = intel_mid_i2c_probe,
+       .remove         = __devexit_p(intel_mid_i2c_remove),
+};
+
+static int __init intel_mid_i2c_init(void)
+{
+       return pci_register_driver(&intel_mid_i2c_driver);
+}
+
+static void __exit intel_mid_i2c_exit(void)
+{
+       pci_unregister_driver(&intel_mid_i2c_driver);
+}
+
+module_init(intel_mid_i2c_init);
+module_exit(intel_mid_i2c_exit);
+
+MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>");
+MODULE_DESCRIPTION("I2C driver for Moorestown Platform");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION);
index 4f93da3..3cad8fe 100644 (file)
@@ -101,12 +101,12 @@ struct cami2c {
 
 static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
 {
-       ctrl_outl(val, (unsigned long)cam->iobase + reg);
+       __raw_writel(val, (unsigned long)cam->iobase + reg);
 }
 
 static inline unsigned long IN32(struct cami2c *cam, int reg)
 {
-       return ctrl_inl((unsigned long)cam->iobase + reg);
+       return __raw_readl((unsigned long)cam->iobase + reg);
 }
 
 static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
index 598c49a..2707f5e 100644 (file)
@@ -538,15 +538,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
 {
        struct resource *res;
        int ret = -ENXIO;
-       int q, m;
-       int k = 0;
-       int n = 0;
+       int n, k = 0;
 
        while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
                for (n = res->start; hook && n <= res->end; n++) {
                        if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
-                                       dev_name(&dev->dev), dev))
+                                       dev_name(&dev->dev), dev)) {
+                               for (n--; n >= res->start; n--)
+                                       free_irq(n, dev);
+
                                goto rollback;
+                       }
                }
                k++;
        }
@@ -554,16 +556,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
        if (hook)
                return k > 0 ? 0 : -ENOENT;
 
-       k--;
        ret = 0;
 
  rollback:
-       for (q = k; k >= 0; k--) {
-               for (m = n; m >= res->start; m--)
-                       free_irq(m, dev);
+       k--;
+
+       while (k >= 0) {
+               res = platform_get_resource(dev, IORESOURCE_IRQ, k);
+               for (n = res->start; n <= res->end; n++)
+                       free_irq(n, dev);
 
-               res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
-               m = res->end;
+               k--;
        }
 
        return ret;
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
deleted file mode 100644 (file)
index e02096c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-config IEEE1394
-       tristate "Legacy alternative FireWire driver stack"
-       depends on PCI || BROKEN
-       help
-         IEEE 1394 describes a high performance serial bus, which is also
-         known as FireWire(tm) or i.Link(tm) and is used for connecting all
-         sorts of devices (most notably digital video cameras) to your
-         computer.
-
-         If you have FireWire hardware and want to use it, say Y here.  This
-         is the core support only, you will also need to select a driver for
-         your IEEE 1394 adapter.
-
-         To compile this driver as a module, say M here: the module will be
-         called ieee1394.
-
-         NOTE:
-         ieee1394 is superseded by the newer firewire-core driver.  See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_OHCI1394
-       tristate "OHCI-1394 controllers"
-       depends on PCI && IEEE1394
-       help
-         Enable this driver if you have an IEEE 1394 controller based on the
-         OHCI-1394 specification. The current driver is only tested with OHCI
-         chipsets made by Texas Instruments and NEC. Most third-party vendors
-         use one of these chipsets.  It should work with any OHCI-1394
-         compliant card, however.
-
-         To compile this driver as a module, say M here: the module will be
-         called ohci1394.
-
-         NOTE:
-         ohci1394 is superseded by the newer firewire-ohci driver.  See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-         If you want to install firewire-ohci and ohci1394 together, you
-         should configure them only as modules and blacklist the driver(s)
-         which you don't want to have auto-loaded.  Add either
-
-             blacklist ohci1394
-             blacklist video1394
-             blacklist dv1394
-         or
-             blacklist firewire-ohci
-
-         to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
-         depending on your distribution.
-
-comment "PCILynx controller requires I2C"
-       depends on IEEE1394 && I2C=n
-
-config IEEE1394_PCILYNX
-       tristate "PCILynx controller"
-       depends on PCI && IEEE1394 && I2C
-       select I2C_ALGOBIT
-       help
-         Say Y here if you have an IEEE-1394 controller with the Texas
-         Instruments PCILynx chip.  Note: this driver is written for revision
-         2 of this chip and may not work with revision 0.
-
-         To compile this driver as a module, say M here: the module will be
-         called pcilynx.
-
-         Only some old and now very rare PCI and CardBus cards and
-         PowerMacs G3 B&W contain the PCILynx controller.  Therefore
-         almost everybody can say N here.
-
-comment "SBP-2 support (for storage devices) requires SCSI"
-       depends on IEEE1394 && SCSI=n
-
-config IEEE1394_SBP2
-       tristate "Storage devices (SBP-2 protocol)"
-       depends on IEEE1394 && SCSI
-       help
-         This option enables you to use SBP-2 devices connected to an IEEE
-         1394 bus.  SBP-2 devices include storage devices like harddisks and
-         DVD drives, also some other FireWire devices like scanners.
-
-         You should also enable support for disks, CD-ROMs, etc. in the SCSI
-         configuration section.
-
-         To compile this driver as a module, say M here: the module will be
-         called sbp2.
-
-         NOTE:
-         sbp2 is superseded by the newer firewire-sbp2 driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_SBP2_PHYS_DMA
-       bool "Enable replacement for physical DMA in SBP2"
-       depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL
-       help
-         This builds sbp2 for use with non-OHCI host adapters which do not
-         support physical DMA or for when ohci1394 is run with phys_dma=0.
-         Physical DMA is data movement without assistance of the drivers'
-         interrupt handlers.  This option includes the interrupt handlers
-         that are required in absence of this hardware feature.
-
-         This option is buggy and currently broken on some architectures.
-         If unsure, say N.
-
-config IEEE1394_ETH1394_ROM_ENTRY
-       depends on IEEE1394
-       bool
-       default n
-
-config IEEE1394_ETH1394
-       tristate "IP networking over 1394 (experimental)"
-       depends on IEEE1394 && EXPERIMENTAL && INET
-       select IEEE1394_ETH1394_ROM_ENTRY
-       help
-         This driver implements a functional majority of RFC 2734: IPv4 over
-         1394.  It will provide IP connectivity with implementations of RFC
-         2734 found on other operating systems.  It will not communicate with
-         older versions of this driver found in stock kernels prior to 2.6.3.
-         This driver is still considered experimental.  It does not yet support
-         MCAP, therefore multicast support is significantly limited.
-
-         The module is called eth1394 although it does not emulate Ethernet.
-
-         NOTE:
-         eth1394 is superseded by the newer firewire-net driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_RAWIO
-       tristate "raw1394 userspace interface"
-       depends on IEEE1394
-       help
-         This option adds support for the raw1394 device file which enables
-         direct communication of user programs with IEEE 1394 devices
-         (isochronous and asynchronous).  Almost all application programs
-         which access FireWire require this option.
-
-         To compile this driver as a module, say M here: the module will be
-         called raw1394.
-
-         NOTE:
-         raw1394 is superseded by the newer firewire-core driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_VIDEO1394
-       tristate "video1394 userspace interface"
-       depends on IEEE1394 && IEEE1394_OHCI1394
-       help
-         This option adds support for the video1394 device files which enable
-         isochronous communication of user programs with IEEE 1394 devices,
-         especially video capture or export.  This interface is used by all
-         libdc1394 based programs and by several other programs, in addition to
-         the raw1394 interface.  It is generally not required for DV capture.
-
-         To compile this driver as a module, say M here: the module will be
-         called video1394.
-
-         NOTE:
-         video1394 is superseded by the newer firewire-core driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_DV1394
-       tristate "dv1394 userspace interface (deprecated)"
-       depends on IEEE1394 && IEEE1394_OHCI1394
-       help
-         The dv1394 driver is unsupported and may be removed from Linux in a
-         future release.  Its functionality is now provided by either
-         raw1394 or firewire-core together with libraries such as libiec61883.
-
-config IEEE1394_VERBOSEDEBUG
-       bool "Excessive debugging output"
-       depends on IEEE1394
-       help
-         If you say Y here, you will get very verbose debugging logs from the
-         ieee1394 drivers, including sent and received packet headers.  This
-         will quickly result in large amounts of data sent to the system log.
-
-         Say Y if you really need the debugging output.  Everyone else says N.
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
deleted file mode 100644 (file)
index 1f8153b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the Linux IEEE 1394 implementation
-#
-
-ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-                highlevel.o csr.o nodemgr.o dma.o iso.o \
-                csr1212.o config_roms.o
-
-obj-$(CONFIG_IEEE1394) += ieee1394.o
-obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
-obj-$(CONFIG_IEEE1394_OHCI1394) += ohci1394.o
-obj-$(CONFIG_IEEE1394_VIDEO1394) += video1394.o
-obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
-obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
-obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
-obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
-
-obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c
deleted file mode 100644 (file)
index 1b98120..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * ConfigROM  entries
- *
- * Copyright (C) 2004 Ben Collins
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/types.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "csr.h"
-#include "config_roms.h"
-
-struct hpsb_config_rom_entry {
-       const char *name;
-
-       /* Base initialization, called at module load */
-       int (*init)(void);
-
-       /* Cleanup called at module exit */
-       void (*cleanup)(void);
-
-       /* The flag added to host->config_roms */
-       unsigned int flag;
-};
-
-/* The default host entry. This must succeed. */
-int hpsb_default_host_entry(struct hpsb_host *host)
-{
-       struct csr1212_keyval *root;
-       struct csr1212_keyval *vend_id = NULL;
-       struct csr1212_keyval *text = NULL;
-       char csr_name[128];
-       int ret;
-
-       sprintf(csr_name, "Linux - %s", host->driver->name);
-       root = host->csr.rom->root_kv;
-
-       vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
-       text = csr1212_new_string_descriptor_leaf(csr_name);
-
-       if (!vend_id || !text) {
-               if (vend_id)
-                       csr1212_release_keyval(vend_id);
-               if (text)
-                       csr1212_release_keyval(text);
-               csr1212_destroy_csr(host->csr.rom);
-               return -ENOMEM;
-       }
-
-       csr1212_associate_keyval(vend_id, text);
-       csr1212_release_keyval(text);
-       ret = csr1212_attach_keyval_to_directory(root, vend_id);
-       csr1212_release_keyval(vend_id);
-       if (ret != CSR1212_SUCCESS) {
-               csr1212_destroy_csr(host->csr.rom);
-               return -ENOMEM;
-       }
-
-       host->update_config_rom = 1;
-
-       return 0;
-}
-
-
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-#include "eth1394.h"
-
-static struct csr1212_keyval *ip1394_ud;
-
-static int config_rom_ip1394_init(void)
-{
-       struct csr1212_keyval *spec_id = NULL;
-       struct csr1212_keyval *spec_desc = NULL;
-       struct csr1212_keyval *ver = NULL;
-       struct csr1212_keyval *ver_desc = NULL;
-       int ret = -ENOMEM;
-
-       ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
-
-       spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
-                                       ETHER1394_GASP_SPECIFIER_ID);
-       spec_desc = csr1212_new_string_descriptor_leaf("IANA");
-       ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
-                                   ETHER1394_GASP_VERSION);
-       ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
-
-       if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
-               goto ip1394_fail;
-
-       csr1212_associate_keyval(spec_id, spec_desc);
-       csr1212_associate_keyval(ver, ver_desc);
-       if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id)
-                       == CSR1212_SUCCESS &&
-           csr1212_attach_keyval_to_directory(ip1394_ud, ver)
-                       == CSR1212_SUCCESS)
-               ret = 0;
-
-ip1394_fail:
-       if (ret && ip1394_ud) {
-               csr1212_release_keyval(ip1394_ud);
-               ip1394_ud = NULL;
-       }
-
-       if (spec_id)
-               csr1212_release_keyval(spec_id);
-       if (spec_desc)
-               csr1212_release_keyval(spec_desc);
-       if (ver)
-               csr1212_release_keyval(ver);
-       if (ver_desc)
-               csr1212_release_keyval(ver_desc);
-
-       return ret;
-}
-
-static void config_rom_ip1394_cleanup(void)
-{
-       if (ip1394_ud) {
-               csr1212_release_keyval(ip1394_ud);
-               ip1394_ud = NULL;
-       }
-}
-
-int hpsb_config_rom_ip1394_add(struct hpsb_host *host)
-{
-       if (!ip1394_ud)
-               return -ENODEV;
-
-       if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
-                                              ip1394_ud) != CSR1212_SUCCESS)
-               return -ENOMEM;
-
-       host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
-       host->update_config_rom = 1;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add);
-
-void hpsb_config_rom_ip1394_remove(struct hpsb_host *host)
-{
-       csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
-       host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394;
-       host->update_config_rom = 1;
-}
-EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove);
-
-static struct hpsb_config_rom_entry ip1394_entry = {
-       .name           = "ip1394",
-       .init           = config_rom_ip1394_init,
-       .cleanup        = config_rom_ip1394_cleanup,
-       .flag           = HPSB_CONFIG_ROM_ENTRY_IP1394,
-};
-
-#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */
-
-static struct hpsb_config_rom_entry *const config_rom_entries[] = {
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-       &ip1394_entry,
-#endif
-};
-
-/* Initialize all config roms */
-int hpsb_init_config_roms(void)
-{
-       int i, error = 0;
-
-       for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
-               if (config_rom_entries[i]->init()) {
-                       HPSB_ERR("Failed to initialize config rom entry `%s'",
-                                config_rom_entries[i]->name);
-                       error = -1;
-               }
-
-       return error;
-}
-
-/* Cleanup all config roms */
-void hpsb_cleanup_config_roms(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
-               config_rom_entries[i]->cleanup();
-}
diff --git a/drivers/ieee1394/config_roms.h b/drivers/ieee1394/config_roms.h
deleted file mode 100644 (file)
index 1f5cd1f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _IEEE1394_CONFIG_ROMS_H
-#define _IEEE1394_CONFIG_ROMS_H
-
-struct hpsb_host;
-
-int hpsb_default_host_entry(struct hpsb_host *host);
-int hpsb_init_config_roms(void);
-void hpsb_cleanup_config_roms(void);
-
-/* List of flags to check if a host contains a certain extra config rom
- * entry. Available in the host->config_roms member. */
-#define HPSB_CONFIG_ROM_ENTRY_IP1394           0x00000001
-
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-int hpsb_config_rom_ip1394_add(struct hpsb_host *host);
-void hpsb_config_rom_ip1394_remove(struct hpsb_host *host);
-#endif
-
-#endif /* _IEEE1394_CONFIG_ROMS_H */
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
deleted file mode 100644 (file)
index d696f69..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * CSR implementation, iso/bus manager implementation.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *               2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        configuration ROM manipulation
- *
- */
-
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/param.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-
-#include "csr1212.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "highlevel.h"
-#include "ieee1394_core.h"
-
-/* Module Parameters */
-/* this module parameter can be used to disable mapping of the FCP registers */
-
-static int fcp = 1;
-module_param(fcp, int, 0444);
-MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
-
-static struct csr1212_keyval *node_cap = NULL;
-
-static void add_host(struct hpsb_host *host);
-static void remove_host(struct hpsb_host *host);
-static void host_reset(struct hpsb_host *host);
-static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                    u64 addr, size_t length, u16 fl);
-static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                    u64 addr, size_t length, u16 flags);
-static int write_regs(struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                    u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl);
-static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
-                      u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl);
-static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                          u64 addr, size_t length, u16 fl);
-static u64 allocate_addr_range(u64 size, u32 alignment, void *__host);
-static void release_addr_range(u64 addr, void *__host);
-
-static struct hpsb_highlevel csr_highlevel = {
-       .name =         "standard registers",
-       .add_host =     add_host,
-       .remove_host =  remove_host,
-       .host_reset =   host_reset,
-};
-
-static const struct hpsb_address_ops map_ops = {
-       .read = read_maps,
-};
-
-static const struct hpsb_address_ops fcp_ops = {
-       .write = write_fcp,
-};
-
-static const struct hpsb_address_ops reg_ops = {
-       .read = read_regs,
-       .write = write_regs,
-       .lock = lock_regs,
-       .lock64 = lock64_regs,
-};
-
-static const struct hpsb_address_ops config_rom_ops = {
-       .read = read_config_rom,
-};
-
-struct csr1212_bus_ops csr_bus_ops = {
-       .allocate_addr_range =  allocate_addr_range,
-       .release_addr =         release_addr_range,
-};
-
-
-static u16 csr_crc16(unsigned *data, int length)
-{
-        int check=0, i;
-        int shift, sum, next=0;
-
-        for (i = length; i; i--) {
-                for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
-                        sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;
-                        next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-                }
-                check = next & 0xffff;
-                data++;
-        }
-
-        return check;
-}
-
-static void host_reset(struct hpsb_host *host)
-{
-        host->csr.state &= 0x300;
-
-        host->csr.bus_manager_id = 0x3f;
-        host->csr.bandwidth_available = 4915;
-       host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
-        host->csr.channels_available_lo = ~0;
-       host->csr.broadcast_channel = 0x80000000 | 31;
-
-       if (host->is_irm) {
-               if (host->driver->hw_csr_reg) {
-                       host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
-               }
-       }
-
-        host->csr.node_ids = host->node_id << 16;
-
-        if (!host->is_root) {
-                /* clear cmstr bit */
-                host->csr.state &= ~0x100;
-        }
-
-       be32_add_cpu(&host->csr.topology_map[1], 1);
-        host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
-                                                | host->selfid_count);
-        host->csr.topology_map[0] =
-                cpu_to_be32((host->selfid_count + 2) << 16
-                            | csr_crc16(host->csr.topology_map + 1,
-                                        host->selfid_count + 2));
-
-       be32_add_cpu(&host->csr.speed_map[1], 1);
-        host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
-                                             | csr_crc16(host->csr.speed_map+1,
-                                                         0x3f1));
-}
-
-/*
- * HI == seconds (bits 0:2)
- * LO == fractions of a second in units of 125usec (bits 19:31)
- *
- * Convert SPLIT_TIMEOUT to jiffies.
- * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms.
- */
-static inline void calculate_expire(struct csr_control *csr)
-{
-       unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 +
-                            (csr->split_timeout_lo >> 19) * 125;
-
-       csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000);
-       HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
-}
-
-
-static void add_host(struct hpsb_host *host)
-{
-       struct csr1212_keyval *root;
-       quadlet_t bus_info[CSR_BUS_INFO_SIZE];
-
-       hpsb_register_addrspace(&csr_highlevel, host, &reg_ops,
-                               CSR_REGISTER_BASE,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM);
-       hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
-       if (fcp) {
-               hpsb_register_addrspace(&csr_highlevel, host, &fcp_ops,
-                                       CSR_REGISTER_BASE + CSR_FCP_COMMAND,
-                                       CSR_REGISTER_BASE + CSR_FCP_END);
-       }
-       hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
-                               CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
-                               CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
-       hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
-                               CSR_REGISTER_BASE + CSR_SPEED_MAP,
-                               CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
-
-        spin_lock_init(&host->csr.lock);
-
-        host->csr.state                 = 0;
-        host->csr.node_ids              = 0;
-        host->csr.split_timeout_hi      = 0;
-        host->csr.split_timeout_lo      = 800 << 19;
-       calculate_expire(&host->csr);
-        host->csr.cycle_time            = 0;
-        host->csr.bus_time              = 0;
-        host->csr.bus_manager_id        = 0x3f;
-        host->csr.bandwidth_available   = 4915;
-       host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
-        host->csr.channels_available_lo = ~0;
-       host->csr.broadcast_channel = 0x80000000 | 31;
-
-       if (host->is_irm) {
-               if (host->driver->hw_csr_reg) {
-                       host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
-               }
-       }
-
-       if (host->csr.max_rec >= 9)
-               host->csr.max_rom = 2;
-       else if (host->csr.max_rec >= 5)
-               host->csr.max_rom = 1;
-       else
-               host->csr.max_rom = 0;
-
-       host->csr.generation = 2;
-
-       bus_info[1] = IEEE1394_BUSID_MAGIC;
-       bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) |
-                                 (1 << CSR_CMC_SHIFT) |
-                                 (1 << CSR_ISC_SHIFT) |
-                                 (0 << CSR_BMC_SHIFT) |
-                                 (0 << CSR_PMC_SHIFT) |
-                                 (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
-                                 (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
-                                 (host->csr.max_rom << CSR_MAX_ROM_SHIFT) |
-                                 (host->csr.generation << CSR_GENERATION_SHIFT) |
-                                 host->csr.lnk_spd);
-
-       bus_info[3] = cpu_to_be32(host->csr.guid_hi);
-       bus_info[4] = cpu_to_be32(host->csr.guid_lo);
-
-       /* The hardware copy of the bus info block will be set later when a
-        * bus reset is issued. */
-
-       csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom);
-
-       root = host->csr.rom->root_kv;
-
-       if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) {
-               HPSB_ERR("Failed to attach Node Capabilities to root directory");
-       }
-
-       host->update_config_rom = 1;
-}
-
-static void remove_host(struct hpsb_host *host)
-{
-       quadlet_t bus_info[CSR_BUS_INFO_SIZE];
-
-       bus_info[1] = IEEE1394_BUSID_MAGIC;
-       bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) |
-                                 (0 << CSR_CMC_SHIFT) |
-                                 (0 << CSR_ISC_SHIFT) |
-                                 (0 << CSR_BMC_SHIFT) |
-                                 (0 << CSR_PMC_SHIFT) |
-                                 (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
-                                 (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
-                                 (0 << CSR_MAX_ROM_SHIFT) |
-                                 (0 << CSR_GENERATION_SHIFT) |
-                                 host->csr.lnk_spd);
-
-       bus_info[3] = cpu_to_be32(host->csr.guid_hi);
-       bus_info[4] = cpu_to_be32(host->csr.guid_lo);
-
-       csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap);
-
-       csr1212_init_local_csr(host->csr.rom, bus_info, 0);
-       host->update_config_rom = 1;
-}
-
-
-int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
-       size_t buffersize, unsigned char rom_version)
-{
-       unsigned long flags;
-       int ret;
-
-       HPSB_NOTICE("hpsb_update_config_rom() is deprecated");
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-       if (rom_version != host->csr.generation)
-                ret = -1;
-       else if (buffersize > host->csr.rom->cache_head->size)
-               ret = -2;
-        else {
-               /* Just overwrite the generated ConfigROM image with new data,
-                * it can be regenerated later. */
-               memcpy(host->csr.rom->cache_head->data, new_rom, buffersize);
-               host->csr.rom->cache_head->len = buffersize;
-
-               if (host->driver->set_hw_config_rom)
-                       host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
-               /* Increment the generation number to keep some sort of sync
-                * with the newer ConfigROM manipulation method. */
-               host->csr.generation++;
-               if (host->csr.generation > 0xf || host->csr.generation < 2)
-                       host->csr.generation = 2;
-               ret=0;
-        }
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-        return ret;
-}
-
-
-/* Read topology / speed maps and configuration ROM */
-static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                     u64 addr, size_t length, u16 fl)
-{
-       unsigned long flags;
-        int csraddr = addr - CSR_REGISTER_BASE;
-        const char *src;
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-
-       if (csraddr < CSR_SPEED_MAP) {
-                src = ((char *)host->csr.topology_map) + csraddr
-                        - CSR_TOPOLOGY_MAP;
-        } else {
-                src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
-        }
-
-        memcpy(buffer, src, length);
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-        return RCODE_COMPLETE;
-}
-
-
-#define out if (--length == 0) break
-
-static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                     u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-        int oldcycle;
-        quadlet_t ret;
-
-        if ((csraddr | length) & 0x3)
-                return RCODE_TYPE_ERROR;
-
-        length /= 4;
-
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-                *(buf++) = cpu_to_be32(host->csr.state);
-                out;
-        case CSR_STATE_SET:
-                *(buf++) = cpu_to_be32(host->csr.state);
-                out;
-        case CSR_NODE_IDS:
-                *(buf++) = cpu_to_be32(host->csr.node_ids);
-                out;
-
-        case CSR_RESET_START:
-                return RCODE_TYPE_ERROR;
-
-                /* address gap - handled by default below */
-
-        case CSR_SPLIT_TIMEOUT_HI:
-                *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);
-                out;
-        case CSR_SPLIT_TIMEOUT_LO:
-                *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_CYCLE_TIME:
-                oldcycle = host->csr.cycle_time;
-                host->csr.cycle_time =
-                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-
-                if (oldcycle > host->csr.cycle_time) {
-                        /* cycle time wrapped around */
-                        host->csr.bus_time += 1 << 7;
-                }
-                *(buf++) = cpu_to_be32(host->csr.cycle_time);
-                out;
-        case CSR_BUS_TIME:
-                oldcycle = host->csr.cycle_time;
-                host->csr.cycle_time =
-                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-
-                if (oldcycle > host->csr.cycle_time) {
-                        /* cycle time wrapped around */
-                        host->csr.bus_time += (1 << 7);
-                }
-                *(buf++) = cpu_to_be32(host->csr.bus_time
-                                       | (host->csr.cycle_time >> 25));
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUS_MANAGER_ID:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 0, 0, 0);
-                else
-                        ret = host->csr.bus_manager_id;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_BANDWIDTH_AVAILABLE:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 1, 0, 0);
-                else
-                        ret = host->csr.bandwidth_available;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_CHANNELS_AVAILABLE_HI:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 2, 0, 0);
-                else
-                        ret = host->csr.channels_available_hi;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_CHANNELS_AVAILABLE_LO:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 3, 0, 0);
-                else
-                        ret = host->csr.channels_available_lo;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-
-       case CSR_BROADCAST_CHANNEL:
-               *(buf++) = cpu_to_be32(host->csr.broadcast_channel);
-               out;
-
-                /* address gap to end - fall through to default */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-static int write_regs(struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-
-        if ((csraddr | length) & 0x3)
-                return RCODE_TYPE_ERROR;
-
-        length /= 4;
-
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-                /* FIXME FIXME FIXME */
-                printk("doh, someone wants to mess with state clear\n");
-                out;
-        case CSR_STATE_SET:
-                printk("doh, someone wants to mess with state set\n");
-                out;
-
-        case CSR_NODE_IDS:
-                host->csr.node_ids &= NODE_MASK << 16;
-                host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
-                host->node_id = host->csr.node_ids >> 16;
-                host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);
-                out;
-
-        case CSR_RESET_START:
-                /* FIXME - perform command reset */
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_SPLIT_TIMEOUT_HI:
-                host->csr.split_timeout_hi =
-                        be32_to_cpu(*(data++)) & 0x00000007;
-               calculate_expire(&host->csr);
-                out;
-        case CSR_SPLIT_TIMEOUT_LO:
-                host->csr.split_timeout_lo =
-                        be32_to_cpu(*(data++)) & 0xfff80000;
-               calculate_expire(&host->csr);
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_CYCLE_TIME:
-                /* should only be set by cycle start packet, automatically */
-                host->csr.cycle_time = be32_to_cpu(*data);
-                host->driver->devctl(host, SET_CYCLE_COUNTER,
-                                       be32_to_cpu(*(data++)));
-                out;
-        case CSR_BUS_TIME:
-                host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80;
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUS_MANAGER_ID:
-        case CSR_BANDWIDTH_AVAILABLE:
-        case CSR_CHANNELS_AVAILABLE_HI:
-        case CSR_CHANNELS_AVAILABLE_LO:
-                /* these are not writable, only lockable */
-                return RCODE_TYPE_ERROR;
-
-       case CSR_BROADCAST_CHANNEL:
-               /* only the valid bit can be written */
-               host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000)
-                        | (be32_to_cpu(*data) & 0x40000000);
-               out;
-
-                /* address gap to end - fall through */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-#undef out
-
-
-static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                     u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-        unsigned long flags;
-        quadlet_t *regptr = NULL;
-
-        if (csraddr & 0x3)
-               return RCODE_TYPE_ERROR;
-
-        if (csraddr < CSR_BUS_MANAGER_ID || csraddr > CSR_CHANNELS_AVAILABLE_LO
-            || extcode != EXTCODE_COMPARE_SWAP)
-                goto unsupported_lockreq;
-
-        data = be32_to_cpu(data);
-        arg = be32_to_cpu(arg);
-
-       /* Is somebody releasing the broadcast_channel on us? */
-       if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) {
-               /* Note: this is may not be the right way to handle
-                * the problem, so we should look into the proper way
-                * eventually. */
-               HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
-                         "broadcast channel 31.  Ignoring.",
-                         NODE_BUS_ARGS(host, nodeid));
-
-               data &= ~0x1;   /* keep broadcast channel allocated */
-       }
-
-        if (host->driver->hw_csr_reg) {
-                quadlet_t old;
-
-                old = host->driver->
-                        hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
-                                   data, arg);
-
-                *store = cpu_to_be32(old);
-                return RCODE_COMPLETE;
-        }
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-
-        switch (csraddr) {
-        case CSR_BUS_MANAGER_ID:
-                regptr = &host->csr.bus_manager_id;
-               *store = cpu_to_be32(*regptr);
-               if (*regptr == arg)
-                       *regptr = data;
-                break;
-
-        case CSR_BANDWIDTH_AVAILABLE:
-        {
-                quadlet_t bandwidth;
-                quadlet_t old;
-                quadlet_t new;
-
-                regptr = &host->csr.bandwidth_available;
-                old = *regptr;
-
-                /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */
-                if (arg > 0x1fff) {
-                        *store = cpu_to_be32(old);     /* change nothing */
-                       break;
-                }
-                data &= 0x1fff;
-                if (arg >= data) {
-                        /* allocate bandwidth */
-                        bandwidth = arg - data;
-                        if (old >= bandwidth) {
-                                new = old - bandwidth;
-                                *store = cpu_to_be32(arg);
-                                *regptr = new;
-                        } else {
-                                *store = cpu_to_be32(old);
-                        }
-                } else {
-                        /* deallocate bandwidth */
-                        bandwidth = data - arg;
-                        if (old + bandwidth < 0x2000) {
-                                new = old + bandwidth;
-                                *store = cpu_to_be32(arg);
-                                *regptr = new;
-                        } else {
-                                *store = cpu_to_be32(old);
-                        }
-                }
-                break;
-        }
-
-        case CSR_CHANNELS_AVAILABLE_HI:
-        {
-                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
-                quadlet_t affected_channels = arg ^ data;
-
-                regptr = &host->csr.channels_available_hi;
-
-                if ((arg & affected_channels) == (*regptr & affected_channels)) {
-                        *regptr ^= affected_channels;
-                        *store = cpu_to_be32(arg);
-                } else {
-                        *store = cpu_to_be32(*regptr);
-                }
-
-                break;
-        }
-
-        case CSR_CHANNELS_AVAILABLE_LO:
-        {
-                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
-                quadlet_t affected_channels = arg ^ data;
-
-                regptr = &host->csr.channels_available_lo;
-
-                if ((arg & affected_channels) == (*regptr & affected_channels)) {
-                        *regptr ^= affected_channels;
-                        *store = cpu_to_be32(arg);
-                } else {
-                        *store = cpu_to_be32(*regptr);
-                }
-                break;
-        }
-        }
-
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-
-        return RCODE_COMPLETE;
-
- unsupported_lockreq:
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-        case CSR_STATE_SET:
-        case CSR_RESET_START:
-        case CSR_NODE_IDS:
-        case CSR_SPLIT_TIMEOUT_HI:
-        case CSR_SPLIT_TIMEOUT_LO:
-        case CSR_CYCLE_TIME:
-        case CSR_BUS_TIME:
-       case CSR_BROADCAST_CHANNEL:
-                return RCODE_TYPE_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented - fall through */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-}
-
-static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
-                      u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl)
-{
-       int csraddr = addr - CSR_REGISTER_BASE;
-       unsigned long flags;
-
-       data = be64_to_cpu(data);
-       arg = be64_to_cpu(arg);
-
-       if (csraddr & 0x3)
-               return RCODE_TYPE_ERROR;
-
-       if (csraddr != CSR_CHANNELS_AVAILABLE
-           || extcode != EXTCODE_COMPARE_SWAP)
-               goto unsupported_lock64req;
-
-       /* Is somebody releasing the broadcast_channel on us? */
-       if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) {
-               /* Note: this is may not be the right way to handle
-                * the problem, so we should look into the proper way
-                 * eventually. */
-               HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
-                         "broadcast channel 31.  Ignoring.",
-                         NODE_BUS_ARGS(host, nodeid));
-
-               data &= ~0x100000000ULL;        /* keep broadcast channel allocated */
-       }
-
-       if (host->driver->hw_csr_reg) {
-               quadlet_t data_hi, data_lo;
-               quadlet_t arg_hi, arg_lo;
-               quadlet_t old_hi, old_lo;
-
-               data_hi = data >> 32;
-               data_lo = data & 0xFFFFFFFF;
-               arg_hi = arg >> 32;
-               arg_lo = arg & 0xFFFFFFFF;
-
-               old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
-                                                  data_hi, arg_hi);
-
-               old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2,
-                                                  data_lo, arg_lo);
-
-               *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo);
-       } else {
-               octlet_t old;
-               octlet_t affected_channels = arg ^ data;
-
-               spin_lock_irqsave(&host->csr.lock, flags);
-
-               old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo;
-
-               if ((arg & affected_channels) == (old & affected_channels)) {
-                       host->csr.channels_available_hi ^= (affected_channels >> 32);
-                       host->csr.channels_available_lo ^= (affected_channels & 0xffffffff);
-                       *store = cpu_to_be64(arg);
-               } else {
-                       *store = cpu_to_be64(old);
-               }
-
-               spin_unlock_irqrestore(&host->csr.lock, flags);
-       }
-
-       /* Is somebody erroneously releasing the broadcast_channel on us? */
-       if (host->csr.channels_available_hi & 0x1)
-               host->csr.channels_available_hi &= ~0x1;
-
-       return RCODE_COMPLETE;
-
- unsupported_lock64req:
-       switch (csraddr) {
-       case CSR_STATE_CLEAR:
-       case CSR_STATE_SET:
-       case CSR_RESET_START:
-       case CSR_NODE_IDS:
-       case CSR_SPLIT_TIMEOUT_HI:
-       case CSR_SPLIT_TIMEOUT_LO:
-       case CSR_CYCLE_TIME:
-       case CSR_BUS_TIME:
-       case CSR_BUS_MANAGER_ID:
-       case CSR_BROADCAST_CHANNEL:
-       case CSR_BUSY_TIMEOUT:
-       case CSR_BANDWIDTH_AVAILABLE:
-               return RCODE_TYPE_ERROR;
-
-       default:
-               return RCODE_ADDRESS_ERROR;
-       }
-}
-
-static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-
-        if (length > 512)
-                return RCODE_TYPE_ERROR;
-
-        switch (csraddr) {
-        case CSR_FCP_COMMAND:
-                highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length);
-                break;
-        case CSR_FCP_RESPONSE:
-                highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length);
-                break;
-        default:
-                return RCODE_TYPE_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                          u64 addr, size_t length, u16 fl)
-{
-       u32 offset = addr - CSR1212_REGISTER_SPACE_BASE;
-
-       if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS)
-               return RCODE_COMPLETE;
-       else
-               return RCODE_ADDRESS_ERROR;
-}
-
-static u64 allocate_addr_range(u64 size, u32 alignment, void *__host)
-{
-       struct hpsb_host *host = (struct hpsb_host*)__host;
-
-       return hpsb_allocate_and_register_addrspace(&csr_highlevel,
-                                                   host,
-                                                   &config_rom_ops,
-                                                   size, alignment,
-                                                   CSR1212_UNITS_SPACE_BASE,
-                                                   CSR1212_UNITS_SPACE_END);
-}
-
-static void release_addr_range(u64 addr, void *__host)
-{
-       struct hpsb_host *host = (struct hpsb_host*)__host;
-       hpsb_unregister_addrspace(&csr_highlevel, host, addr);
-}
-
-
-int init_csr(void)
-{
-       node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0);
-       if (!node_cap) {
-               HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!");
-               return -ENOMEM;
-       }
-
-       hpsb_register_highlevel(&csr_highlevel);
-
-       return 0;
-}
-
-void cleanup_csr(void)
-{
-       if (node_cap)
-               csr1212_release_keyval(node_cap);
-        hpsb_unregister_highlevel(&csr_highlevel);
-}
diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h
deleted file mode 100644 (file)
index 90fb3f2..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef _IEEE1394_CSR_H
-#define _IEEE1394_CSR_H
-
-#include <linux/spinlock_types.h>
-
-#include "csr1212.h"
-#include "ieee1394_types.h"
-
-#define CSR_REGISTER_BASE              0xfffff0000000ULL
-
-/* register offsets relative to CSR_REGISTER_BASE */
-#define CSR_STATE_CLEAR                        0x0
-#define CSR_STATE_SET                  0x4
-#define CSR_NODE_IDS                   0x8
-#define CSR_RESET_START                        0xc
-#define CSR_SPLIT_TIMEOUT_HI           0x18
-#define CSR_SPLIT_TIMEOUT_LO           0x1c
-#define CSR_CYCLE_TIME                 0x200
-#define CSR_BUS_TIME                   0x204
-#define CSR_BUSY_TIMEOUT               0x210
-#define CSR_BUS_MANAGER_ID             0x21c
-#define CSR_BANDWIDTH_AVAILABLE                0x220
-#define CSR_CHANNELS_AVAILABLE         0x224
-#define CSR_CHANNELS_AVAILABLE_HI      0x224
-#define CSR_CHANNELS_AVAILABLE_LO      0x228
-#define CSR_BROADCAST_CHANNEL          0x234
-#define CSR_CONFIG_ROM                 0x400
-#define CSR_CONFIG_ROM_END             0x800
-#define CSR_FCP_COMMAND                        0xB00
-#define CSR_FCP_RESPONSE               0xD00
-#define CSR_FCP_END                    0xF00
-#define CSR_TOPOLOGY_MAP               0x1000
-#define CSR_TOPOLOGY_MAP_END           0x1400
-#define CSR_SPEED_MAP                  0x2000
-#define CSR_SPEED_MAP_END              0x3000
-
-/* IEEE 1394 bus specific Configuration ROM Key IDs */
-#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
-
-/* IEEE 1394 Bus Information Block specifics */
-#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
-
-#define CSR_IRMC_SHIFT                 31
-#define CSR_CMC_SHIFT                  30
-#define CSR_ISC_SHIFT                  29
-#define CSR_BMC_SHIFT                  28
-#define CSR_PMC_SHIFT                  27
-#define CSR_CYC_CLK_ACC_SHIFT          16
-#define CSR_MAX_REC_SHIFT              12
-#define CSR_MAX_ROM_SHIFT              8
-#define CSR_GENERATION_SHIFT           4
-
-static inline void csr_set_bus_info_generation(struct csr1212_csr *csr, u8 gen)
-{
-       csr->bus_info_data[2] &= ~cpu_to_be32(0xf << CSR_GENERATION_SHIFT);
-       csr->bus_info_data[2] |= cpu_to_be32((u32)gen << CSR_GENERATION_SHIFT);
-}
-
-struct csr_control {
-       spinlock_t lock;
-
-       quadlet_t state;
-       quadlet_t node_ids;
-       quadlet_t split_timeout_hi, split_timeout_lo;
-       unsigned long expire;   /* Calculated from split_timeout */
-       quadlet_t cycle_time;
-       quadlet_t bus_time;
-       quadlet_t bus_manager_id;
-       quadlet_t bandwidth_available;
-       quadlet_t channels_available_hi, channels_available_lo;
-       quadlet_t broadcast_channel;
-
-       /* Bus Info */
-       quadlet_t guid_hi, guid_lo;
-       u8 cyc_clk_acc;
-       u8 max_rec;
-       u8 max_rom;
-       u8 generation;  /* Only use values between 0x2 and 0xf */
-       u8 lnk_spd;
-
-       unsigned long gen_timestamp[16];
-
-       struct csr1212_csr *rom;
-
-       quadlet_t topology_map[256];
-       quadlet_t speed_map[1024];
-};
-
-extern struct csr1212_bus_ops csr_bus_ops;
-
-int init_csr(void);
-void cleanup_csr(void);
-
-/* hpsb_update_config_rom() is deprecated */
-struct hpsb_host;
-int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
-                          size_t size, unsigned char rom_version);
-
-#endif /* _IEEE1394_CSR_H */
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
deleted file mode 100644 (file)
index e76cac6..0000000
+++ /dev/null
@@ -1,1467 +0,0 @@
-/*
- * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
- *
- * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
- *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *    3. The name of the author may not be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/* TODO List:
- * - Verify interface consistency: i.e., public functions that take a size
- *   parameter expect size to be in bytes.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/kmemcheck.h>
-#include <linux/string.h>
-#include <asm/bug.h>
-#include <asm/byteorder.h>
-
-#include "csr1212.h"
-
-
-/* Permitted key type for each key id */
-#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE)
-#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET)
-#define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
-#define __L (1 << CSR1212_KV_TYPE_LEAF)
-static const u8 csr1212_key_id_type_map[0x30] = {
-       __C,                    /* used by Apple iSight */
-       __D | __L,              /* Descriptor */
-       __I | __D | __L,        /* Bus_Dependent_Info */
-       __I | __D | __L,        /* Vendor */
-       __I,                    /* Hardware_Version */
-       0, 0,                   /* Reserved */
-       __D | __L | __I,        /* Module */
-       __I, 0, 0, 0,           /* used by Apple iSight, Reserved */
-       __I,                    /* Node_Capabilities */
-       __L,                    /* EUI_64 */
-       0, 0, 0,                /* Reserved */
-       __D,                    /* Unit */
-       __I,                    /* Specifier_ID */
-       __I,                    /* Version */
-       __I | __C | __D | __L,  /* Dependent_Info */
-       __L,                    /* Unit_Location */
-       0,                      /* Reserved */
-       __I,                    /* Model */
-       __D,                    /* Instance */
-       __L,                    /* Keyword */
-       __D,                    /* Feature */
-       __L,                    /* Extended_ROM */
-       __I,                    /* Extended_Key_Specifier_ID */
-       __I,                    /* Extended_Key */
-       __I | __C | __D | __L,  /* Extended_Data */
-       __L,                    /* Modifiable_Descriptor */
-       __I,                    /* Directory_ID */
-       __I,                    /* Revision */
-};
-#undef __I
-#undef __C
-#undef __D
-#undef __L
-
-
-#define quads_to_bytes(_q) ((_q) * sizeof(u32))
-#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32))
-
-static void free_keyval(struct csr1212_keyval *kv)
-{
-       if ((kv->key.type == CSR1212_KV_TYPE_LEAF) &&
-           (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM))
-               CSR1212_FREE(kv->value.leaf.data);
-
-       CSR1212_FREE(kv);
-}
-
-static u16 csr1212_crc16(const u32 *buffer, size_t length)
-{
-       int shift;
-       u32 data;
-       u16 sum, crc = 0;
-
-       for (; length; length--) {
-               data = be32_to_cpu(*buffer);
-               buffer++;
-               for (shift = 28; shift >= 0; shift -= 4 ) {
-                       sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
-                       crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-               }
-               crc &= 0xffff;
-       }
-
-       return cpu_to_be16(crc);
-}
-
-/* Microsoft computes the CRC with the bytes in reverse order. */
-static u16 csr1212_msft_crc16(const u32 *buffer, size_t length)
-{
-       int shift;
-       u32 data;
-       u16 sum, crc = 0;
-
-       for (; length; length--) {
-               data = le32_to_cpu(*buffer);
-               buffer++;
-               for (shift = 28; shift >= 0; shift -= 4 ) {
-                       sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
-                       crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-               }
-               crc &= 0xffff;
-       }
-
-       return cpu_to_be16(crc);
-}
-
-static struct csr1212_dentry *
-csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv)
-{
-       struct csr1212_dentry *pos;
-
-       for (pos = dir->value.directory.dentries_head;
-            pos != NULL; pos = pos->next)
-               if (pos->kv == kv)
-                       return pos;
-       return NULL;
-}
-
-static struct csr1212_keyval *
-csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u32 offset)
-{
-       struct csr1212_keyval *kv;
-
-       for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next)
-               if (kv->offset == offset)
-                       return kv;
-       return NULL;
-}
-
-
-/* Creation Routines */
-
-struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
-                                      size_t bus_info_size, void *private)
-{
-       struct csr1212_csr *csr;
-
-       csr = CSR1212_MALLOC(sizeof(*csr));
-       if (!csr)
-               return NULL;
-
-       csr->cache_head =
-               csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
-                                        CSR1212_CONFIG_ROM_SPACE_SIZE);
-       if (!csr->cache_head) {
-               CSR1212_FREE(csr);
-               return NULL;
-       }
-
-       /* The keyval key id is not used for the root node, but a valid key id
-        * that can be used for a directory needs to be passed to
-        * csr1212_new_directory(). */
-       csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
-       if (!csr->root_kv) {
-               CSR1212_FREE(csr->cache_head);
-               CSR1212_FREE(csr);
-               return NULL;
-       }
-
-       csr->bus_info_data = csr->cache_head->data;
-       csr->bus_info_len = bus_info_size;
-       csr->crc_len = bus_info_size;
-       csr->ops = ops;
-       csr->private = private;
-       csr->cache_tail = csr->cache_head;
-
-       return csr;
-}
-
-void csr1212_init_local_csr(struct csr1212_csr *csr,
-                           const u32 *bus_info_data, int max_rom)
-{
-       static const int mr_map[] = { 4, 64, 1024, 0 };
-
-       BUG_ON(max_rom & ~0x3);
-       csr->max_rom = mr_map[max_rom];
-       memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
-}
-
-static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key)
-{
-       struct csr1212_keyval *kv;
-
-       if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
-               return NULL;
-
-       kv = CSR1212_MALLOC(sizeof(*kv));
-       if (!kv)
-               return NULL;
-
-       atomic_set(&kv->refcnt, 1);
-       kv->key.type = type;
-       kv->key.id = key;
-       kv->associate = NULL;
-       kv->next = NULL;
-       kv->prev = NULL;
-       kv->offset = 0;
-       kv->valid = 0;
-       return kv;
-}
-
-struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.immediate = value;
-       kv->valid = 1;
-       return kv;
-}
-
-static struct csr1212_keyval *
-csr1212_new_leaf(u8 key, const void *data, size_t data_len)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
-       if (!kv)
-               return NULL;
-
-       if (data_len > 0) {
-               kv->value.leaf.data = CSR1212_MALLOC(data_len);
-               if (!kv->value.leaf.data) {
-                       CSR1212_FREE(kv);
-                       return NULL;
-               }
-
-               if (data)
-                       memcpy(kv->value.leaf.data, data, data_len);
-       } else {
-               kv->value.leaf.data = NULL;
-       }
-
-       kv->value.leaf.len = bytes_to_quads(data_len);
-       kv->offset = 0;
-       kv->valid = 1;
-
-       return kv;
-}
-
-static struct csr1212_keyval *
-csr1212_new_csr_offset(u8 key, u32 csr_offset)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.csr_offset = csr_offset;
-
-       kv->offset = 0;
-       kv->valid = 1;
-       return kv;
-}
-
-struct csr1212_keyval *csr1212_new_directory(u8 key)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.directory.len = 0;
-       kv->offset = 0;
-       kv->value.directory.dentries_head = NULL;
-       kv->value.directory.dentries_tail = NULL;
-       kv->valid = 1;
-       return kv;
-}
-
-void csr1212_associate_keyval(struct csr1212_keyval *kv,
-                             struct csr1212_keyval *associate)
-{
-       BUG_ON(!kv || !associate || kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
-              (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
-               associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
-               associate->key.id < 0x30) ||
-              (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) ||
-              (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) ||
-              (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
-               kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) ||
-              (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
-               kv->key.id != CSR1212_KV_ID_EXTENDED_KEY));
-
-       if (kv->associate)
-               csr1212_release_keyval(kv->associate);
-
-       csr1212_keep_keyval(associate);
-       kv->associate = associate;
-}
-
-static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                               struct csr1212_keyval *kv,
-                                               bool keep_keyval)
-{
-       struct csr1212_dentry *dentry;
-
-       BUG_ON(!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY);
-
-       dentry = CSR1212_MALLOC(sizeof(*dentry));
-       if (!dentry)
-               return -ENOMEM;
-
-       if (keep_keyval)
-               csr1212_keep_keyval(kv);
-       dentry->kv = kv;
-
-       dentry->next = NULL;
-       dentry->prev = dir->value.directory.dentries_tail;
-
-       if (!dir->value.directory.dentries_head)
-               dir->value.directory.dentries_head = dentry;
-
-       if (dir->value.directory.dentries_tail)
-               dir->value.directory.dentries_tail->next = dentry;
-       dir->value.directory.dentries_tail = dentry;
-
-       return CSR1212_SUCCESS;
-}
-
-int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                      struct csr1212_keyval *kv)
-{
-       return __csr1212_attach_keyval_to_directory(dir, kv, true);
-}
-
-#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
-       (&((kv)->value.leaf.data[1]))
-
-#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \
-       ((kv)->value.leaf.data[0] = \
-        cpu_to_be32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \
-                    ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)))
-#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \
-       ((kv)->value.leaf.data[0] = \
-        cpu_to_be32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \
-                     CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \
-                    ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)))
-
-static struct csr1212_keyval *
-csr1212_new_descriptor_leaf(u8 dtype, u32 specifier_id,
-                           const void *data, size_t data_len)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
-                             data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
-       if (!kv)
-               return NULL;
-
-       kmemcheck_annotate_variable(kv->value.leaf.data[0]);
-       CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
-       CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
-
-       if (data)
-               memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
-
-       return kv;
-}
-
-/* Check if string conforms to minimal ASCII as per IEEE 1212 clause 7.4 */
-static int csr1212_check_minimal_ascii(const char *s)
-{
-       static const char minimal_ascii_table[] = {
-                                       /*  1   2   4   8  16  32  64  128 */
-               128,                    /* --, --, --, --, --, --, --, 07, */
-               4 + 16 + 32,            /* --, --, 0a, --, 0C, 0D, --, --, */
-               0,                      /* --, --, --, --, --, --, --, --, */
-               0,                      /* --, --, --, --, --, --, --, --, */
-               255 - 8 - 16,           /* 20, 21, 22, --, --, 25, 26, 27, */
-               255,                    /* 28, 29, 2a, 2b, 2c, 2d, 2e, 2f, */
-               255,                    /* 30, 31, 32, 33, 34, 35, 36, 37, */
-               255,                    /* 38, 39, 3a, 3b, 3c, 3d, 3e, 3f, */
-               255,                    /* 40, 41, 42, 43, 44, 45, 46, 47, */
-               255,                    /* 48, 49, 4a, 4b, 4c, 4d, 4e, 4f, */
-               255,                    /* 50, 51, 52, 53, 54, 55, 56, 57, */
-               1 + 2 + 4 + 128,        /* 58, 59, 5a, --, --, --, --, 5f, */
-               255 - 1,                /* --, 61, 62, 63, 64, 65, 66, 67, */
-               255,                    /* 68, 69, 6a, 6b, 6c, 6d, 6e, 6f, */
-               255,                    /* 70, 71, 72, 73, 74, 75, 76, 77, */
-               1 + 2 + 4,              /* 78, 79, 7a, --, --, --, --, --, */
-       };
-       int i, j;
-
-       for (; *s; s++) {
-               i = *s >> 3;            /*  i = *s / 8;         */
-               j = 1 << (*s & 3);      /*  j = 1 << (*s % 8);  */
-
-               if (i >= ARRAY_SIZE(minimal_ascii_table) ||
-                   !(minimal_ascii_table[i] & j))
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-/* IEEE 1212 clause 7.5.4.1 textual descriptors (English, minimal ASCII) */
-struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
-{
-       struct csr1212_keyval *kv;
-       u32 *text;
-       size_t str_len, quads;
-
-       if (!s || !*s || csr1212_check_minimal_ascii(s))
-               return NULL;
-
-       str_len = strlen(s);
-       quads = bytes_to_quads(str_len);
-       kv = csr1212_new_descriptor_leaf(0, 0, NULL, quads_to_bytes(quads) +
-                                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
-       if (!kv)
-               return NULL;
-
-       kv->value.leaf.data[1] = 0;     /* width, character_set, language */
-       text = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
-       text[quads - 1] = 0;            /* padding */
-       memcpy(text, s, str_len);
-
-       return kv;
-}
-
-
-/* Destruction Routines */
-
-void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
-                                         struct csr1212_keyval *kv)
-{
-       struct csr1212_dentry *dentry;
-
-       if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
-               return;
-
-       dentry = csr1212_find_keyval(dir, kv);
-
-       if (!dentry)
-               return;
-
-       if (dentry->prev)
-               dentry->prev->next = dentry->next;
-       if (dentry->next)
-               dentry->next->prev = dentry->prev;
-       if (dir->value.directory.dentries_head == dentry)
-               dir->value.directory.dentries_head = dentry->next;
-       if (dir->value.directory.dentries_tail == dentry)
-               dir->value.directory.dentries_tail = dentry->prev;
-
-       CSR1212_FREE(dentry);
-
-       csr1212_release_keyval(kv);
-}
-
-/* This function is used to free the memory taken by a keyval.  If the given
- * keyval is a directory type, then any keyvals contained in that directory
- * will be destroyed as well if noone holds a reference on them.  By means of
- * list manipulation, this routine will descend a directory structure in a
- * non-recursive manner. */
-void csr1212_release_keyval(struct csr1212_keyval *kv)
-{
-       struct csr1212_keyval *k, *a;
-       struct csr1212_dentry dentry;
-       struct csr1212_dentry *head, *tail;
-
-       if (!atomic_dec_and_test(&kv->refcnt))
-               return;
-
-       dentry.kv = kv;
-       dentry.next = NULL;
-       dentry.prev = NULL;
-
-       head = &dentry;
-       tail = head;
-
-       while (head) {
-               k = head->kv;
-
-               while (k) {
-                       /* must not dec_and_test kv->refcnt again */
-                       if (k != kv && !atomic_dec_and_test(&k->refcnt))
-                               break;
-
-                       a = k->associate;
-
-                       if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
-                               /* If the current entry is a directory, move all
-                                * the entries to the destruction list. */
-                               if (k->value.directory.dentries_head) {
-                                       tail->next =
-                                           k->value.directory.dentries_head;
-                                       k->value.directory.dentries_head->prev =
-                                           tail;
-                                       tail = k->value.directory.dentries_tail;
-                               }
-                       }
-                       free_keyval(k);
-                       k = a;
-               }
-
-               head = head->next;
-               if (head) {
-                       if (head->prev && head->prev != &dentry)
-                               CSR1212_FREE(head->prev);
-                       head->prev = NULL;
-               } else if (tail != &dentry) {
-                       CSR1212_FREE(tail);
-               }
-       }
-}
-
-void csr1212_destroy_csr(struct csr1212_csr *csr)
-{
-       struct csr1212_csr_rom_cache *c, *oc;
-       struct csr1212_cache_region *cr, *ocr;
-
-       csr1212_release_keyval(csr->root_kv);
-
-       c = csr->cache_head;
-       while (c) {
-               oc = c;
-               cr = c->filled_head;
-               while (cr) {
-                       ocr = cr;
-                       cr = cr->next;
-                       CSR1212_FREE(ocr);
-               }
-               c = c->next;
-               CSR1212_FREE(oc);
-       }
-
-       CSR1212_FREE(csr);
-}
-
-
-/* CSR Image Creation */
-
-static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
-{
-       struct csr1212_csr_rom_cache *cache;
-       u64 csr_addr;
-
-       BUG_ON(!csr || !csr->ops || !csr->ops->allocate_addr_range ||
-              !csr->ops->release_addr || csr->max_rom < 1);
-
-       /* ROM size must be a multiple of csr->max_rom */
-       romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
-
-       csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom,
-                                                csr->private);
-       if (csr_addr == CSR1212_INVALID_ADDR_SPACE)
-               return -ENOMEM;
-
-       if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
-               /* Invalid address returned from allocate_addr_range(). */
-               csr->ops->release_addr(csr_addr, csr->private);
-               return -ENOMEM;
-       }
-
-       cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE,
-                                        romsize);
-       if (!cache) {
-               csr->ops->release_addr(csr_addr, csr->private);
-               return -ENOMEM;
-       }
-
-       cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF,
-                                           CSR1212_KV_ID_EXTENDED_ROM);
-       if (!cache->ext_rom) {
-               csr->ops->release_addr(csr_addr, csr->private);
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-
-       if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) !=
-           CSR1212_SUCCESS) {
-               csr1212_release_keyval(cache->ext_rom);
-               csr->ops->release_addr(csr_addr, csr->private);
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-       cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
-       cache->ext_rom->value.leaf.len = -1;
-       cache->ext_rom->value.leaf.data = cache->data;
-
-       /* Add cache to tail of cache list */
-       cache->prev = csr->cache_tail;
-       csr->cache_tail->next = cache;
-       csr->cache_tail = cache;
-       return CSR1212_SUCCESS;
-}
-
-static void csr1212_remove_cache(struct csr1212_csr *csr,
-                                struct csr1212_csr_rom_cache *cache)
-{
-       if (csr->cache_head == cache)
-               csr->cache_head = cache->next;
-       if (csr->cache_tail == cache)
-               csr->cache_tail = cache->prev;
-
-       if (cache->prev)
-               cache->prev->next = cache->next;
-       if (cache->next)
-               cache->next->prev = cache->prev;
-
-       if (cache->ext_rom) {
-               csr1212_detach_keyval_from_directory(csr->root_kv,
-                                                    cache->ext_rom);
-               csr1212_release_keyval(cache->ext_rom);
-       }
-
-       CSR1212_FREE(cache);
-}
-
-static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
-                                         struct csr1212_keyval **layout_tail)
-{
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *dkv;
-       struct csr1212_keyval *last_extkey_spec = NULL;
-       struct csr1212_keyval *last_extkey = NULL;
-       int num_entries = 0;
-
-       for (dentry = dir->value.directory.dentries_head; dentry;
-            dentry = dentry->next) {
-               for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
-                       /* Special Case: Extended Key Specifier_ID */
-                       if (dkv->key.id ==
-                           CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
-                               if (last_extkey_spec == NULL)
-                                       last_extkey_spec = dkv;
-                               else if (dkv->value.immediate !=
-                                        last_extkey_spec->value.immediate)
-                                       last_extkey_spec = dkv;
-                               else
-                                       continue;
-                       /* Special Case: Extended Key */
-                       } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
-                               if (last_extkey == NULL)
-                                       last_extkey = dkv;
-                               else if (dkv->value.immediate !=
-                                        last_extkey->value.immediate)
-                                       last_extkey = dkv;
-                               else
-                                       continue;
-                       }
-
-                       num_entries += 1;
-
-                       switch (dkv->key.type) {
-                       default:
-                       case CSR1212_KV_TYPE_IMMEDIATE:
-                       case CSR1212_KV_TYPE_CSR_OFFSET:
-                               break;
-                       case CSR1212_KV_TYPE_LEAF:
-                       case CSR1212_KV_TYPE_DIRECTORY:
-                               /* Remove from list */
-                               if (dkv->prev && (dkv->prev->next == dkv))
-                                       dkv->prev->next = dkv->next;
-                               if (dkv->next && (dkv->next->prev == dkv))
-                                       dkv->next->prev = dkv->prev;
-                               //if (dkv == *layout_tail)
-                               //      *layout_tail = dkv->prev;
-
-                               /* Special case: Extended ROM leafs */
-                               if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-                                       dkv->value.leaf.len = -1;
-                                       /* Don't add Extended ROM leafs in the
-                                        * layout list, they are handled
-                                        * differently. */
-                                       break;
-                               }
-
-                               /* Add to tail of list */
-                               dkv->next = NULL;
-                               dkv->prev = *layout_tail;
-                               (*layout_tail)->next = dkv;
-                               *layout_tail = dkv;
-                               break;
-                       }
-               }
-       }
-       return num_entries;
-}
-
-static size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
-{
-       struct csr1212_keyval *ltail = kv;
-       size_t agg_size = 0;
-
-       while (kv) {
-               switch (kv->key.type) {
-               case CSR1212_KV_TYPE_LEAF:
-                       /* Add 1 quadlet for crc/len field */
-                       agg_size += kv->value.leaf.len + 1;
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       kv->value.directory.len =
-                               csr1212_generate_layout_subdir(kv, &ltail);
-                       /* Add 1 quadlet for crc/len field */
-                       agg_size += kv->value.directory.len + 1;
-                       break;
-               }
-               kv = kv->next;
-       }
-       return quads_to_bytes(agg_size);
-}
-
-static struct csr1212_keyval *
-csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
-                          struct csr1212_keyval *start_kv, int start_pos)
-{
-       struct csr1212_keyval *kv = start_kv;
-       struct csr1212_keyval *okv = start_kv;
-       int pos = start_pos;
-       int kv_len = 0, okv_len = 0;
-
-       cache->layout_head = kv;
-
-       while (kv && pos < cache->size) {
-               /* Special case: Extended ROM leafs */
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                       kv->offset = cache->offset + pos;
-
-               switch (kv->key.type) {
-               case CSR1212_KV_TYPE_LEAF:
-                       kv_len = kv->value.leaf.len;
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       kv_len = kv->value.directory.len;
-                       break;
-
-               default:
-                       /* Should never get here */
-                       WARN_ON(1);
-                       break;
-               }
-
-               pos += quads_to_bytes(kv_len + 1);
-
-               if (pos <= cache->size) {
-                       okv = kv;
-                       okv_len = kv_len;
-                       kv = kv->next;
-               }
-       }
-
-       cache->layout_tail = okv;
-       cache->len = okv->offset - cache->offset + quads_to_bytes(okv_len + 1);
-
-       return kv;
-}
-
-#define CSR1212_KV_KEY_SHIFT           24
-#define CSR1212_KV_KEY_TYPE_SHIFT      6
-#define CSR1212_KV_KEY_ID_MASK         0x3f
-#define CSR1212_KV_KEY_TYPE_MASK       0x3     /* after shift */
-
-static void
-csr1212_generate_tree_subdir(struct csr1212_keyval *dir, u32 *data_buffer)
-{
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *last_extkey_spec = NULL;
-       struct csr1212_keyval *last_extkey = NULL;
-       int index = 0;
-
-       for (dentry = dir->value.directory.dentries_head;
-            dentry;
-            dentry = dentry->next) {
-               struct csr1212_keyval *a;
-
-               for (a = dentry->kv; a; a = a->associate) {
-                       u32 value = 0;
-
-                       /* Special Case: Extended Key Specifier_ID */
-                       if (a->key.id ==
-                           CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
-                               if (last_extkey_spec == NULL)
-                                       last_extkey_spec = a;
-                               else if (a->value.immediate !=
-                                        last_extkey_spec->value.immediate)
-                                       last_extkey_spec = a;
-                               else
-                                       continue;
-
-                       /* Special Case: Extended Key */
-                       } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
-                               if (last_extkey == NULL)
-                                       last_extkey = a;
-                               else if (a->value.immediate !=
-                                        last_extkey->value.immediate)
-                                       last_extkey = a;
-                               else
-                                       continue;
-                       }
-
-                       switch (a->key.type) {
-                       case CSR1212_KV_TYPE_IMMEDIATE:
-                               value = a->value.immediate;
-                               break;
-                       case CSR1212_KV_TYPE_CSR_OFFSET:
-                               value = a->value.csr_offset;
-                               break;
-                       case CSR1212_KV_TYPE_LEAF:
-                               value = a->offset;
-                               value -= dir->offset + quads_to_bytes(1+index);
-                               value = bytes_to_quads(value);
-                               break;
-                       case CSR1212_KV_TYPE_DIRECTORY:
-                               value = a->offset;
-                               value -= dir->offset + quads_to_bytes(1+index);
-                               value = bytes_to_quads(value);
-                               break;
-                       default:
-                               /* Should never get here */
-                               WARN_ON(1);
-                               break;
-                       }
-
-                       value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) <<
-                                CSR1212_KV_KEY_SHIFT;
-                       value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
-                                (CSR1212_KV_KEY_SHIFT +
-                                 CSR1212_KV_KEY_TYPE_SHIFT);
-                       data_buffer[index] = cpu_to_be32(value);
-                       index++;
-               }
-       }
-}
-
-struct csr1212_keyval_img {
-       u16 length;
-       u16 crc;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-static void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
-{
-       struct csr1212_keyval *kv, *nkv;
-       struct csr1212_keyval_img *kvi;
-
-       for (kv = cache->layout_head;
-            kv != cache->layout_tail->next;
-            kv = nkv) {
-               kvi = (struct csr1212_keyval_img *)(cache->data +
-                               bytes_to_quads(kv->offset - cache->offset));
-               switch (kv->key.type) {
-               default:
-               case CSR1212_KV_TYPE_IMMEDIATE:
-               case CSR1212_KV_TYPE_CSR_OFFSET:
-                       /* Should never get here */
-                       WARN_ON(1);
-                       break;
-
-               case CSR1212_KV_TYPE_LEAF:
-                       /* Don't copy over Extended ROM areas, they are
-                        * already filled out! */
-                       if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                               memcpy(kvi->data, kv->value.leaf.data,
-                                      quads_to_bytes(kv->value.leaf.len));
-
-                       kvi->length = cpu_to_be16(kv->value.leaf.len);
-                       kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       csr1212_generate_tree_subdir(kv, kvi->data);
-
-                       kvi->length = cpu_to_be16(kv->value.directory.len);
-                       kvi->crc = csr1212_crc16(kvi->data,
-                                                kv->value.directory.len);
-                       break;
-               }
-
-               nkv = kv->next;
-               if (kv->prev)
-                       kv->prev->next = NULL;
-               if (kv->next)
-                       kv->next->prev = NULL;
-               kv->prev = NULL;
-               kv->next = NULL;
-       }
-}
-
-/* This size is arbitrarily chosen.
- * The struct overhead is subtracted for more economic allocations. */
-#define CSR1212_EXTENDED_ROM_SIZE (2048 - sizeof(struct csr1212_csr_rom_cache))
-
-int csr1212_generate_csr_image(struct csr1212_csr *csr)
-{
-       struct csr1212_bus_info_block_img *bi;
-       struct csr1212_csr_rom_cache *cache;
-       struct csr1212_keyval *kv;
-       size_t agg_size;
-       int ret;
-       int init_offset;
-
-       BUG_ON(!csr);
-
-       cache = csr->cache_head;
-
-       bi = (struct csr1212_bus_info_block_img*)cache->data;
-
-       bi->length = bytes_to_quads(csr->bus_info_len) - 1;
-       bi->crc_length = bi->length;
-       bi->crc = csr1212_crc16(bi->data, bi->crc_length);
-
-       csr->root_kv->next = NULL;
-       csr->root_kv->prev = NULL;
-
-       agg_size = csr1212_generate_layout_order(csr->root_kv);
-
-       init_offset = csr->bus_info_len;
-
-       for (kv = csr->root_kv, cache = csr->cache_head;
-            kv;
-            cache = cache->next) {
-               if (!cache) {
-                       /* Estimate approximate number of additional cache
-                        * regions needed (it assumes that the cache holding
-                        * the first 1K Config ROM space always exists). */
-                       int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
-                                               (2 * sizeof(u32))) + 1;
-
-                       /* Add additional cache regions, extras will be
-                        * removed later */
-                       for (; est_c; est_c--) {
-                               ret = csr1212_append_new_cache(csr,
-                                               CSR1212_EXTENDED_ROM_SIZE);
-                               if (ret != CSR1212_SUCCESS)
-                                       return ret;
-                       }
-                       /* Need to re-layout for additional cache regions */
-                       agg_size = csr1212_generate_layout_order(csr->root_kv);
-                       kv = csr->root_kv;
-                       cache = csr->cache_head;
-                       init_offset = csr->bus_info_len;
-               }
-               kv = csr1212_generate_positions(cache, kv, init_offset);
-               agg_size -= cache->len;
-               init_offset = sizeof(u32);
-       }
-
-       /* Remove unused, excess cache regions */
-       while (cache) {
-               struct csr1212_csr_rom_cache *oc = cache;
-
-               cache = cache->next;
-               csr1212_remove_cache(csr, oc);
-       }
-
-       /* Go through the list backward so that when done, the correct CRC
-        * will be calculated for the Extended ROM areas. */
-       for (cache = csr->cache_tail; cache; cache = cache->prev) {
-               /* Only Extended ROM caches should have this set. */
-               if (cache->ext_rom) {
-                       int leaf_size;
-
-                       /* Make sure the Extended ROM leaf is a multiple of
-                        * max_rom in size. */
-                       BUG_ON(csr->max_rom < 1);
-                       leaf_size = (cache->len + (csr->max_rom - 1)) &
-                               ~(csr->max_rom - 1);
-
-                       /* Zero out the unused ROM region */
-                       memset(cache->data + bytes_to_quads(cache->len), 0x00,
-                              leaf_size - cache->len);
-
-                       /* Subtract leaf header */
-                       leaf_size -= sizeof(u32);
-
-                       /* Update the Extended ROM leaf length */
-                       cache->ext_rom->value.leaf.len =
-                               bytes_to_quads(leaf_size);
-               } else {
-                       /* Zero out the unused ROM region */
-                       memset(cache->data + bytes_to_quads(cache->len), 0x00,
-                              cache->size - cache->len);
-               }
-
-               /* Copy the data into the cache buffer */
-               csr1212_fill_cache(cache);
-
-               if (cache != csr->cache_head) {
-                       /* Set the length and CRC of the extended ROM. */
-                       struct csr1212_keyval_img *kvi =
-                               (struct csr1212_keyval_img*)cache->data;
-                       u16 len = bytes_to_quads(cache->len) - 1;
-
-                       kvi->length = cpu_to_be16(len);
-                       kvi->crc = csr1212_crc16(kvi->data, len);
-               }
-       }
-
-       return CSR1212_SUCCESS;
-}
-
-int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer, u32 len)
-{
-       struct csr1212_csr_rom_cache *cache;
-
-       for (cache = csr->cache_head; cache; cache = cache->next)
-               if (offset >= cache->offset &&
-                   (offset + len) <= (cache->offset + cache->size)) {
-                       memcpy(buffer, &cache->data[
-                                       bytes_to_quads(offset - cache->offset)],
-                              len);
-                       return CSR1212_SUCCESS;
-               }
-
-       return -ENOENT;
-}
-
-/*
- * Apparently there are many different wrong implementations of the CRC
- * algorithm.  We don't fail, we just warn... approximately once per GUID.
- */
-static void
-csr1212_check_crc(const u32 *buffer, size_t length, u16 crc, __be32 *guid)
-{
-       static u64 last_bad_eui64;
-       u64 eui64 = ((u64)be32_to_cpu(guid[0]) << 32) | be32_to_cpu(guid[1]);
-
-       if (csr1212_crc16(buffer, length) == crc ||
-           csr1212_msft_crc16(buffer, length) == crc ||
-           eui64 == last_bad_eui64)
-               return;
-
-       printk(KERN_DEBUG "ieee1394: config ROM CRC error\n");
-       last_bad_eui64 = eui64;
-}
-
-/* Parse a chunk of data as a Config ROM */
-
-static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
-{
-       struct csr1212_bus_info_block_img *bi;
-       struct csr1212_cache_region *cr;
-       int i;
-       int ret;
-
-       for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) {
-               ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
-                               &csr->cache_head->data[bytes_to_quads(i)],
-                               csr->private);
-               if (ret != CSR1212_SUCCESS)
-                       return ret;
-
-               /* check ROM header's info_length */
-               if (i == 0 &&
-                   be32_to_cpu(csr->cache_head->data[0]) >> 24 !=
-                   bytes_to_quads(csr->bus_info_len) - 1)
-                       return -EINVAL;
-       }
-
-       bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
-       csr->crc_len = quads_to_bytes(bi->crc_length);
-
-       /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that
-        * is not always the case, so read the rest of the crc area 1 quadlet at
-        * a time. */
-       for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) {
-               ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
-                               &csr->cache_head->data[bytes_to_quads(i)],
-                               csr->private);
-               if (ret != CSR1212_SUCCESS)
-                       return ret;
-       }
-
-       csr1212_check_crc(bi->data, bi->crc_length, bi->crc,
-                         &csr->bus_info_data[3]);
-
-       cr = CSR1212_MALLOC(sizeof(*cr));
-       if (!cr)
-               return -ENOMEM;
-
-       cr->next = NULL;
-       cr->prev = NULL;
-       cr->offset_start = 0;
-       cr->offset_end = csr->crc_len + 4;
-
-       csr->cache_head->filled_head = cr;
-       csr->cache_head->filled_tail = cr;
-
-       return CSR1212_SUCCESS;
-}
-
-#define CSR1212_KV_KEY(q)      (be32_to_cpu(q) >> CSR1212_KV_KEY_SHIFT)
-#define CSR1212_KV_KEY_TYPE(q) (CSR1212_KV_KEY(q) >> CSR1212_KV_KEY_TYPE_SHIFT)
-#define CSR1212_KV_KEY_ID(q)   (CSR1212_KV_KEY(q) & CSR1212_KV_KEY_ID_MASK)
-#define CSR1212_KV_VAL_MASK    0xffffff
-#define CSR1212_KV_VAL(q)      (be32_to_cpu(q) & CSR1212_KV_VAL_MASK)
-
-static int
-csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
-{
-       int ret = CSR1212_SUCCESS;
-       struct csr1212_keyval *k = NULL;
-       u32 offset;
-       bool keep_keyval = true;
-
-       switch (CSR1212_KV_KEY_TYPE(ki)) {
-       case CSR1212_KV_TYPE_IMMEDIATE:
-               k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
-                                         CSR1212_KV_VAL(ki));
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               break;
-
-       case CSR1212_KV_TYPE_CSR_OFFSET:
-               k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
-                                          CSR1212_KV_VAL(ki));
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               break;
-
-       default:
-               /* Compute the offset from 0xffff f000 0000. */
-               offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
-               if (offset == kv_pos) {
-                       /* Uh-oh.  Can't have a relative offset of 0 for Leaves
-                        * or Directories.  The Config ROM image is most likely
-                        * messed up, so we'll just abort here. */
-                       ret = -EIO;
-                       goto out;
-               }
-
-               k = csr1212_find_keyval_offset(dir, offset);
-
-               if (k)
-                       break;          /* Found it. */
-
-               if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY)
-                       k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
-               else
-                       k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
-
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               /* Contents not read yet so it's not valid. */
-               k->valid = 0;
-               k->offset = offset;
-
-               k->prev = dir;
-               k->next = dir->next;
-               dir->next->prev = k;
-               dir->next = k;
-       }
-       ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval);
-out:
-       if (ret != CSR1212_SUCCESS && k != NULL)
-               free_keyval(k);
-       return ret;
-}
-
-int csr1212_parse_keyval(struct csr1212_keyval *kv,
-                        struct csr1212_csr_rom_cache *cache)
-{
-       struct csr1212_keyval_img *kvi;
-       int i;
-       int ret = CSR1212_SUCCESS;
-       int kvi_len;
-
-       kvi = (struct csr1212_keyval_img*)
-               &cache->data[bytes_to_quads(kv->offset - cache->offset)];
-       kvi_len = be16_to_cpu(kvi->length);
-
-       /* GUID is wrong in here in case of extended ROM.  We don't care. */
-       csr1212_check_crc(kvi->data, kvi_len, kvi->crc, &cache->data[3]);
-
-       switch (kv->key.type) {
-       case CSR1212_KV_TYPE_DIRECTORY:
-               for (i = 0; i < kvi_len; i++) {
-                       u32 ki = kvi->data[i];
-
-                       /* Some devices put null entries in their unit
-                        * directories.  If we come across such an entry,
-                        * then skip it. */
-                       if (ki == 0x0)
-                               continue;
-                       ret = csr1212_parse_dir_entry(kv, ki,
-                                       kv->offset + quads_to_bytes(i + 1));
-               }
-               kv->value.directory.len = kvi_len;
-               break;
-
-       case CSR1212_KV_TYPE_LEAF:
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
-                       size_t size = quads_to_bytes(kvi_len);
-
-                       kv->value.leaf.data = CSR1212_MALLOC(size);
-                       if (!kv->value.leaf.data) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-
-                       kv->value.leaf.len = kvi_len;
-                       memcpy(kv->value.leaf.data, kvi->data, size);
-               }
-               break;
-       }
-
-       kv->valid = 1;
-out:
-       return ret;
-}
-
-static int
-csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
-{
-       struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
-       struct csr1212_keyval_img *kvi = NULL;
-       struct csr1212_csr_rom_cache *cache;
-       int cache_index;
-       u64 addr;
-       u32 *cache_ptr;
-       u16 kv_len = 0;
-
-       BUG_ON(!csr || !kv || csr->max_rom < 1);
-
-       /* First find which cache the data should be in (or go in if not read
-        * yet). */
-       for (cache = csr->cache_head; cache; cache = cache->next)
-               if (kv->offset >= cache->offset &&
-                   kv->offset < (cache->offset + cache->size))
-                       break;
-
-       if (!cache) {
-               u32 q, cache_size;
-
-               /* Only create a new cache for Extended ROM leaves. */
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                       return -EINVAL;
-
-               if (csr->ops->bus_read(csr,
-                                      CSR1212_REGISTER_SPACE_BASE + kv->offset,
-                                      &q, csr->private))
-                       return -EIO;
-
-               kv->value.leaf.len = be32_to_cpu(q) >> 16;
-
-               cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
-                             (csr->max_rom - 1)) & ~(csr->max_rom - 1);
-
-               cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
-               if (!cache)
-                       return -ENOMEM;
-
-               kv->value.leaf.data = &cache->data[1];
-               csr->cache_tail->next = cache;
-               cache->prev = csr->cache_tail;
-               cache->next = NULL;
-               csr->cache_tail = cache;
-               cache->filled_head =
-                       CSR1212_MALLOC(sizeof(*cache->filled_head));
-               if (!cache->filled_head)
-                       return -ENOMEM;
-
-               cache->filled_head->offset_start = 0;
-               cache->filled_head->offset_end = sizeof(u32);
-               cache->filled_tail = cache->filled_head;
-               cache->filled_head->next = NULL;
-               cache->filled_head->prev = NULL;
-               cache->data[0] = q;
-
-               /* Don't read the entire extended ROM now.  Pieces of it will
-                * be read when entries inside it are read. */
-               return csr1212_parse_keyval(kv, cache);
-       }
-
-       cache_index = kv->offset - cache->offset;
-
-       /* Now seach read portions of the cache to see if it is there. */
-       for (cr = cache->filled_head; cr; cr = cr->next) {
-               if (cache_index < cr->offset_start) {
-                       newcr = CSR1212_MALLOC(sizeof(*newcr));
-                       if (!newcr)
-                               return -ENOMEM;
-
-                       newcr->offset_start = cache_index & ~(csr->max_rom - 1);
-                       newcr->offset_end = newcr->offset_start;
-                       newcr->next = cr;
-                       newcr->prev = cr->prev;
-                       cr->prev = newcr;
-                       cr = newcr;
-                       break;
-               } else if ((cache_index >= cr->offset_start) &&
-                          (cache_index < cr->offset_end)) {
-                       kvi = (struct csr1212_keyval_img*)
-                               (&cache->data[bytes_to_quads(cache_index)]);
-                       kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
-                       break;
-               } else if (cache_index == cr->offset_end) {
-                       break;
-               }
-       }
-
-       if (!cr) {
-               cr = cache->filled_tail;
-               newcr = CSR1212_MALLOC(sizeof(*newcr));
-               if (!newcr)
-                       return -ENOMEM;
-
-               newcr->offset_start = cache_index & ~(csr->max_rom - 1);
-               newcr->offset_end = newcr->offset_start;
-               newcr->prev = cr;
-               newcr->next = cr->next;
-               cr->next = newcr;
-               cr = newcr;
-               cache->filled_tail = newcr;
-       }
-
-       while(!kvi || cr->offset_end < cache_index + kv_len) {
-               cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
-                                                       ~(csr->max_rom - 1))];
-
-               addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
-                       cr->offset_end) & ~(csr->max_rom - 1);
-
-               if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private))
-                       return -EIO;
-
-               cr->offset_end += csr->max_rom - (cr->offset_end &
-                                                 (csr->max_rom - 1));
-
-               if (!kvi && (cr->offset_end > cache_index)) {
-                       kvi = (struct csr1212_keyval_img*)
-                               (&cache->data[bytes_to_quads(cache_index)]);
-                       kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
-               }
-
-               if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
-                       /* The Leaf or Directory claims its length extends
-                        * beyond the ConfigROM image region and thus beyond the
-                        * end of our cache region.  Therefore, we abort now
-                        * rather than seg faulting later. */
-                       return -EIO;
-               }
-
-               ncr = cr->next;
-
-               if (ncr && (cr->offset_end >= ncr->offset_start)) {
-                       /* consolidate region entries */
-                       ncr->offset_start = cr->offset_start;
-
-                       if (cr->prev)
-                               cr->prev->next = cr->next;
-                       ncr->prev = cr->prev;
-                       if (cache->filled_head == cr)
-                               cache->filled_head = ncr;
-                       CSR1212_FREE(cr);
-                       cr = ncr;
-               }
-       }
-
-       return csr1212_parse_keyval(kv, cache);
-}
-
-struct csr1212_keyval *
-csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
-{
-       if (!kv)
-               return NULL;
-       if (!kv->valid)
-               if (csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS)
-                       return NULL;
-       return kv;
-}
-
-int csr1212_parse_csr(struct csr1212_csr *csr)
-{
-       struct csr1212_dentry *dentry;
-       int ret;
-
-       BUG_ON(!csr || !csr->ops || !csr->ops->bus_read);
-
-       ret = csr1212_parse_bus_info_block(csr);
-       if (ret != CSR1212_SUCCESS)
-               return ret;
-
-       /*
-        * There has been a buggy firmware with bus_info_block.max_rom > 0
-        * spotted which actually only supported quadlet read requests to the
-        * config ROM.  Therefore read everything quadlet by quadlet regardless
-        * of what the bus info block says.
-        */
-       csr->max_rom = 4;
-
-       csr->cache_head->layout_head = csr->root_kv;
-       csr->cache_head->layout_tail = csr->root_kv;
-
-       csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
-               csr->bus_info_len;
-
-       csr->root_kv->valid = 0;
-       csr->root_kv->next = csr->root_kv;
-       csr->root_kv->prev = csr->root_kv;
-       ret = csr1212_read_keyval(csr, csr->root_kv);
-       if (ret != CSR1212_SUCCESS)
-               return ret;
-
-       /* Scan through the Root directory finding all extended ROM regions
-        * and make cache regions for them */
-       for (dentry = csr->root_kv->value.directory.dentries_head;
-            dentry; dentry = dentry->next) {
-               if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
-                       !dentry->kv->valid) {
-                       ret = csr1212_read_keyval(csr, dentry->kv);
-                       if (ret != CSR1212_SUCCESS)
-                               return ret;
-               }
-       }
-
-       return CSR1212_SUCCESS;
-}
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
deleted file mode 100644 (file)
index a892d92..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * csr1212.h -- IEEE 1212 Control and Status Register support for Linux
- *
- * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
- *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *    3. The name of the author may not be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CSR1212_H__
-#define __CSR1212_H__
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <asm/atomic.h>
-
-#define CSR1212_MALLOC(size)   kmalloc((size), GFP_KERNEL)
-#define CSR1212_FREE(ptr)      kfree(ptr)
-
-#define CSR1212_SUCCESS (0)
-
-
-/* CSR 1212 key types */
-#define CSR1212_KV_TYPE_IMMEDIATE              0
-#define CSR1212_KV_TYPE_CSR_OFFSET             1
-#define CSR1212_KV_TYPE_LEAF                   2
-#define CSR1212_KV_TYPE_DIRECTORY              3
-
-
-/* CSR 1212 key ids */
-#define CSR1212_KV_ID_DESCRIPTOR               0x01
-#define CSR1212_KV_ID_BUS_DEPENDENT_INFO       0x02
-#define CSR1212_KV_ID_VENDOR                   0x03
-#define CSR1212_KV_ID_HARDWARE_VERSION         0x04
-#define CSR1212_KV_ID_MODULE                   0x07
-#define CSR1212_KV_ID_NODE_CAPABILITIES                0x0C
-#define CSR1212_KV_ID_EUI_64                   0x0D
-#define CSR1212_KV_ID_UNIT                     0x11
-#define CSR1212_KV_ID_SPECIFIER_ID             0x12
-#define CSR1212_KV_ID_VERSION                  0x13
-#define CSR1212_KV_ID_DEPENDENT_INFO           0x14
-#define CSR1212_KV_ID_UNIT_LOCATION            0x15
-#define CSR1212_KV_ID_MODEL                    0x17
-#define CSR1212_KV_ID_INSTANCE                 0x18
-#define CSR1212_KV_ID_KEYWORD                  0x19
-#define CSR1212_KV_ID_FEATURE                  0x1A
-#define CSR1212_KV_ID_EXTENDED_ROM             0x1B
-#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID        0x1C
-#define CSR1212_KV_ID_EXTENDED_KEY             0x1D
-#define CSR1212_KV_ID_EXTENDED_DATA            0x1E
-#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR    0x1F
-#define CSR1212_KV_ID_DIRECTORY_ID             0x20
-#define CSR1212_KV_ID_REVISION                 0x21
-
-
-/* IEEE 1212 Address space map */
-#define CSR1212_ALL_SPACE_BASE                 (0x000000000000ULL)
-#define CSR1212_ALL_SPACE_SIZE                 (1ULL << 48)
-#define CSR1212_ALL_SPACE_END                  (CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE)
-
-#define  CSR1212_MEMORY_SPACE_BASE             (0x000000000000ULL)
-#define  CSR1212_MEMORY_SPACE_SIZE             ((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20)))
-#define  CSR1212_MEMORY_SPACE_END              (CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE)
-
-#define  CSR1212_PRIVATE_SPACE_BASE            (0xffffe0000000ULL)
-#define  CSR1212_PRIVATE_SPACE_SIZE            (256ULL * (1ULL << 20))
-#define  CSR1212_PRIVATE_SPACE_END             (CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE)
-
-#define  CSR1212_REGISTER_SPACE_BASE           (0xfffff0000000ULL)
-#define  CSR1212_REGISTER_SPACE_SIZE           (256ULL * (1ULL << 20))
-#define  CSR1212_REGISTER_SPACE_END            (CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE)
-
-#define  CSR1212_CSR_ARCH_REG_SPACE_BASE       (0xfffff0000000ULL)
-#define  CSR1212_CSR_ARCH_REG_SPACE_SIZE       (512)
-#define  CSR1212_CSR_ARCH_REG_SPACE_END                (CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE)
-#define  CSR1212_CSR_ARCH_REG_SPACE_OFFSET     (CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_BASE    (0xfffff0000200ULL)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE    (512)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_END     (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET  (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_CONFIG_ROM_SPACE_BASE         (0xfffff0000400ULL)
-#define  CSR1212_CONFIG_ROM_SPACE_SIZE         (1024)
-#define  CSR1212_CONFIG_ROM_SPACE_END          (CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE)
-#define  CSR1212_CONFIG_ROM_SPACE_OFFSET       (CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_UNITS_SPACE_BASE              (0xfffff0000800ULL)
-#define  CSR1212_UNITS_SPACE_SIZE              ((256ULL * (1ULL << 20)) - 2048)
-#define  CSR1212_UNITS_SPACE_END               (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE)
-#define  CSR1212_UNITS_SPACE_OFFSET            (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_INVALID_ADDR_SPACE            -1
-
-
-/* Config ROM image structures */
-struct csr1212_bus_info_block_img {
-       u8 length;
-       u8 crc_length;
-       u16 crc;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-struct csr1212_leaf {
-       int len;
-       u32 *data;
-};
-
-struct csr1212_dentry {
-       struct csr1212_dentry *next, *prev;
-       struct csr1212_keyval *kv;
-};
-
-struct csr1212_directory {
-       int len;
-       struct csr1212_dentry *dentries_head, *dentries_tail;
-};
-
-struct csr1212_keyval {
-       struct {
-               u8 type;
-               u8 id;
-       } key;
-       union {
-               u32 immediate;
-               u32 csr_offset;
-               struct csr1212_leaf leaf;
-               struct csr1212_directory directory;
-       } value;
-       struct csr1212_keyval *associate;
-       atomic_t refcnt;
-
-       /* used in generating and/or parsing CSR image */
-       struct csr1212_keyval *next, *prev;     /* flat list of CSR elements */
-       u32 offset;     /* position in CSR from 0xffff f000 0000 */
-       u8 valid;       /* flag indicating keyval has valid data*/
-};
-
-
-struct csr1212_cache_region {
-       struct csr1212_cache_region *next, *prev;
-       u32 offset_start;       /* inclusive */
-       u32 offset_end;         /* exclusive */
-};
-
-struct csr1212_csr_rom_cache {
-       struct csr1212_csr_rom_cache *next, *prev;
-       struct csr1212_cache_region *filled_head, *filled_tail;
-       struct csr1212_keyval *layout_head, *layout_tail;
-       size_t size;
-       u32 offset;
-       struct csr1212_keyval *ext_rom;
-       size_t len;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-struct csr1212_csr {
-       size_t bus_info_len;    /* bus info block length in bytes */
-       size_t crc_len;         /* crc length in bytes */
-       __be32 *bus_info_data;  /* bus info data incl bus name and EUI */
-
-       void *private;          /* private, bus specific data */
-       struct csr1212_bus_ops *ops;
-
-       struct csr1212_keyval *root_kv;
-
-       int max_rom;            /* max bytes readable in Config ROM region */
-
-       /* Items below used for image parsing and generation */
-       struct csr1212_csr_rom_cache *cache_head, *cache_tail;
-};
-
-struct csr1212_bus_ops {
-       /* This function is used by csr1212 to read additional information
-        * from remote nodes when parsing a Config ROM (i.e., read Config ROM
-        * entries located in the Units Space.  Must return 0 on success
-        * anything else indicates an error. */
-       int (*bus_read) (struct csr1212_csr *csr, u64 addr,
-                        void *buffer, void *private);
-
-       /* This function is used by csr1212 to allocate a region in units space
-        * in the event that Config ROM entries don't all fit in the predefined
-        * 1K region.  The void *private parameter is private member of struct
-        * csr1212_csr. */
-       u64 (*allocate_addr_range) (u64 size, u32 alignment, void *private);
-
-       /* This function is used by csr1212 to release a region in units space
-        * that is no longer needed. */
-       void (*release_addr) (u64 addr, void *private);
-};
-
-
-/* Descriptor Leaf manipulation macros */
-#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24
-#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff
-#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
-
-#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[0]) >> \
-        CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
-#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[0]) & \
-        CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)
-
-
-/* Text Descriptor Leaf manipulation macros */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff  /* after shift */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
-
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[1]) >> \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \
-       ((be32_to_cpu((kv)->value.leaf.data[1]) >> \
-         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[1]) & \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \
-       (&((kv)->value.leaf.data[2]))
-
-
-/* The following 2 function are for creating new Configuration ROM trees.  The
- * first function is used for both creating local trees and parsing remote
- * trees.  The second function adds pertinent information to local Configuration
- * ROM trees - namely data for the bus information block. */
-extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
-                                             size_t bus_info_size,
-                                             void *private);
-extern void csr1212_init_local_csr(struct csr1212_csr *csr,
-                                  const u32 *bus_info_data, int max_rom);
-
-
-/* Destroy a Configuration ROM tree and release all memory taken by the tree. */
-extern void csr1212_destroy_csr(struct csr1212_csr *csr);
-
-
-/* The following set of functions are fore creating new keyvals for placement in
- * a Configuration ROM tree.  Code that creates new keyvals with these functions
- * must release those keyvals with csr1212_release_keyval() when they are no
- * longer needed. */
-extern struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value);
-extern struct csr1212_keyval *csr1212_new_directory(u8 key);
-extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s);
-
-
-/* The following function manages association between keyvals.  Typically,
- * Descriptor Leaves and Directories will be associated with another keyval and
- * it is desirable for the Descriptor keyval to be place immediately after the
- * keyval that it is associated with.
- * Take care with subsequent ROM modifications:  There is no function to remove
- * previously specified associations.
- */
-extern void csr1212_associate_keyval(struct csr1212_keyval *kv,
-                                    struct csr1212_keyval *associate);
-
-
-/* The following functions manage the association of a keyval and directories.
- * A keyval may be attached to more than one directory. */
-extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                             struct csr1212_keyval *kv);
-extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
-                                                struct csr1212_keyval *kv);
-
-
-/* Creates a complete Configuration ROM image in the list of caches available
- * via csr->cache_head. */
-extern int csr1212_generate_csr_image(struct csr1212_csr *csr);
-
-
-/* This is a convience function for reading a block of data out of one of the
- * caches in the csr->cache_head list. */
-extern int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer,
-                       u32 len);
-
-
-/* The following functions are in place for parsing Configuration ROM images.
- * csr1212_parse_keyval() is used should there be a need to directly parse a
- * Configuration ROM directly. */
-extern int csr1212_parse_keyval(struct csr1212_keyval *kv,
-                               struct csr1212_csr_rom_cache *cache);
-extern int csr1212_parse_csr(struct csr1212_csr *csr);
-
-
-/* This function allocates a new cache which may be used for either parsing or
- * generating sub-sets of Configuration ROM images. */
-static inline struct csr1212_csr_rom_cache *
-csr1212_rom_cache_malloc(u32 offset, size_t size)
-{
-       struct csr1212_csr_rom_cache *cache;
-
-       cache = CSR1212_MALLOC(sizeof(*cache) + size);
-       if (!cache)
-               return NULL;
-
-       cache->next = NULL;
-       cache->prev = NULL;
-       cache->filled_head = NULL;
-       cache->filled_tail = NULL;
-       cache->layout_head = NULL;
-       cache->layout_tail = NULL;
-       cache->offset = offset;
-       cache->size = size;
-       cache->ext_rom = NULL;
-
-       return cache;
-}
-
-
-/* This function ensures that a keyval contains data when referencing a keyval
- * created by parsing a Configuration ROM. */
-extern struct csr1212_keyval *
-csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
-
-
-/* This function increments the reference count for a keyval should there be a
- * need for code to retain a keyval that has been parsed. */
-static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
-{
-       atomic_inc(&kv->refcnt);
-       smp_mb__after_atomic_inc();
-}
-
-
-/* This function decrements a keyval's reference count and will destroy the
- * keyval when there are no more users of the keyval.  This should be called by
- * any code that calls csr1212_keep_keyval() or any of the keyval creation
- * routines csr1212_new_*(). */
-extern void csr1212_release_keyval(struct csr1212_keyval *kv);
-
-
-/*
- * This macro allows for looping over the keyval entries in a directory and it
- * ensures that keyvals from remote ConfigROMs are parsed properly.
- *
- * struct csr1212_csr *_csr points to the CSR associated with dir.
- * struct csr1212_keyval *_kv points to the current keyval (loop index).
- * struct csr1212_keyval *_dir points to the directory to be looped.
- * struct csr1212_dentry *_pos is used internally for indexing.
- *
- * kv will be NULL upon exit of the loop.
- */
-#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos)              \
-       for (csr1212_get_keyval((_csr), (_dir)),                        \
-            _pos = (_dir)->value.directory.dentries_head,              \
-            _kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL;\
-            (_kv) && (_pos);                                           \
-            (_kv->associate == NULL) ?                                 \
-                    ((_pos = _pos->next), (_kv = (_pos) ?              \
-                               csr1212_get_keyval((_csr), _pos->kv) :  \
-                               NULL)) :                                \
-                    (_kv = csr1212_get_keyval((_csr), _kv->associate)))
-
-#endif /* __CSR1212_H__ */
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
deleted file mode 100644 (file)
index d178699..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * DMA region bookkeeping routines
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/scatterlist.h>
-
-#include "dma.h"
-
-/* dma_prog_region */
-
-void dma_prog_region_init(struct dma_prog_region *prog)
-{
-       prog->kvirt = NULL;
-       prog->dev = NULL;
-       prog->n_pages = 0;
-       prog->bus_addr = 0;
-}
-
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
-                         struct pci_dev *dev)
-{
-       /* round up to page size */
-       n_bytes = PAGE_ALIGN(n_bytes);
-
-       prog->n_pages = n_bytes >> PAGE_SHIFT;
-
-       prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
-       if (!prog->kvirt) {
-               printk(KERN_ERR
-                      "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
-               dma_prog_region_free(prog);
-               return -ENOMEM;
-       }
-
-       prog->dev = dev;
-
-       return 0;
-}
-
-void dma_prog_region_free(struct dma_prog_region *prog)
-{
-       if (prog->kvirt) {
-               pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
-                                   prog->kvirt, prog->bus_addr);
-       }
-
-       prog->kvirt = NULL;
-       prog->dev = NULL;
-       prog->n_pages = 0;
-       prog->bus_addr = 0;
-}
-
-/* dma_region */
-
-/**
- * dma_region_init - clear out all fields but do not allocate anything
- */
-void dma_region_init(struct dma_region *dma)
-{
-       dma->kvirt = NULL;
-       dma->dev = NULL;
-       dma->n_pages = 0;
-       dma->n_dma_pages = 0;
-       dma->sglist = NULL;
-}
-
-/**
- * dma_region_alloc - allocate the buffer and map it to the IOMMU
- */
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
-                    struct pci_dev *dev, int direction)
-{
-       unsigned int i;
-
-       /* round up to page size */
-       n_bytes = PAGE_ALIGN(n_bytes);
-
-       dma->n_pages = n_bytes >> PAGE_SHIFT;
-
-       dma->kvirt = vmalloc_32(n_bytes);
-       if (!dma->kvirt) {
-               printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
-               goto err;
-       }
-
-       /* Clear the ram out, no junk to the user */
-       memset(dma->kvirt, 0, n_bytes);
-
-       /* allocate scatter/gather list */
-       dma->sglist = vmalloc(dma->n_pages * sizeof(*dma->sglist));
-       if (!dma->sglist) {
-               printk(KERN_ERR "dma_region_alloc: vmalloc(sglist) failed\n");
-               goto err;
-       }
-
-       sg_init_table(dma->sglist, dma->n_pages);
-
-       /* fill scatter/gather list with pages */
-       for (i = 0; i < dma->n_pages; i++) {
-               unsigned long va =
-                   (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
-
-               sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va),
-                               PAGE_SIZE, 0);
-       }
-
-       /* map sglist to the IOMMU */
-       dma->n_dma_pages =
-           pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
-
-       if (dma->n_dma_pages == 0) {
-               printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
-               goto err;
-       }
-
-       dma->dev = dev;
-       dma->direction = direction;
-
-       return 0;
-
-      err:
-       dma_region_free(dma);
-       return -ENOMEM;
-}
-
-/**
- * dma_region_free - unmap and free the buffer
- */
-void dma_region_free(struct dma_region *dma)
-{
-       if (dma->n_dma_pages) {
-               pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
-                            dma->direction);
-               dma->n_dma_pages = 0;
-               dma->dev = NULL;
-       }
-
-       vfree(dma->sglist);
-       dma->sglist = NULL;
-
-       vfree(dma->kvirt);
-       dma->kvirt = NULL;
-       dma->n_pages = 0;
-}
-
-/* find the scatterlist index and remaining offset corresponding to a
-   given offset from the beginning of the buffer */
-static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
-                                 unsigned int start, unsigned long *rem)
-{
-       int i;
-       unsigned long off = offset;
-
-       for (i = start; i < dma->n_dma_pages; i++) {
-               if (off < sg_dma_len(&dma->sglist[i])) {
-                       *rem = off;
-                       break;
-               }
-
-               off -= sg_dma_len(&dma->sglist[i]);
-       }
-
-       BUG_ON(i >= dma->n_dma_pages);
-
-       return i;
-}
-
-/**
- * dma_region_offset_to_bus - get bus address of an offset within a DMA region
- *
- * Returns the DMA bus address of the byte with the given @offset relative to
- * the beginning of the @dma.
- */
-dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
-                                   unsigned long offset)
-{
-       unsigned long rem = 0;
-
-       struct scatterlist *sg =
-           &dma->sglist[dma_region_find(dma, offset, 0, &rem)];
-       return sg_dma_address(sg) + rem;
-}
-
-/**
- * dma_region_sync_for_cpu - sync the CPU's view of the buffer
- */
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
-                            unsigned long len)
-{
-       int first, last;
-       unsigned long rem = 0;
-
-       if (!len)
-               len = 1;
-
-       first = dma_region_find(dma, offset, 0, &rem);
-       last = dma_region_find(dma, rem + len - 1, first, &rem);
-
-       pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
-                               dma->direction);
-}
-
-/**
- * dma_region_sync_for_device - sync the IO bus' view of the buffer
- */
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
-                               unsigned long len)
-{
-       int first, last;
-       unsigned long rem = 0;
-
-       if (!len)
-               len = 1;
-
-       first = dma_region_find(dma, offset, 0, &rem);
-       last = dma_region_find(dma, rem + len - 1, first, &rem);
-
-       pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
-                                  last - first + 1, dma->direction);
-}
-
-#ifdef CONFIG_MMU
-
-static int dma_region_pagefault(struct vm_area_struct *vma,
-                               struct vm_fault *vmf)
-{
-       struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
-
-       if (!dma->kvirt)
-               return VM_FAULT_SIGBUS;
-
-       if (vmf->pgoff >= dma->n_pages)
-               return VM_FAULT_SIGBUS;
-
-       vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
-       get_page(vmf->page);
-       return 0;
-}
-
-static const struct vm_operations_struct dma_region_vm_ops = {
-       .fault = dma_region_pagefault,
-};
-
-/**
- * dma_region_mmap - map the buffer into a user space process
- */
-int dma_region_mmap(struct dma_region *dma, struct file *file,
-                   struct vm_area_struct *vma)
-{
-       unsigned long size;
-
-       if (!dma->kvirt)
-               return -EINVAL;
-
-       /* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
-       if (vma->vm_pgoff != 0)
-               return -EINVAL;
-
-       /* check the length */
-       size = vma->vm_end - vma->vm_start;
-       if (size > (dma->n_pages << PAGE_SHIFT))
-               return -EINVAL;
-
-       vma->vm_ops = &dma_region_vm_ops;
-       vma->vm_private_data = dma;
-       vma->vm_file = file;
-       vma->vm_flags |= VM_RESERVED | VM_ALWAYSDUMP;
-
-       return 0;
-}
-
-#else                          /* CONFIG_MMU */
-
-int dma_region_mmap(struct dma_region *dma, struct file *file,
-                   struct vm_area_struct *vma)
-{
-       return -EINVAL;
-}
-
-#endif                         /* CONFIG_MMU */
diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h
deleted file mode 100644 (file)
index 467373c..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * DMA region bookkeeping routines
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#ifndef IEEE1394_DMA_H
-#define IEEE1394_DMA_H
-
-#include <asm/types.h>
-
-struct file;
-struct pci_dev;
-struct scatterlist;
-struct vm_area_struct;
-
-/**
- * struct dma_prog_region - small contiguous DMA buffer
- * @kvirt:    kernel virtual address
- * @dev:      PCI device
- * @n_pages:  number of kernel pages
- * @bus_addr: base bus address
- *
- * a small, physically contiguous DMA buffer with random-access, synchronous
- * usage characteristics
- */
-struct dma_prog_region {
-       unsigned char *kvirt;
-       struct pci_dev *dev;
-       unsigned int n_pages;
-       dma_addr_t bus_addr;
-};
-
-/* clear out all fields but do not allocate any memory */
-void dma_prog_region_init(struct dma_prog_region *prog);
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
-                         struct pci_dev *dev);
-void dma_prog_region_free(struct dma_prog_region *prog);
-
-static inline dma_addr_t dma_prog_region_offset_to_bus(
-               struct dma_prog_region *prog, unsigned long offset)
-{
-       return prog->bus_addr + offset;
-}
-
-/**
- * struct dma_region - large non-contiguous DMA buffer
- * @virt:        kernel virtual address
- * @dev:         PCI device
- * @n_pages:     number of kernel pages
- * @n_dma_pages: number of IOMMU pages
- * @sglist:      IOMMU mapping
- * @direction:   PCI_DMA_TODEVICE, etc.
- *
- * a large, non-physically-contiguous DMA buffer with streaming, asynchronous
- * usage characteristics
- */
-struct dma_region {
-       unsigned char *kvirt;
-       struct pci_dev *dev;
-       unsigned int n_pages;
-       unsigned int n_dma_pages;
-       struct scatterlist *sglist;
-       int direction;
-};
-
-void dma_region_init(struct dma_region *dma);
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
-                    struct pci_dev *dev, int direction);
-void dma_region_free(struct dma_region *dma);
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
-                            unsigned long len);
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
-                               unsigned long len);
-int  dma_region_mmap(struct dma_region *dma, struct file *file,
-                    struct vm_area_struct *vma);
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
-                                   unsigned long offset);
-
-/**
- * dma_region_i - macro to index into a DMA region (or dma_prog_region)
- */
-#define dma_region_i(_dma, _type, _index) \
-       ( ((_type*) ((_dma)->kvirt)) + (_index) )
-
-#endif /* IEEE1394_DMA_H */
diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h
deleted file mode 100644 (file)
index 18b92cb..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * dv1394-private.h - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *   video1394.h - driver for OHCI 1394 boards
- *   Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                          Peter Schlaile <udbz@rz.uni-karlsruhe.de>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DV_1394_PRIVATE_H
-#define _DV_1394_PRIVATE_H
-
-#include "ieee1394.h"
-#include "ohci1394.h"
-#include "dma.h"
-
-/* data structures private to the dv1394 driver */
-/* none of this is exposed to user-space */
-
-
-/*
-   the 8-byte CIP (Common Isochronous Packet) header that precedes
-   each packet of DV data.
-
-   See the IEC 61883 standard.
-*/
-
-struct CIP_header { unsigned char b[8]; };
-
-static inline void fill_cip_header(struct CIP_header *cip,
-                                  unsigned char source_node_id,
-                                  unsigned long counter,
-                                  enum pal_or_ntsc format,
-                                  unsigned long timestamp)
-{
-       cip->b[0] = source_node_id;
-       cip->b[1] = 0x78; /* packet size in quadlets (480/4) - even for empty packets! */
-       cip->b[2] = 0x00;
-       cip->b[3] = counter;
-
-       cip->b[4] = 0x80; /* const */
-
-       switch(format) {
-       case DV1394_PAL:
-               cip->b[5] = 0x80;
-               break;
-       case DV1394_NTSC:
-               cip->b[5] = 0x00;
-               break;
-       }
-
-       cip->b[6] = timestamp >> 8;
-       cip->b[7] = timestamp & 0xFF;
-}
-
-
-
-/*
-   DMA commands used to program the OHCI's DMA engine
-
-   See the Texas Instruments OHCI 1394 chipset documentation.
-*/
-
-struct output_more_immediate { __le32 q[8]; };
-struct output_more { __le32 q[4]; };
-struct output_last { __le32 q[4]; };
-struct input_more { __le32 q[4]; };
-struct input_last { __le32 q[4]; };
-
-/* outputs */
-
-static inline void fill_output_more_immediate(struct output_more_immediate *omi,
-                                             unsigned char tag,
-                                             unsigned char channel,
-                                             unsigned char sync_tag,
-                                             unsigned int  payload_size)
-{
-       omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */
-       omi->q[1] = cpu_to_le32(0);
-       omi->q[2] = cpu_to_le32(0);
-       omi->q[3] = cpu_to_le32(0);
-
-       /* IT packet header */
-       omi->q[4] = cpu_to_le32(  (0x0 << 16)  /* IEEE1394_SPEED_100 */
-                                 | (tag << 14)
-                                 | (channel << 8)
-                                 | (TCODE_ISO_DATA << 4)
-                                 | (sync_tag) );
-
-       /* reserved field; mimic behavior of my Sony DSR-40 */
-       omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0);
-
-       omi->q[6] = cpu_to_le32(0);
-       omi->q[7] = cpu_to_le32(0);
-}
-
-static inline void fill_output_more(struct output_more *om,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       om->q[0] = cpu_to_le32(data_size);
-       om->q[1] = cpu_to_le32(data_phys_addr);
-       om->q[2] = cpu_to_le32(0);
-       om->q[3] = cpu_to_le32(0);
-}
-
-static inline void fill_output_last(struct output_last *ol,
-                                   int want_timestamp,
-                                   int want_interrupt,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       u32 temp = 0;
-       temp |= 1 << 28; /* OUTPUT_LAST */
-
-       if (want_timestamp) /* controller will update timestamp at DMA time */
-               temp |= 1 << 27;
-
-       if (want_interrupt)
-               temp |= 3 << 20;
-
-       temp |= 3 << 18; /* must take branch */
-       temp |= data_size;
-
-       ol->q[0] = cpu_to_le32(temp);
-       ol->q[1] = cpu_to_le32(data_phys_addr);
-       ol->q[2] = cpu_to_le32(0);
-       ol->q[3] = cpu_to_le32(0);
-}
-
-/* inputs */
-
-static inline void fill_input_more(struct input_more *im,
-                                  int want_interrupt,
-                                  unsigned int data_size,
-                                  unsigned long data_phys_addr)
-{
-       u32 temp =  2 << 28; /* INPUT_MORE */
-       temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
-       if (want_interrupt)
-               temp |= 0 << 20; /* interrupts, i=0 in packet-per-buffer mode */
-       temp |= 0x0 << 16; /* disable branch to address for packet-per-buffer mode */
-                              /* disable wait on sync field, not used in DV :-( */
-               temp |= data_size;
-
-       im->q[0] = cpu_to_le32(temp);
-       im->q[1] = cpu_to_le32(data_phys_addr);
-       im->q[2] = cpu_to_le32(0); /* branchAddress and Z not use in packet-per-buffer mode */
-       im->q[3] = cpu_to_le32(0); /* xferStatus & resCount, resCount must be initialize to data_size */
-}
-static inline void fill_input_last(struct input_last *il,
-                                   int want_interrupt,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       u32 temp =  3 << 28; /* INPUT_LAST */
-       temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
-       if (want_interrupt)
-               temp |= 3 << 20; /* enable interrupts */
-       temp |= 0xC << 16; /* enable branch to address */
-                              /* disable wait on sync field, not used in DV :-( */
-       temp |= data_size;
-
-       il->q[0] = cpu_to_le32(temp);
-       il->q[1] = cpu_to_le32(data_phys_addr);
-       il->q[2] = cpu_to_le32(1); /* branchAddress (filled in later) and Z = 1 descriptor in next block */
-       il->q[3] = cpu_to_le32(data_size); /* xferStatus & resCount, resCount must be initialize to data_size */
-}
-
-
-
-/*
-   A "DMA descriptor block" consists of several contiguous DMA commands.
-   struct DMA_descriptor_block encapsulates all of the commands necessary
-   to send one packet of DV data.
-
-   There are three different types of these blocks:
-
-        1) command to send an empty packet (CIP header only, no DV data):
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_LAST           <-- points to the CIP header
-
-       2) command to send a full packet when the DV data payload does NOT
-          cross a page boundary:
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_MORE           <-- points to the CIP header
-           OUTPUT_LAST           <-- points to entire DV data payload
-
-       3) command to send a full packet when the DV payload DOES cross
-          a page boundary:
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_MORE           <-- points to the CIP header
-           OUTPUT_MORE           <-- points to first part of DV data payload
-           OUTPUT_LAST           <-- points to second part of DV data payload
-
-   This struct describes all three block types using unions.
-
-   !!! It is vital that an even number of these descriptor blocks fit on one
-   page of memory, since a block cannot cross a page boundary !!!
-
- */
-
-struct DMA_descriptor_block {
-
-       union {
-               struct {
-                       /*  iso header, common to all output block types */
-                       struct output_more_immediate omi;
-
-                       union {
-                               /* empty packet */
-                               struct {
-                                       struct output_last ol;  /* CIP header */
-                               } empty;
-
-                               /* full packet */
-                               struct {
-                                       struct output_more om;  /* CIP header */
-
-                                       union {
-                                              /* payload does not cross page boundary */
-                                               struct {
-                                                       struct output_last ol;  /* data payload */
-                                               } nocross;
-
-                                              /* payload crosses page boundary */
-                                               struct {
-                                                       struct output_more om;  /* data payload */
-                                                       struct output_last ol;  /* data payload */
-                                               } cross;
-                                       } u;
-
-                               } full;
-                       } u;
-               } out;
-
-               struct {
-                       struct input_last il;
-               } in;
-
-       } u;
-
-       /* ensure that PAGE_SIZE % sizeof(struct DMA_descriptor_block) == 0
-          by padding out to 128 bytes */
-       u32 __pad__[12];
-};
-
-
-/* struct frame contains all data associated with one frame in the
-   ringbuffer these are allocated when the DMA context is initialized
-   do_dv1394_init().  They are re-used after the card finishes
-   transmitting the frame. */
-
-struct video_card; /* forward declaration */
-
-struct frame {
-
-       /* points to the struct video_card that owns this frame */
-       struct video_card *video;
-
-       /* index of this frame in video_card->frames[] */
-       unsigned int frame_num;
-
-       /* FRAME_CLEAR - DMA program not set up, waiting for data
-          FRAME_READY - DMA program written, ready to transmit
-
-          Changes to these should be locked against the interrupt
-       */
-       enum {
-               FRAME_CLEAR = 0,
-               FRAME_READY
-       } state;
-
-       /* whether this frame has been DMA'ed already; used only from
-          the IRQ handler to determine whether the frame can be reset */
-       int done;
-
-
-       /* kernel virtual pointer to the start of this frame's data in
-          the user ringbuffer. Use only for CPU access; to get the DMA
-          bus address you must go through the video->user_dma mapping */
-       unsigned long data;
-
-       /* Max # of packets per frame */
-#define MAX_PACKETS 500
-
-
-       /* a PAGE_SIZE memory pool for allocating CIP headers
-          !header_pool must be aligned to PAGE_SIZE! */
-       struct CIP_header *header_pool;
-       dma_addr_t         header_pool_dma;
-
-
-       /* a physically contiguous memory pool for allocating DMA
-          descriptor blocks; usually around 64KB in size
-          !descriptor_pool must be aligned to PAGE_SIZE! */
-       struct DMA_descriptor_block *descriptor_pool;
-       dma_addr_t                   descriptor_pool_dma;
-       unsigned long                descriptor_pool_size;
-
-
-       /* # of packets allocated for this frame */
-       unsigned int n_packets;
-
-
-       /* below are several pointers (kernel virtual addresses, not
-          DMA bus addresses) to parts of the DMA program.  These are
-          set each time the DMA program is written in
-          frame_prepare(). They are used later on, e.g. from the
-          interrupt handler, to check the status of the frame */
-
-       /* points to status/timestamp field of first DMA packet */
-       /* (we'll check it later to monitor timestamp accuracy) */
-       __le32 *frame_begin_timestamp;
-
-       /* the timestamp we assigned to the first packet in the frame */
-       u32 assigned_timestamp;
-
-       /* pointer to the first packet's CIP header (where the timestamp goes) */
-       struct CIP_header *cip_syt1;
-
-       /* pointer to the second packet's CIP header
-          (only set if the first packet was empty) */
-       struct CIP_header *cip_syt2;
-
-       /* in order to figure out what caused an interrupt,
-          store pointers to the status fields of the two packets
-          that can cause interrupts. We'll check these from the
-          interrupt handler.
-       */
-       __le32 *mid_frame_timestamp;
-       __le32 *frame_end_timestamp;
-
-       /* branch address field of final packet. This is effectively
-          the "tail" in the chain of DMA descriptor blocks.
-          We will fill it with the address of the first DMA descriptor
-          block in the subsequent frame, once it is ready.
-       */
-       __le32 *frame_end_branch;
-
-       /* the number of descriptors in the first descriptor block
-          of the frame. Needed to start DMA */
-       int first_n_descriptors;
-};
-
-
-struct packet {
-       __le16  timestamp;
-       u16     invalid;
-       u16     iso_header;
-       __le16  data_length;
-       u32     cip_h1;
-       u32     cip_h2;
-       unsigned char data[480];
-       unsigned char padding[16]; /* force struct size =512 for page alignment */
-};
-
-
-/* allocate/free a frame */
-static struct frame* frame_new(unsigned int frame_num, struct video_card *video);
-static void frame_delete(struct frame *f);
-
-/* reset f so that it can be used again */
-static void frame_reset(struct frame *f);
-
-/* struct video_card contains all data associated with one instance
-   of the dv1394 driver
-*/
-enum modes {
-       MODE_RECEIVE,
-       MODE_TRANSMIT
-};
-
-struct video_card {
-
-       /* ohci card to which this instance corresponds */
-       struct ti_ohci *ohci;
-
-       /* OHCI card id; the link between the VFS inode and a specific video_card
-          (essentially the device minor number) */
-       int id;
-
-       /* entry in dv1394_cards */
-       struct list_head list;
-
-       /* OHCI card IT DMA context number, -1 if not in use */
-       int ohci_it_ctx;
-       struct ohci1394_iso_tasklet it_tasklet;
-
-       /* register offsets for current IT DMA context, 0 if not in use */
-       u32 ohci_IsoXmitContextControlSet;
-       u32 ohci_IsoXmitContextControlClear;
-       u32 ohci_IsoXmitCommandPtr;
-
-       /* OHCI card IR DMA context number, -1 if not in use */
-       struct ohci1394_iso_tasklet ir_tasklet;
-       int ohci_ir_ctx;
-
-       /* register offsets for current IR DMA context, 0 if not in use */
-       u32 ohci_IsoRcvContextControlSet;
-       u32 ohci_IsoRcvContextControlClear;
-       u32 ohci_IsoRcvCommandPtr;
-       u32 ohci_IsoRcvContextMatch;
-
-
-       /* CONCURRENCY CONTROL */
-
-       /* there are THREE levels of locking associated with video_card. */
-
-       /*
-          1) the 'open' flag - this prevents more than one process from
-          opening the device. (the driver currently assumes only one opener).
-          This is a regular int, but use test_and_set_bit() (on bit zero) 
-          for atomicity.
-        */
-       unsigned long open;
-
-       /*
-          2) the spinlock - this provides mutual exclusion between the interrupt
-          handler and process-context operations. Generally you must take the
-          spinlock under the following conditions:
-            1) DMA (and hence the interrupt handler) may be running
-            AND
-            2) you need to operate on the video_card, especially active_frame
-
-            It is OK to play with video_card without taking the spinlock if
-            you are certain that DMA is not running. Even if DMA is running,
-            it is OK to *read* active_frame with the lock, then drop it
-            immediately. This is safe because the interrupt handler will never
-            advance active_frame onto a frame that is not READY (and the spinlock
-            must be held while marking a frame READY).
-
-            spinlock is also used to protect ohci_it_ctx and ohci_ir_ctx,
-            which can be accessed from both process and interrupt context
-        */
-       spinlock_t spinlock;
-
-       /* flag to prevent spurious interrupts (which OHCI seems to
-          generate a lot :) from accessing the struct */
-       int dma_running;
-
-       /*
-         3) the sleeping mutex 'mtx' - this is used from process context only,
-         to serialize various operations on the video_card. Even though only one
-         open() is allowed, we still need to prevent multiple threads of execution
-         from entering calls like read, write, ioctl, etc.
-
-         I honestly can't think of a good reason to use dv1394 from several threads
-         at once, but we need to serialize anyway to prevent oopses =).
-
-         NOTE: if you need both spinlock and mtx, take mtx first to avoid deadlock!
-        */
-       struct mutex mtx;
-
-       /* people waiting for buffer space, please form a line here... */
-       wait_queue_head_t waitq;
-
-       /* support asynchronous I/O signals (SIGIO) */
-       struct fasync_struct *fasync;
-
-       /* the large, non-contiguous (rvmalloc()) ringbuffer for DV
-           data, exposed to user-space via mmap() */
-       unsigned long      dv_buf_size;
-       struct dma_region  dv_buf;
-
-       /* next byte in the ringbuffer that a write() call will fill */
-       size_t write_off;
-
-       struct frame *frames[DV1394_MAX_FRAMES];
-
-       /* n_frames also serves as an indicator that this struct video_card is
-          initialized and ready to run DMA buffers */
-
-       int n_frames;
-
-       /* this is the frame that is currently "owned" by the OHCI DMA controller
-          (set to -1 iff DMA is not running)
-
-          ! must lock against the interrupt handler when accessing it !
-
-          RULES:
-
-              Only the interrupt handler may change active_frame if DMA
-                 is running; if not, process may change it
-
-              If the next frame is READY, the interrupt handler will advance
-              active_frame when the current frame is finished.
-
-              If the next frame is CLEAR, the interrupt handler will re-transmit
-              the current frame, and the dropped_frames counter will be  incremented.
-
-              The interrupt handler will NEVER advance active_frame to a
-              frame that is not READY.
-       */
-       int active_frame;
-       int first_run;
-
-       /* the same locking rules apply to these three fields also: */
-
-       /* altered ONLY from process context. Must check first_clear_frame->state;
-          if it's READY, that means the ringbuffer is full with READY frames;
-          if it's CLEAR, that means one or more ringbuffer frames are CLEAR */
-       unsigned int first_clear_frame;
-
-       /* altered both by process and interrupt */
-       unsigned int n_clear_frames;
-
-       /* only altered by the interrupt */
-       unsigned int dropped_frames;
-
-
-
-       /* the CIP accumulator and continuity counter are properties
-          of the DMA stream as a whole (not a single frame), so they
-          are stored here in the video_card */
-
-       unsigned long cip_accum;
-       unsigned long cip_n, cip_d;
-       unsigned int syt_offset;
-       unsigned int continuity_counter;
-
-       enum pal_or_ntsc pal_or_ntsc;
-
-       /* redundant, but simplifies the code somewhat */
-       unsigned int frame_size; /* in bytes */
-
-       /* the isochronous channel to use, -1 if video card is inactive */
-       int channel;
-
-
-       /* physically contiguous packet ringbuffer for receive */
-       struct dma_region packet_buf;
-       unsigned long  packet_buf_size;
-
-       unsigned int current_packet;
-       int first_frame;        /* received first start frame marker? */
-       enum modes mode;
-};
-
-/*
-   if the video_card is not initialized, then the ONLY fields that are valid are:
-   ohci
-   open
-   n_frames
-*/
-
-static inline int video_card_initialized(struct video_card *v)
-{
-       return v->n_frames > 0;
-}
-
-static int do_dv1394_init(struct video_card *video, struct dv1394_init *init);
-static int do_dv1394_init_default(struct video_card *video);
-static void do_dv1394_shutdown(struct video_card *video, int free_user_buf);
-
-
-/* NTSC empty packet rate accurate to within 0.01%,
-   calibrated against a Sony DSR-40 DVCAM deck */
-
-#define CIP_N_NTSC   68000000
-#define CIP_D_NTSC 1068000000
-
-#define CIP_N_PAL  1
-#define CIP_D_PAL 16
-
-#endif /* _DV_1394_PRIVATE_H */
-
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
deleted file mode 100644 (file)
index c5a031b..0000000
+++ /dev/null
@@ -1,2584 +0,0 @@
-/*
- * dv1394.c - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *  video1394.c - video driver for OHCI 1394 boards
- *  Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
-  OVERVIEW
-
-  I designed dv1394 as a "pipe" that you can use to shoot DV onto a
-  FireWire bus. In transmission mode, dv1394 does the following:
-
-   1. accepts contiguous frames of DV data from user-space, via write()
-      or mmap() (see dv1394.h for the complete API)
-   2. wraps IEC 61883 packets around the DV data, inserting
-      empty synchronization packets as necessary
-   3. assigns accurate SYT timestamps to the outgoing packets
-   4. shoots them out using the OHCI card's IT DMA engine
-
-   Thanks to Dan Dennedy, we now have a receive mode that does the following:
-
-   1. accepts raw IEC 61883 packets from the OHCI card
-   2. re-assembles the DV data payloads into contiguous frames,
-      discarding empty packets
-   3. sends the DV data to user-space via read() or mmap()
-*/
-
-/*
-  TODO:
-
-  - tunable frame-drop behavior: either loop last frame, or halt transmission
-
-  - use a scatter/gather buffer for DMA programs (f->descriptor_pool)
-    so that we don't rely on allocating 64KB of contiguous kernel memory
-    via pci_alloc_consistent()
-
-  DONE:
-  - during reception, better handling of dropped frames and continuity errors
-  - during reception, prevent DMA from bypassing the irq tasklets
-  - reduce irq rate during reception (1/250 packets).
-  - add many more internal buffers during reception with scatter/gather dma.
-  - add dbc (continuity) checking on receive, increment status.dropped_frames
-    if not continuous.
-  - restart IT DMA after a bus reset
-  - safely obtain and release ISO Tx channels in cooperation with OHCI driver
-  - map received DIF blocks to their proper location in DV frame (ensure
-    recovery if dropped packet)
-  - handle bus resets gracefully (OHCI card seems to take care of this itself(!))
-  - do not allow resizing the user_buf once allocated; eliminate nuke_buffer_mappings
-  - eliminated #ifdef DV1394_DEBUG_LEVEL by inventing macros debug_printk and irq_printk
-  - added wmb() and mb() to places where PCI read/write ordering needs to be enforced
-  - set video->id correctly
-  - store video_cards in an array indexed by OHCI card ID, rather than a list
-  - implement DMA context allocation to cooperate with other users of the OHCI
-  - fix all XXX showstoppers
-  - disable IR/IT DMA interrupts on shutdown
-  - flush pci writes to the card by issuing a read
-  - character device dispatching
-  - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
-  - keep all video_cards in a list (for open() via chardev), set file->private_data = video
-  - dv1394_poll should indicate POLLIN when receiving buffers are available
-  - add proc fs interface to set cip_n, cip_d, syt_offset, and video signal
-  - expose xmit and recv as separate devices (not exclusive)
-  - expose NTSC and PAL as separate devices (can be overridden)
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-
-#include "dv1394.h"
-#include "dv1394-private.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "ohci1394.h"
-
-/* DEBUG LEVELS:
-   0 - no debugging messages
-   1 - some debugging messages, but none during DMA frame transmission
-   2 - lots of messages, including during DMA frame transmission
-       (will cause underflows if your machine is too slow!)
-*/
-
-#define DV1394_DEBUG_LEVEL 0
-
-/* for debugging use ONLY: allow more than one open() of the device */
-/* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */
-
-#if DV1394_DEBUG_LEVEL >= 2
-#define irq_printk( args... ) printk( args )
-#else
-#define irq_printk( args... ) do {} while (0)
-#endif
-
-#if DV1394_DEBUG_LEVEL >= 1
-#define debug_printk( args... ) printk( args)
-#else
-#define debug_printk( args... ) do {} while (0)
-#endif
-
-/* issue a dummy PCI read to force the preceding write
-   to be posted to the PCI bus immediately */
-
-static inline void flush_pci_write(struct ti_ohci *ohci)
-{
-       mb();
-       reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static void it_tasklet_func(unsigned long data);
-static void ir_tasklet_func(unsigned long data);
-
-#ifdef CONFIG_COMPAT
-static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
-                              unsigned long arg);
-#endif
-
-/* GLOBAL DATA */
-
-/* list of all video_cards */
-static LIST_HEAD(dv1394_cards);
-static DEFINE_SPINLOCK(dv1394_cards_lock);
-
-/* translate from a struct file* to the corresponding struct video_card* */
-
-static inline struct video_card* file_to_video_card(struct file *file)
-{
-       return file->private_data;
-}
-
-/*** FRAME METHODS *********************************************************/
-
-static void frame_reset(struct frame *f)
-{
-       f->state = FRAME_CLEAR;
-       f->done = 0;
-       f->n_packets = 0;
-       f->frame_begin_timestamp = NULL;
-       f->assigned_timestamp = 0;
-       f->cip_syt1 = NULL;
-       f->cip_syt2 = NULL;
-       f->mid_frame_timestamp = NULL;
-       f->frame_end_timestamp = NULL;
-       f->frame_end_branch = NULL;
-}
-
-static struct frame* frame_new(unsigned int frame_num, struct video_card *video)
-{
-       struct frame *f = kmalloc(sizeof(*f), GFP_KERNEL);
-       if (!f)
-               return NULL;
-
-       f->video = video;
-       f->frame_num = frame_num;
-
-       f->header_pool = pci_alloc_consistent(f->video->ohci->dev, PAGE_SIZE, &f->header_pool_dma);
-       if (!f->header_pool) {
-               printk(KERN_ERR "dv1394: failed to allocate CIP header pool\n");
-               kfree(f);
-               return NULL;
-       }
-
-       debug_printk("dv1394: frame_new: allocated CIP header pool at virt 0x%08lx (contig) dma 0x%08lx size %ld\n",
-                    (unsigned long) f->header_pool, (unsigned long) f->header_pool_dma, PAGE_SIZE);
-
-       f->descriptor_pool_size = MAX_PACKETS * sizeof(struct DMA_descriptor_block);
-       /* make it an even # of pages */
-       f->descriptor_pool_size += PAGE_SIZE - (f->descriptor_pool_size%PAGE_SIZE);
-
-       f->descriptor_pool = pci_alloc_consistent(f->video->ohci->dev,
-                                                 f->descriptor_pool_size,
-                                                 &f->descriptor_pool_dma);
-       if (!f->descriptor_pool) {
-               pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma);
-               kfree(f);
-               return NULL;
-       }
-
-       debug_printk("dv1394: frame_new: allocated DMA program memory at virt 0x%08lx (contig) dma 0x%08lx size %ld\n",
-                    (unsigned long) f->descriptor_pool, (unsigned long) f->descriptor_pool_dma, f->descriptor_pool_size);
-
-       f->data = 0;
-       frame_reset(f);
-
-       return f;
-}
-
-static void frame_delete(struct frame *f)
-{
-       pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma);
-       pci_free_consistent(f->video->ohci->dev, f->descriptor_pool_size, f->descriptor_pool, f->descriptor_pool_dma);
-       kfree(f);
-}
-
-
-
-
-/*
-   frame_prepare() - build the DMA program for transmitting
-
-   Frame_prepare() must be called OUTSIDE the video->spinlock.
-   However, frame_prepare() must still be serialized, so
-   it should be called WITH the video->mtx taken.
- */
-
-static void frame_prepare(struct video_card *video, unsigned int this_frame)
-{
-       struct frame *f = video->frames[this_frame];
-       int last_frame;
-
-       struct DMA_descriptor_block *block;
-       dma_addr_t block_dma;
-       struct CIP_header *cip;
-       dma_addr_t cip_dma;
-
-       unsigned int n_descriptors, full_packets, packets_per_frame, payload_size;
-
-       /* these flags denote packets that need special attention */
-       int empty_packet, first_packet, last_packet, mid_packet;
-
-       __le32 *branch_address, *last_branch_address = NULL;
-       unsigned long data_p;
-       int first_packet_empty = 0;
-       u32 cycleTimer, ct_sec, ct_cyc, ct_off;
-       unsigned long irq_flags;
-
-       irq_printk("frame_prepare( %d ) ---------------------\n", this_frame);
-
-       full_packets = 0;
-
-
-
-       if (video->pal_or_ntsc == DV1394_PAL)
-               packets_per_frame = DV1394_PAL_PACKETS_PER_FRAME;
-       else
-               packets_per_frame = DV1394_NTSC_PACKETS_PER_FRAME;
-
-       while ( full_packets < packets_per_frame ) {
-               empty_packet = first_packet = last_packet = mid_packet = 0;
-
-               data_p = f->data + full_packets * 480;
-
-               /************************************************/
-               /* allocate a descriptor block and a CIP header */
-               /************************************************/
-
-               /* note: these should NOT cross a page boundary (DMA restriction) */
-
-               if (f->n_packets >= MAX_PACKETS) {
-                       printk(KERN_ERR "dv1394: FATAL ERROR: max packet count exceeded\n");
-                       return;
-               }
-
-               /* the block surely won't cross a page boundary,
-                  since an even number of descriptor_blocks fit on a page */
-               block = &(f->descriptor_pool[f->n_packets]);
-
-               /* DMA address of the block = offset of block relative
-                   to the kernel base address of the descriptor pool
-                   + DMA base address of the descriptor pool */
-               block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-
-
-               /* the whole CIP pool fits on one page, so no worries about boundaries */
-               if ( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool)
-                   > PAGE_SIZE) {
-                       printk(KERN_ERR "dv1394: FATAL ERROR: no room to allocate CIP header\n");
-                       return;
-               }
-
-               cip = &(f->header_pool[f->n_packets]);
-
-               /* DMA address of the CIP header = offset of cip
-                  relative to kernel base address of the header pool
-                  + DMA base address of the header pool */
-               cip_dma = (unsigned long) cip % PAGE_SIZE + f->header_pool_dma;
-
-               /* is this an empty packet? */
-
-               if (video->cip_accum > (video->cip_d - video->cip_n)) {
-                       empty_packet = 1;
-                       payload_size = 8;
-                       video->cip_accum -= (video->cip_d - video->cip_n);
-               } else {
-                       payload_size = 488;
-                       video->cip_accum += video->cip_n;
-               }
-
-               /* there are three important packets each frame:
-
-                  the first packet in the frame - we ask the card to record the timestamp when
-                                                  this packet is actually sent, so we can monitor
-                                                  how accurate our timestamps are. Also, the first
-                                                  packet serves as a semaphore to let us know that
-                                                  it's OK to free the *previous* frame's DMA buffer
-
-                  the last packet in the frame -  this packet is used to detect buffer underflows.
-                                                  if this is the last ready frame, the last DMA block
-                                                  will have a branch back to the beginning of the frame
-                                                  (so that the card will re-send the frame on underflow).
-                                                  if this branch gets taken, we know that at least one
-                                                  frame has been dropped. When the next frame is ready,
-                                                  the branch is pointed to its first packet, and the
-                                                  semaphore is disabled.
-
-                  a "mid" packet slightly before the end of the frame - this packet should trigger
-                                  an interrupt so we can go and assign a timestamp to the first packet
-                                  in the next frame. We don't use the very last packet in the frame
-                                  for this purpose, because that would leave very little time to set
-                                  the timestamp before DMA starts on the next frame.
-               */
-
-               if (f->n_packets == 0) {
-                       first_packet = 1;
-               } else if ( full_packets == (packets_per_frame-1) ) {
-                       last_packet = 1;
-               } else if (f->n_packets == packets_per_frame) {
-                       mid_packet = 1;
-               }
-
-
-               /********************/
-               /* setup CIP header */
-               /********************/
-
-               /* the timestamp will be written later from the
-                  mid-frame interrupt handler. For now we just
-                  store the address of the CIP header(s) that
-                  need a timestamp. */
-
-               /* first packet in the frame needs a timestamp */
-               if (first_packet) {
-                       f->cip_syt1 = cip;
-                       if (empty_packet)
-                               first_packet_empty = 1;
-
-               } else if (first_packet_empty && (f->n_packets == 1) ) {
-                       /* if the first packet was empty, the second
-                          packet's CIP header also needs a timestamp */
-                       f->cip_syt2 = cip;
-               }
-
-               fill_cip_header(cip,
-                               /* the node ID number of the OHCI card */
-                               reg_read(video->ohci, OHCI1394_NodeID) & 0x3F,
-                               video->continuity_counter,
-                               video->pal_or_ntsc,
-                               0xFFFF /* the timestamp is filled in later */);
-
-               /* advance counter, only for full packets */
-               if ( ! empty_packet )
-                       video->continuity_counter++;
-
-               /******************************/
-               /* setup DMA descriptor block */
-               /******************************/
-
-               /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */
-               fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size);
-
-               if (empty_packet) {
-                       /* second descriptor - OUTPUT_LAST for CIP header */
-                       fill_output_last( &(block->u.out.u.empty.ol),
-
-                                         /* want completion status on all interesting packets */
-                                         (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                         /* want interrupts on all interesting packets */
-                                         (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                         sizeof(struct CIP_header), /* data size */
-                                         cip_dma);
-
-                       if (first_packet)
-                               f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                       else if (mid_packet)
-                               f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                       else if (last_packet) {
-                               f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                               f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]);
-                       }
-
-                       branch_address = &(block->u.out.u.empty.ol.q[2]);
-                       n_descriptors = 3;
-                       if (first_packet)
-                               f->first_n_descriptors = n_descriptors;
-
-               } else { /* full packet */
-
-                       /* second descriptor - OUTPUT_MORE for CIP header */
-                       fill_output_more( &(block->u.out.u.full.om),
-                                         sizeof(struct CIP_header), /* data size */
-                                         cip_dma);
-
-
-                       /* third (and possibly fourth) descriptor - for DV data */
-                       /* the 480-byte payload can cross a page boundary; if so,
-                          we need to split it into two DMA descriptors */
-
-                       /* does the 480-byte data payload cross a page boundary? */
-                       if ( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) {
-
-                               /* page boundary crossed */
-
-                               fill_output_more( &(block->u.out.u.full.u.cross.om),
-                                                 /* data size - how much of data_p fits on the first page */
-                                                 PAGE_SIZE - (data_p % PAGE_SIZE),
-
-                                                 /* DMA address of data_p */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p - (unsigned long) video->dv_buf.kvirt));
-
-                               fill_output_last( &(block->u.out.u.full.u.cross.ol),
-
-                                                 /* want completion status on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* want interrupt on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* data size - remaining portion of data_p */
-                                                 480 - (PAGE_SIZE - (data_p % PAGE_SIZE)),
-
-                                                 /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt));
-
-                               if (first_packet)
-                                       f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                               else if (mid_packet)
-                                       f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                               else if (last_packet) {
-                                       f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                                       f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]);
-                               }
-
-                               branch_address = &(block->u.out.u.full.u.cross.ol.q[2]);
-
-                               n_descriptors = 5;
-                               if (first_packet)
-                                       f->first_n_descriptors = n_descriptors;
-
-                               full_packets++;
-
-                       } else {
-                               /* fits on one page */
-
-                               fill_output_last( &(block->u.out.u.full.u.nocross.ol),
-
-                                                 /* want completion status on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* want interrupt on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 480, /* data size (480 bytes of DV data) */
-
-
-                                                 /* DMA address of data_p */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p - (unsigned long) video->dv_buf.kvirt));
-
-                               if (first_packet)
-                                       f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                               else if (mid_packet)
-                                       f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                               else if (last_packet) {
-                                       f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                                       f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]);
-                               }
-
-                               branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]);
-
-                               n_descriptors = 4;
-                               if (first_packet)
-                                       f->first_n_descriptors = n_descriptors;
-
-                               full_packets++;
-                       }
-               }
-
-               /* link this descriptor block into the DMA program by filling in
-                  the branch address of the previous block */
-
-               /* note: we are not linked into the active DMA chain yet */
-
-               if (last_branch_address) {
-                       *(last_branch_address) = cpu_to_le32(block_dma | n_descriptors);
-               }
-
-               last_branch_address = branch_address;
-
-
-               f->n_packets++;
-
-       }
-
-       /* when we first assemble a new frame, set the final branch
-          to loop back up to the top */
-       *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);
-
-       /* make the latest version of this frame visible to the PCI card */
-       dma_region_sync_for_device(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size);
-
-       /* lock against DMA interrupt */
-       spin_lock_irqsave(&video->spinlock, irq_flags);
-
-       f->state = FRAME_READY;
-
-       video->n_clear_frames--;
-
-       last_frame = video->first_clear_frame - 1;
-       if (last_frame == -1)
-               last_frame = video->n_frames-1;
-
-       video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-
-       irq_printk("   frame %d prepared, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n last=%d\n",
-                  this_frame, video->active_frame, video->n_clear_frames, video->first_clear_frame, last_frame);
-
-       irq_printk("   begin_ts %08lx mid_ts %08lx end_ts %08lx end_br %08lx\n",
-                  (unsigned long) f->frame_begin_timestamp,
-                  (unsigned long) f->mid_frame_timestamp,
-                  (unsigned long) f->frame_end_timestamp,
-                  (unsigned long) f->frame_end_branch);
-
-       if (video->active_frame != -1) {
-
-               /* if DMA is already active, we are almost done */
-               /* just link us onto the active DMA chain */
-               if (video->frames[last_frame]->frame_end_branch) {
-                       u32 temp;
-
-                       /* point the previous frame's tail to this frame's head */
-                       *(video->frames[last_frame]->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);
-
-                       /* this write MUST precede the next one, or we could silently drop frames */
-                       wmb();
-
-                       /* disable the want_status semaphore on the last packet */
-                       temp = le32_to_cpu(*(video->frames[last_frame]->frame_end_branch - 2));
-                       temp &= 0xF7CFFFFF;
-                       *(video->frames[last_frame]->frame_end_branch - 2) = cpu_to_le32(temp);
-
-                       /* flush these writes to memory ASAP */
-                       flush_pci_write(video->ohci);
-
-                       /* NOTE:
-                          ideally the writes should be "atomic": if
-                          the OHCI card reads the want_status flag in
-                          between them, we'll falsely report a
-                          dropped frame. Hopefully this window is too
-                          small to really matter, and the consequence
-                          is rather harmless. */
-
-
-                       irq_printk("     new frame %d linked onto DMA chain\n", this_frame);
-
-               } else {
-                       printk(KERN_ERR "dv1394: last frame not ready???\n");
-               }
-
-       } else {
-
-               u32 transmit_sec, transmit_cyc;
-               u32 ts_cyc;
-
-               /* DMA is stopped, so this is the very first frame */
-               video->active_frame = this_frame;
-
-               /* set CommandPtr to address and size of first descriptor block */
-               reg_write(video->ohci, video->ohci_IsoXmitCommandPtr,
-                         video->frames[video->active_frame]->descriptor_pool_dma |
-                         f->first_n_descriptors);
-
-               /* assign a timestamp based on the current cycle time...
-                  We'll tell the card to begin DMA 100 cycles from now,
-                  and assign a timestamp 103 cycles from now */
-
-               cycleTimer = reg_read(video->ohci, OHCI1394_IsochronousCycleTimer);
-
-               ct_sec = cycleTimer >> 25;
-               ct_cyc = (cycleTimer >> 12) & 0x1FFF;
-               ct_off = cycleTimer & 0xFFF;
-
-               transmit_sec = ct_sec;
-               transmit_cyc = ct_cyc + 100;
-
-               transmit_sec += transmit_cyc/8000;
-               transmit_cyc %= 8000;
-
-               ts_cyc = transmit_cyc + 3;
-               ts_cyc %= 8000;
-
-               f->assigned_timestamp = (ts_cyc&0xF) << 12;
-
-               /* now actually write the timestamp into the appropriate CIP headers */
-               if (f->cip_syt1) {
-                       f->cip_syt1->b[6] = f->assigned_timestamp >> 8;
-                       f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF;
-               }
-               if (f->cip_syt2) {
-                       f->cip_syt2->b[6] = f->assigned_timestamp >> 8;
-                       f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF;
-               }
-
-               /* --- start DMA --- */
-
-               /* clear all bits in ContextControl register */
-
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, 0xFFFFFFFF);
-               wmb();
-
-               /* the OHCI card has the ability to start ISO transmission on a
-                  particular cycle (start-on-cycle). This way we can ensure that
-                  the first DV frame will have an accurate timestamp.
-
-                  However, start-on-cycle only appears to work if the OHCI card
-                  is cycle master! Since the consequences of messing up the first
-                  timestamp are minimal*, just disable start-on-cycle for now.
-
-                  * my DV deck drops the first few frames before it "locks in;"
-                    so the first frame having an incorrect timestamp is inconsequential.
-               */
-
-#if 0
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlSet,
-                         (1 << 31) /* enable start-on-cycle */
-                         | ( (transmit_sec & 0x3) << 29)
-                         | (transmit_cyc << 16));
-               wmb();
-#endif
-
-               video->dma_running = 1;
-
-               /* set the 'run' bit */
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, 0x8000);
-               flush_pci_write(video->ohci);
-
-               /* --- DMA should be running now --- */
-
-               debug_printk("    Cycle = %4u ContextControl = %08x CmdPtr = %08x\n",
-                            (reg_read(video->ohci, OHCI1394_IsochronousCycleTimer) >> 12) & 0x1FFF,
-                            reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                            reg_read(video->ohci, video->ohci_IsoXmitCommandPtr));
-
-               debug_printk("    DMA start - current cycle %4u, transmit cycle %4u (%2u), assigning ts cycle %2u\n",
-                            ct_cyc, transmit_cyc, transmit_cyc & 0xF, ts_cyc & 0xF);
-
-#if DV1394_DEBUG_LEVEL >= 2
-               {
-                       /* check if DMA is really running */
-                       int i = 0;
-                       while (i < 20) {
-                               mb();
-                               mdelay(1);
-                               if (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) {
-                                       printk("DMA ACTIVE after %d msec\n", i);
-                                       break;
-                               }
-                               i++;
-                       }
-
-                       printk("set = %08x, cmdPtr = %08x\n",
-                              reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                              reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)
-                              );
-
-                       if ( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) &  (1 << 10)) ) {
-                               printk("DMA did NOT go active after 20ms, event = %x\n",
-                                      reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F);
-                       } else
-                               printk("DMA is RUNNING!\n");
-               }
-#endif
-
-       }
-
-
-       spin_unlock_irqrestore(&video->spinlock, irq_flags);
-}
-
-
-
-/*** RECEIVE FUNCTIONS *****************************************************/
-
-/*
-       frame method put_packet
-
-       map and copy the packet data to its location in the frame
-       based upon DIF section and sequence
-*/
-
-static void inline
-frame_put_packet (struct frame *f, struct packet *p)
-{
-       int section_type = p->data[0] >> 5;           /* section type is in bits 5 - 7 */
-       int dif_sequence = p->data[1] >> 4;           /* dif sequence number is in bits 4 - 7 */
-       int dif_block = p->data[2];
-
-       /* sanity check */
-       if (dif_sequence > 11 || dif_block > 149) return;
-
-       switch (section_type) {
-       case 0:           /* 1 Header block */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480);
-               break;
-
-       case 1:           /* 2 Subcode blocks */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (1 + dif_block) * 80, p->data, 480);
-               break;
-
-       case 2:           /* 3 VAUX blocks */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (3 + dif_block) * 80, p->data, 480);
-               break;
-
-       case 3:           /* 9 Audio blocks interleaved with video */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80, p->data, 480);
-               break;
-
-       case 4:           /* 135 Video blocks interleaved with audio */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (7 + (dif_block / 15) + dif_block) * 80, p->data, 480);
-               break;
-
-       default:           /* we can not handle any other data */
-               break;
-       }
-}
-
-
-static void start_dma_receive(struct video_card *video)
-{
-       if (video->first_run == 1) {
-               video->first_run = 0;
-
-               /* start DMA once all of the frames are READY */
-               video->n_clear_frames = 0;
-               video->first_clear_frame = -1;
-               video->current_packet = 0;
-               video->active_frame = 0;
-
-               /* reset iso recv control register */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF);
-               wmb();
-
-               /* clear bufferFill, set isochHeader and speed (0=100) */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000);
-
-               /* match on all tags, listen on channel */
-               reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel);
-
-               /* address and first descriptor block + Z=1 */
-               reg_write(video->ohci, video->ohci_IsoRcvCommandPtr,
-                         video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */
-               wmb();
-
-               video->dma_running = 1;
-
-               /* run */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000);
-               flush_pci_write(video->ohci);
-
-               debug_printk("dv1394: DMA started\n");
-
-#if DV1394_DEBUG_LEVEL >= 2
-               {
-                       int i;
-
-                       for (i = 0; i < 1000; ++i) {
-                               mdelay(1);
-                               if (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) {
-                                       printk("DMA ACTIVE after %d msec\n", i);
-                                       break;
-                               }
-                       }
-                       if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
-                               printk("DEAD, event = %x\n",
-                                          reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-                       } else
-                               printk("RUNNING!\n");
-               }
-#endif
-       } else if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
-               debug_printk("DEAD, event = %x\n",
-                            reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-
-               /* wake */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-       }
-}
-
-
-/*
-   receive_packets() - build the DMA program for receiving
-*/
-
-static void receive_packets(struct video_card *video)
-{
-       struct DMA_descriptor_block *block = NULL;
-       dma_addr_t block_dma = 0;
-       struct packet *data = NULL;
-       dma_addr_t data_dma = 0;
-       __le32 *last_branch_address = NULL;
-       unsigned long irq_flags;
-       int want_interrupt = 0;
-       struct frame *f = NULL;
-       int i, j;
-
-       spin_lock_irqsave(&video->spinlock, irq_flags);
-
-       for (j = 0; j < video->n_frames; j++) {
-
-               /* connect frames */
-               if (j > 0 && f != NULL && f->frame_end_branch != NULL)
-                       *(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */
-
-               f = video->frames[j];
-
-               for (i = 0; i < MAX_PACKETS; i++) {
-                       /* locate a descriptor block and packet from the buffer */
-                       block = &(f->descriptor_pool[i]);
-                       block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-
-                       data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i;
-                       data_dma = dma_region_offset_to_bus( &video->packet_buf,
-                                                            ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) );
-
-                       /* setup DMA descriptor block */
-                       want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1));
-                       fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma);
-
-                       /* link descriptors */
-                       last_branch_address = f->frame_end_branch;
-
-                       if (last_branch_address != NULL)
-                               *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */
-
-                       f->frame_end_branch = &(block->u.in.il.q[2]);
-               }
-
-       } /* next j */
-
-       spin_unlock_irqrestore(&video->spinlock, irq_flags);
-
-}
-
-
-
-/*** MANAGEMENT FUNCTIONS **************************************************/
-
-static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
-{
-       unsigned long flags, new_buf_size;
-       int i;
-       u64 chan_mask;
-       int retval = -EINVAL;
-
-       debug_printk("dv1394: initialising %d\n", video->id);
-       if (init->api_version != DV1394_API_VERSION)
-               return -EINVAL;
-
-       /* first sanitize all the parameters */
-       if ( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) )
-               return -EINVAL;
-
-       if ( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) )
-               return -EINVAL;
-
-       if ( (init->syt_offset == 0) || (init->syt_offset > 50) )
-               /* default SYT offset is 3 cycles */
-               init->syt_offset = 3;
-
-       if (init->channel > 63)
-               init->channel = 63;
-
-       chan_mask = (u64)1 << init->channel;
-
-       /* calculate what size DMA buffer is needed */
-       if (init->format == DV1394_NTSC)
-               new_buf_size = DV1394_NTSC_FRAME_SIZE * init->n_frames;
-       else
-               new_buf_size = DV1394_PAL_FRAME_SIZE * init->n_frames;
-
-       /* round up to PAGE_SIZE */
-       if (new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE);
-
-       /* don't allow the user to allocate the DMA buffer more than once */
-       if (video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) {
-               printk("dv1394: re-sizing the DMA buffer is not allowed\n");
-               return -EINVAL;
-       }
-
-       /* shutdown the card if it's currently active */
-       /* (the card should not be reset if the parameters are screwy) */
-
-       do_dv1394_shutdown(video, 0);
-
-       /* try to claim the ISO channel */
-       spin_lock_irqsave(&video->ohci->IR_channel_lock, flags);
-       if (video->ohci->ISO_channel_usage & chan_mask) {
-               spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-               retval = -EBUSY;
-               goto err;
-       }
-       video->ohci->ISO_channel_usage |= chan_mask;
-       spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-
-       video->channel = init->channel;
-
-       /* initialize misc. fields of video */
-       video->n_frames = init->n_frames;
-       video->pal_or_ntsc = init->format;
-
-       video->cip_accum = 0;
-       video->continuity_counter = 0;
-
-       video->active_frame = -1;
-       video->first_clear_frame = 0;
-       video->n_clear_frames = video->n_frames;
-       video->dropped_frames = 0;
-
-       video->write_off = 0;
-
-       video->first_run = 1;
-       video->current_packet = -1;
-       video->first_frame = 0;
-
-       if (video->pal_or_ntsc == DV1394_NTSC) {
-               video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_NTSC;
-               video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_NTSC;
-               video->frame_size = DV1394_NTSC_FRAME_SIZE;
-       } else {
-               video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_PAL;
-               video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_PAL;
-               video->frame_size = DV1394_PAL_FRAME_SIZE;
-       }
-
-       video->syt_offset = init->syt_offset;
-
-       /* find and claim DMA contexts on the OHCI card */
-
-       if (video->ohci_it_ctx == -1) {
-               ohci1394_init_iso_tasklet(&video->it_tasklet, OHCI_ISO_TRANSMIT,
-                                         it_tasklet_func, (unsigned long) video);
-
-               if (ohci1394_register_iso_tasklet(video->ohci, &video->it_tasklet) < 0) {
-                       printk(KERN_ERR "dv1394: could not find an available IT DMA context\n");
-                       retval = -EBUSY;
-                       goto err;
-               }
-
-               video->ohci_it_ctx = video->it_tasklet.context;
-               debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx);
-       }
-
-       if (video->ohci_ir_ctx == -1) {
-               ohci1394_init_iso_tasklet(&video->ir_tasklet, OHCI_ISO_RECEIVE,
-                                         ir_tasklet_func, (unsigned long) video);
-
-               if (ohci1394_register_iso_tasklet(video->ohci, &video->ir_tasklet) < 0) {
-                       printk(KERN_ERR "dv1394: could not find an available IR DMA context\n");
-                       retval = -EBUSY;
-                       goto err;
-               }
-               video->ohci_ir_ctx = video->ir_tasklet.context;
-               debug_printk("dv1394: claimed IR DMA context %d\n", video->ohci_ir_ctx);
-       }
-
-       /* allocate struct frames */
-       for (i = 0; i < init->n_frames; i++) {
-               video->frames[i] = frame_new(i, video);
-
-               if (!video->frames[i]) {
-                       printk(KERN_ERR "dv1394: Cannot allocate frame structs\n");
-                       retval = -ENOMEM;
-                       goto err;
-               }
-       }
-
-       if (!video->dv_buf.kvirt) {
-               /* allocate the ringbuffer */
-               retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE);
-               if (retval)
-                       goto err;
-
-               video->dv_buf_size = new_buf_size;
-
-               debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), %lu bytes\n", 
-                            video->n_frames, video->dv_buf.n_pages,
-                            video->dv_buf.n_dma_pages, video->dv_buf_size);
-       }
-
-       /* set up the frame->data pointers */
-       for (i = 0; i < video->n_frames; i++)
-               video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size;
-
-       if (!video->packet_buf.kvirt) {
-               /* allocate packet buffer */
-               video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS;
-               if (video->packet_buf_size % PAGE_SIZE)
-                       video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE);
-
-               retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size,
-                                         video->ohci->dev, PCI_DMA_FROMDEVICE);
-               if (retval)
-                       goto err;
-
-               debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n",
-                                video->n_frames*MAX_PACKETS, video->packet_buf.n_pages,
-                                video->packet_buf.n_dma_pages, video->packet_buf_size);
-       }
-
-       /* set up register offsets for IT context */
-       /* IT DMA context registers are spaced 16 bytes apart */
-       video->ohci_IsoXmitContextControlSet = OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx;
-       video->ohci_IsoXmitContextControlClear = OHCI1394_IsoXmitContextControlClear+16*video->ohci_it_ctx;
-       video->ohci_IsoXmitCommandPtr = OHCI1394_IsoXmitCommandPtr+16*video->ohci_it_ctx;
-
-       /* enable interrupts for IT context */
-       reg_write(video->ohci, OHCI1394_IsoXmitIntMaskSet, (1 << video->ohci_it_ctx));
-       debug_printk("dv1394: interrupts enabled for IT context %d\n", video->ohci_it_ctx);
-
-       /* set up register offsets for IR context */
-       /* IR DMA context registers are spaced 32 bytes apart */
-       video->ohci_IsoRcvContextControlSet = OHCI1394_IsoRcvContextControlSet+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvContextControlClear = OHCI1394_IsoRcvContextControlClear+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvCommandPtr = OHCI1394_IsoRcvCommandPtr+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvContextMatch = OHCI1394_IsoRcvContextMatch+32*video->ohci_ir_ctx;
-
-       /* enable interrupts for IR context */
-       reg_write(video->ohci, OHCI1394_IsoRecvIntMaskSet, (1 << video->ohci_ir_ctx) );
-       debug_printk("dv1394: interrupts enabled for IR context %d\n", video->ohci_ir_ctx);
-
-       return 0;
-
-err:
-       do_dv1394_shutdown(video, 1);
-       return retval;
-}
-
-/* if the user doesn't bother to call ioctl(INIT) before starting
-   mmap() or read()/write(), just give him some default values */
-
-static int do_dv1394_init_default(struct video_card *video)
-{
-       struct dv1394_init init;
-
-       init.api_version = DV1394_API_VERSION;
-       init.n_frames = DV1394_MAX_FRAMES / 4;
-       init.channel = video->channel;
-       init.format = video->pal_or_ntsc;
-       init.cip_n = video->cip_n;
-       init.cip_d = video->cip_d;
-       init.syt_offset = video->syt_offset;
-
-       return do_dv1394_init(video, &init);
-}
-
-/* do NOT call from interrupt context */
-static void stop_dma(struct video_card *video)
-{
-       unsigned long flags;
-       int i;
-
-       /* no interrupts */
-       spin_lock_irqsave(&video->spinlock, flags);
-
-       video->dma_running = 0;
-
-       if ( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) )
-               goto out;
-
-       /* stop DMA if in progress */
-       if ( (video->active_frame != -1) ||
-           (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
-           (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) &  (1 << 10)) ) {
-
-               /* clear the .run bits */
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15));
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15));
-               flush_pci_write(video->ohci);
-
-               video->active_frame = -1;
-               video->first_run = 1;
-
-               /* wait until DMA really stops */
-               i = 0;
-               while (i < 1000) {
-
-                       /* wait 0.1 millisecond */
-                       udelay(100);
-
-                       if ( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
-                           (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear)  & (1 << 10)) ) {
-                               /* still active */
-                               debug_printk("dv1394: stop_dma: DMA not stopped yet\n" );
-                               mb();
-                       } else {
-                               debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10);
-                               break;
-                       }
-
-                       i++;
-               }
-
-               if (i == 1000) {
-                       printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10);
-               }
-       }
-       else
-               debug_printk("dv1394: stop_dma: already stopped.\n");
-
-out:
-       spin_unlock_irqrestore(&video->spinlock, flags);
-}
-
-
-
-static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
-{
-       int i;
-
-       debug_printk("dv1394: shutdown...\n");
-
-       /* stop DMA if in progress */
-       stop_dma(video);
-
-       /* release the DMA contexts */
-       if (video->ohci_it_ctx != -1) {
-               video->ohci_IsoXmitContextControlSet = 0;
-               video->ohci_IsoXmitContextControlClear = 0;
-               video->ohci_IsoXmitCommandPtr = 0;
-
-               /* disable interrupts for IT context */
-               reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx));
-
-               /* remove tasklet */
-               ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
-               debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx);
-               video->ohci_it_ctx = -1;
-       }
-
-       if (video->ohci_ir_ctx != -1) {
-               video->ohci_IsoRcvContextControlSet = 0;
-               video->ohci_IsoRcvContextControlClear = 0;
-               video->ohci_IsoRcvCommandPtr = 0;
-               video->ohci_IsoRcvContextMatch = 0;
-
-               /* disable interrupts for IR context */
-               reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx));
-
-               /* remove tasklet */
-               ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
-               debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx);
-               video->ohci_ir_ctx = -1;
-       }
-
-       /* release the ISO channel */
-       if (video->channel != -1) {
-               u64 chan_mask;
-               unsigned long flags;
-
-               chan_mask = (u64)1 << video->channel;
-
-               spin_lock_irqsave(&video->ohci->IR_channel_lock, flags);
-               video->ohci->ISO_channel_usage &= ~(chan_mask);
-               spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-
-               video->channel = -1;
-       }
-
-       /* free the frame structs */
-       for (i = 0; i < DV1394_MAX_FRAMES; i++) {
-               if (video->frames[i])
-                       frame_delete(video->frames[i]);
-               video->frames[i] = NULL;
-       }
-
-       video->n_frames = 0;
-
-       /* we can't free the DMA buffer unless it is guaranteed that
-          no more user-space mappings exist */
-
-       if (free_dv_buf) {
-               dma_region_free(&video->dv_buf);
-               video->dv_buf_size = 0;
-       }
-
-       /* free packet buffer */
-       dma_region_free(&video->packet_buf);
-       video->packet_buf_size = 0;
-
-       debug_printk("dv1394: shutdown OK\n");
-}
-
-/*
-       **********************************
-       *** MMAP() THEORY OF OPERATION ***
-       **********************************
-
-        The ringbuffer cannot be re-allocated or freed while
-        a user program maintains a mapping of it. (note that a mapping
-       can persist even after the device fd is closed!)
-
-       So, only let the user process allocate the DMA buffer once.
-       To resize or deallocate it, you must close the device file
-       and open it again.
-
-       Previously Dan M. hacked out a scheme that allowed the DMA
-       buffer to change by forcefully unmapping it from the user's
-       address space. It was prone to error because it's very hard to
-       track all the places the buffer could have been mapped (we
-       would have had to walk the vma list of every process in the
-       system to be sure we found all the mappings!). Instead, we
-       force the user to choose one buffer size and stick with
-       it. This small sacrifice is worth the huge reduction in
-       error-prone code in dv1394.
-*/
-
-static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct video_card *video = file_to_video_card(file);
-       int retval = -EINVAL;
-
-       /*
-        * We cannot use the blocking variant mutex_lock here because .mmap
-        * is called with mmap_sem held, while .ioctl, .read, .write acquire
-        * video->mtx and subsequently call copy_to/from_user which will
-        * grab mmap_sem in case of a page fault.
-        */
-       if (!mutex_trylock(&video->mtx))
-               return -EAGAIN;
-
-       if ( ! video_card_initialized(video) ) {
-               retval = do_dv1394_init_default(video);
-               if (retval)
-                       goto out;
-       }
-
-       retval = dma_region_mmap(&video->dv_buf, file, vma);
-out:
-       mutex_unlock(&video->mtx);
-       return retval;
-}
-
-/*** DEVICE FILE INTERFACE *************************************************/
-
-/* no need to serialize, multiple threads OK */
-static unsigned int dv1394_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct video_card *video = file_to_video_card(file);
-       unsigned int mask = 0;
-       unsigned long flags;
-
-       poll_wait(file, &video->waitq, wait);
-
-       spin_lock_irqsave(&video->spinlock, flags);
-       if ( video->n_frames == 0 ) {
-
-       } else if ( video->active_frame == -1 ) {
-               /* nothing going on */
-               mask |= POLLOUT;
-       } else {
-               /* any clear/ready buffers? */
-               if (video->n_clear_frames >0)
-                       mask |= POLLOUT | POLLIN;
-       }
-       spin_unlock_irqrestore(&video->spinlock, flags);
-
-       return mask;
-}
-
-static int dv1394_fasync(int fd, struct file *file, int on)
-{
-       /* I just copied this code verbatim from Alan Cox's mouse driver example
-          (Documentation/DocBook/) */
-
-       struct video_card *video = file_to_video_card(file);
-
-       return fasync_helper(fd, file, on, &video->fasync);
-}
-
-static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-       struct video_card *video = file_to_video_card(file);
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t ret;
-       size_t cnt;
-       unsigned long flags;
-       int target_frame;
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       if ( !video_card_initialized(video) ) {
-               ret = do_dv1394_init_default(video);
-               if (ret) {
-                       mutex_unlock(&video->mtx);
-                       return ret;
-               }
-       }
-
-       ret = 0;
-       add_wait_queue(&video->waitq, &wait);
-
-       while (count > 0) {
-
-               /* must set TASK_INTERRUPTIBLE *before* checking for free
-                  buffers; otherwise we could miss a wakeup if the interrupt
-                  fires between the check and the schedule() */
-
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               target_frame = video->first_clear_frame;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (video->frames[target_frame]->state == FRAME_CLEAR) {
-
-                       /* how much room is left in the target frame buffer */
-                       cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);
-
-               } else {
-                       /* buffer is already used */
-                       cnt = 0;
-               }
-
-               if (cnt > count)
-                       cnt = count;
-
-               if (cnt <= 0) {
-                       /* no room left, gotta wait */
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               break;
-                       }
-
-                       schedule();
-
-                       continue; /* start over from 'while(count > 0)...' */
-               }
-
-               if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) {
-                       if (!ret)
-                               ret = -EFAULT;
-                       break;
-               }
-
-               video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames))
-                               frame_prepare(video, target_frame);
-       }
-
-       remove_wait_queue(&video->waitq, &wait);
-       set_current_state(TASK_RUNNING);
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-
-static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count, loff_t *ppos)
-{
-       struct video_card *video = file_to_video_card(file);
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t ret;
-       size_t cnt;
-       unsigned long flags;
-       int target_frame;
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       if ( !video_card_initialized(video) ) {
-               ret = do_dv1394_init_default(video);
-               if (ret) {
-                       mutex_unlock(&video->mtx);
-                       return ret;
-               }
-               video->continuity_counter = -1;
-
-               receive_packets(video);
-
-               start_dma_receive(video);
-       }
-
-       ret = 0;
-       add_wait_queue(&video->waitq, &wait);
-
-       while (count > 0) {
-
-               /* must set TASK_INTERRUPTIBLE *before* checking for free
-                  buffers; otherwise we could miss a wakeup if the interrupt
-                  fires between the check and the schedule() */
-
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               target_frame = video->first_clear_frame;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (target_frame >= 0 &&
-                       video->n_clear_frames > 0 &&
-                       video->frames[target_frame]->state == FRAME_CLEAR) {
-
-                       /* how much room is left in the target frame buffer */
-                       cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);
-
-               } else {
-                       /* buffer is already used */
-                       cnt = 0;
-               }
-
-               if (cnt > count)
-                       cnt = count;
-
-               if (cnt <= 0) {
-                       /* no room left, gotta wait */
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               break;
-                       }
-
-                       schedule();
-
-                       continue; /* start over from 'while(count > 0)...' */
-               }
-
-               if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) {
-                               if (!ret)
-                                       ret = -EFAULT;
-                               break;
-               }
-
-               video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) {
-                       spin_lock_irqsave(&video->spinlock, flags);
-                       video->n_clear_frames--;
-                       video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-               }
-       }
-
-       remove_wait_queue(&video->waitq, &wait);
-       set_current_state(TASK_RUNNING);
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-
-/*** DEVICE IOCTL INTERFACE ************************************************/
-
-static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct video_card *video = file_to_video_card(file);
-       unsigned long flags;
-       int ret = -EINVAL;
-       void __user *argp = (void __user *)arg;
-
-       DECLARE_WAITQUEUE(wait, current);
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       switch(cmd)
-       {
-       case DV1394_IOC_SUBMIT_FRAMES: {
-               unsigned int n_submit;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = do_dv1394_init_default(video);
-                       if (ret)
-                               goto out;
-               }
-
-               n_submit = (unsigned int) arg;
-
-               if (n_submit > video->n_frames) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               while (n_submit > 0) {
-
-                       add_wait_queue(&video->waitq, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       spin_lock_irqsave(&video->spinlock, flags);
-
-                       /* wait until video->first_clear_frame is really CLEAR */
-                       while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) {
-
-                               spin_unlock_irqrestore(&video->spinlock, flags);
-
-                               if (signal_pending(current)) {
-                                       remove_wait_queue(&video->waitq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       ret = -EINTR;
-                                       goto out;
-                               }
-
-                               schedule();
-                               set_current_state(TASK_INTERRUPTIBLE);
-
-                               spin_lock_irqsave(&video->spinlock, flags);
-                       }
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-
-                       remove_wait_queue(&video->waitq, &wait);
-                       set_current_state(TASK_RUNNING);
-
-                       frame_prepare(video, video->first_clear_frame);
-
-                       n_submit--;
-               }
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_WAIT_FRAMES: {
-               unsigned int n_wait;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               n_wait = (unsigned int) arg;
-
-               /* since we re-run the last frame on underflow, we will
-                  never actually have n_frames clear frames; at most only
-                  n_frames - 1 */
-
-               if (n_wait > (video->n_frames-1) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               add_wait_queue(&video->waitq, &wait);
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               while (video->n_clear_frames < n_wait) {
-
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-
-                       if (signal_pending(current)) {
-                               remove_wait_queue(&video->waitq, &wait);
-                               set_current_state(TASK_RUNNING);
-                               ret = -EINTR;
-                               goto out;
-                       }
-
-                       schedule();
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       spin_lock_irqsave(&video->spinlock, flags);
-               }
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               remove_wait_queue(&video->waitq, &wait);
-               set_current_state(TASK_RUNNING);
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_RECEIVE_FRAMES: {
-               unsigned int n_recv;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               n_recv = (unsigned int) arg;
-
-               /* at least one frame must be active */
-               if (n_recv > (video->n_frames-1) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               /* release the clear frames */
-               video->n_clear_frames -= n_recv;
-
-               /* advance the clear frame cursor */
-               video->first_clear_frame = (video->first_clear_frame + n_recv) % video->n_frames;
-
-               /* reset dropped_frames */
-               video->dropped_frames = 0;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_START_RECEIVE: {
-               if ( !video_card_initialized(video) ) {
-                       ret = do_dv1394_init_default(video);
-                       if (ret)
-                               goto out;
-               }
-
-               video->continuity_counter = -1;
-
-               receive_packets(video);
-
-               start_dma_receive(video);
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_INIT: {
-               struct dv1394_init init;
-               if (!argp) {
-                       ret = do_dv1394_init_default(video);
-               } else {
-                       if (copy_from_user(&init, argp, sizeof(init))) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       ret = do_dv1394_init(video, &init);
-               }
-               break;
-       }
-
-       case DV1394_IOC_SHUTDOWN:
-               do_dv1394_shutdown(video, 0);
-               ret = 0;
-               break;
-
-
-        case DV1394_IOC_GET_STATUS: {
-               struct dv1394_status status;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               status.init.api_version = DV1394_API_VERSION;
-               status.init.channel = video->channel;
-               status.init.n_frames = video->n_frames;
-               status.init.format = video->pal_or_ntsc;
-               status.init.cip_n = video->cip_n;
-               status.init.cip_d = video->cip_d;
-               status.init.syt_offset = video->syt_offset;
-
-               status.first_clear_frame = video->first_clear_frame;
-
-               /* the rest of the fields need to be locked against the interrupt */
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               status.active_frame = video->active_frame;
-               status.n_clear_frames = video->n_clear_frames;
-
-               status.dropped_frames = video->dropped_frames;
-
-               /* reset dropped_frames */
-               video->dropped_frames = 0;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (copy_to_user(argp, &status, sizeof(status))) {
-                       ret = -EFAULT;
-                       goto out;
-               }
-
-               ret = 0;
-               break;
-       }
-
-       default:
-               break;
-       }
-
- out:
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-/*** DEVICE FILE INTERFACE CONTINUED ***************************************/
-
-static int dv1394_open(struct inode *inode, struct file *file)
-{
-       struct video_card *video = NULL;
-
-       if (file->private_data) {
-               video = file->private_data;
-
-       } else {
-               /* look up the card by ID */
-               unsigned long flags;
-               int idx = ieee1394_file_to_instance(file);
-
-               spin_lock_irqsave(&dv1394_cards_lock, flags);
-               if (!list_empty(&dv1394_cards)) {
-                       struct video_card *p;
-                       list_for_each_entry(p, &dv1394_cards, list) {
-                               if ((p->id) == idx) {
-                                       video = p;
-                                       break;
-                               }
-                       }
-               }
-               spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-               if (!video) {
-                       debug_printk("dv1394: OHCI card %d not found", idx);
-                       return -ENODEV;
-               }
-
-               file->private_data = (void*) video;
-       }
-
-#ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN
-
-       if ( test_and_set_bit(0, &video->open) ) {
-               /* video is already open by someone else */
-               return -EBUSY;
-       }
-
-#endif
-
-       printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported "
-              "and will not be available in the new firewire driver stack. "
-              "Try libraw1394 based programs instead.\n", current->comm);
-
-       return nonseekable_open(inode, file);
-}
-
-
-static int dv1394_release(struct inode *inode, struct file *file)
-{
-       struct video_card *video = file_to_video_card(file);
-
-       /* OK to free the DMA buffer, no more mappings can exist */
-       do_dv1394_shutdown(video, 1);
-
-       /* give someone else a turn */
-       clear_bit(0, &video->open);
-
-       return 0;
-}
-
-
-/*** DEVICE DRIVER HANDLERS ************************************************/
-
-static void it_tasklet_func(unsigned long data)
-{
-       int wake = 0;
-       struct video_card *video = (struct video_card*) data;
-
-       spin_lock(&video->spinlock);
-
-       if (!video->dma_running)
-               goto out;
-
-       irq_printk("ContextControl = %08x, CommandPtr = %08x\n",
-              reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-              reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)
-              );
-
-
-       if ( (video->ohci_it_ctx != -1) &&
-           (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) {
-
-               struct frame *f;
-               unsigned int frame, i;
-
-
-               if (video->active_frame == -1)
-                       frame = 0;
-               else
-                       frame = video->active_frame;
-
-               /* check all the DMA-able frames */
-               for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) {
-
-                       irq_printk("IRQ checking frame %d...", frame);
-                       f = video->frames[frame];
-                       if (f->state != FRAME_READY) {
-                               irq_printk("clear, skipping\n");
-                               /* we don't own this frame */
-                               continue;
-                       }
-
-                       irq_printk("DMA\n");
-
-                       /* check the frame begin semaphore to see if we can free the previous frame */
-                       if ( *(f->frame_begin_timestamp) ) {
-                               int prev_frame;
-                               struct frame *prev_f;
-
-
-
-                               /* don't reset, need this later *(f->frame_begin_timestamp) = 0; */
-                               irq_printk("  BEGIN\n");
-
-                               prev_frame = frame - 1;
-                               if (prev_frame == -1)
-                                       prev_frame += video->n_frames;
-                               prev_f = video->frames[prev_frame];
-
-                               /* make sure we can actually garbage collect
-                                  this frame */
-                               if ( (prev_f->state == FRAME_READY) &&
-                                   prev_f->done && (!f->done) )
-                               {
-                                       frame_reset(prev_f);
-                                       video->n_clear_frames++;
-                                       wake = 1;
-                                       video->active_frame = frame;
-
-                                       irq_printk("  BEGIN - freeing previous frame %d, new active frame is %d\n", prev_frame, frame);
-                               } else {
-                                       irq_printk("  BEGIN - can't free yet\n");
-                               }
-
-                               f->done = 1;
-                       }
-
-
-                       /* see if we need to set the timestamp for the next frame */
-                       if ( *(f->mid_frame_timestamp) ) {
-                               struct frame *next_frame;
-                               u32 begin_ts, ts_cyc, ts_off;
-
-                               *(f->mid_frame_timestamp) = 0;
-
-                               begin_ts = le32_to_cpu(*(f->frame_begin_timestamp));
-
-                               irq_printk("  MIDDLE - first packet was sent at cycle %4u (%2u), assigned timestamp was (%2u) %4u\n",
-                                          begin_ts & 0x1FFF, begin_ts & 0xF,
-                                          f->assigned_timestamp >> 12, f->assigned_timestamp & 0xFFF);
-
-                               /* prepare next frame and assign timestamp */
-                               next_frame = video->frames[ (frame+1) % video->n_frames ];
-
-                               if (next_frame->state == FRAME_READY) {
-                                       irq_printk("  MIDDLE - next frame is ready, good\n");
-                               } else {
-                                       debug_printk("dv1394: Underflow! At least one frame has been dropped.\n");
-                                       next_frame = f;
-                               }
-
-                               /* set the timestamp to the timestamp of the last frame sent,
-                                  plus the length of the last frame sent, plus the syt latency */
-                               ts_cyc = begin_ts & 0xF;
-                               /* advance one frame, plus syt latency (typically 2-3) */
-                               ts_cyc += f->n_packets + video->syt_offset ;
-
-                               ts_off = 0;
-
-                               ts_cyc += ts_off/3072;
-                               ts_off %= 3072;
-
-                               next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off;
-                               if (next_frame->cip_syt1) {
-                                       next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8;
-                                       next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF;
-                               }
-                               if (next_frame->cip_syt2) {
-                                       next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8;
-                                       next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF;
-                               }
-
-                       }
-
-                       /* see if the frame looped */
-                       if ( *(f->frame_end_timestamp) ) {
-
-                               *(f->frame_end_timestamp) = 0;
-
-                               debug_printk("  END - the frame looped at least once\n");
-
-                               video->dropped_frames++;
-                       }
-
-               } /* for (each frame) */
-       }
-
-       if (wake) {
-               kill_fasync(&video->fasync, SIGIO, POLL_OUT);
-
-               /* wake readers/writers/ioctl'ers */
-               wake_up_interruptible(&video->waitq);
-       }
-
-out:
-       spin_unlock(&video->spinlock);
-}
-
-static void ir_tasklet_func(unsigned long data)
-{
-       int wake = 0;
-       struct video_card *video = (struct video_card*) data;
-
-       spin_lock(&video->spinlock);
-
-       if (!video->dma_running)
-               goto out;
-
-       if ( (video->ohci_ir_ctx != -1) &&
-           (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) {
-
-               int sof=0; /* start-of-frame flag */
-               struct frame *f;
-               u16 packet_length;
-               int i, dbc=0;
-               struct DMA_descriptor_block *block = NULL;
-               u16 xferstatus;
-
-               int next_i, prev_i;
-               struct DMA_descriptor_block *next = NULL;
-               dma_addr_t next_dma = 0;
-               struct DMA_descriptor_block *prev = NULL;
-
-               /* loop over all descriptors in all frames */
-               for (i = 0; i < video->n_frames*MAX_PACKETS; i++) {
-                       struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet);
-
-                       /* make sure we are seeing the latest changes to p */
-                       dma_region_sync_for_cpu(&video->packet_buf,
-                                               (unsigned long) p - (unsigned long) video->packet_buf.kvirt,
-                                               sizeof(struct packet));
-
-                       packet_length = le16_to_cpu(p->data_length);
-
-                       /* get the descriptor based on packet_buffer cursor */
-                       f = video->frames[video->current_packet / MAX_PACKETS];
-                       block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]);
-                       xferstatus = le32_to_cpu(block->u.in.il.q[3]) >> 16;
-                       xferstatus &= 0x1F;
-                       irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) );
-
-                       /* get the current frame */
-                       f = video->frames[video->active_frame];
-
-                       /* exclude empty packet */
-                       if (packet_length > 8 && xferstatus == 0x11) {
-                               /* check for start of frame */
-                               /* DRD> Changed to check section type ([0]>>5==0)
-                                  and dif sequence ([1]>>4==0) */
-                               sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0);
-
-                               dbc = (int) (p->cip_h1 >> 24);
-                               if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) )
-                               {
-                                       printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" );
-                                       video->dropped_frames += video->n_clear_frames + 1;
-                                       video->first_frame = 0;
-                                       video->n_clear_frames = 0;
-                                       video->first_clear_frame = -1;
-                               }
-                               video->continuity_counter = dbc;
-
-                               if (!video->first_frame) {
-                                       if (sof) {
-                                               video->first_frame = 1;
-                                       }
-
-                               } else if (sof) {
-                                       /* close current frame */
-                                       frame_reset(f);  /* f->state = STATE_CLEAR */
-                                       video->n_clear_frames++;
-                                       if (video->n_clear_frames > video->n_frames) {
-                                               video->dropped_frames++;
-                                               printk(KERN_WARNING "dv1394: dropped a frame during reception\n" );
-                                               video->n_clear_frames = video->n_frames-1;
-                                               video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-                                       }
-                                       if (video->first_clear_frame == -1)
-                                               video->first_clear_frame = video->active_frame;
-
-                                       /* get the next frame */
-                                       video->active_frame = (video->active_frame + 1) % video->n_frames;
-                                       f = video->frames[video->active_frame];
-                                       irq_printk("   frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n",
-                                                  video->active_frame, video->n_clear_frames, video->first_clear_frame);
-                               }
-                               if (video->first_frame) {
-                                       if (sof) {
-                                               /* open next frame */
-                                               f->state = FRAME_READY;
-                                       }
-
-                                       /* copy to buffer */
-                                       if (f->n_packets > (video->frame_size / 480)) {
-                                               printk(KERN_ERR "frame buffer overflow during receive\n");
-                                       }
-
-                                       frame_put_packet(f, p);
-
-                               } /* first_frame */
-                       }
-
-                       /* stop, end of ready packets */
-                       else if (xferstatus == 0) {
-                               break;
-                       }
-
-                       /* reset xferStatus & resCount */
-                       block->u.in.il.q[3] = cpu_to_le32(512);
-
-                       /* terminate dma chain at this (next) packet */
-                       next_i = video->current_packet;
-                       f = video->frames[next_i / MAX_PACKETS];
-                       next = &(f->descriptor_pool[next_i % MAX_PACKETS]);
-                       next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-                       next->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
-                       next->u.in.il.q[2] = cpu_to_le32(0); /* disable branch */
-
-                       /* link previous to next */
-                       prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1);
-                       f = video->frames[prev_i / MAX_PACKETS];
-                       prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]);
-                       if (prev_i % (MAX_PACKETS/2)) {
-                               prev->u.in.il.q[0] &= ~cpu_to_le32(3 << 20); /* no interrupt */
-                       } else {
-                               prev->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
-                       }
-                       prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */
-                       wmb();
-
-                       /* wake up DMA in case it fell asleep */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-
-                       /* advance packet_buffer cursor */
-                       video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames);
-
-               } /* for all packets */
-
-               wake = 1; /* why the hell not? */
-
-       } /* receive interrupt */
-
-       if (wake) {
-               kill_fasync(&video->fasync, SIGIO, POLL_IN);
-
-               /* wake readers/writers/ioctl'ers */
-               wake_up_interruptible(&video->waitq);
-       }
-
-out:
-       spin_unlock(&video->spinlock);
-}
-
-static struct cdev dv1394_cdev;
-static const struct file_operations dv1394_fops=
-{
-       .owner =        THIS_MODULE,
-       .poll =         dv1394_poll,
-       .unlocked_ioctl = dv1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = dv1394_compat_ioctl,
-#endif
-       .mmap =         dv1394_mmap,
-       .open =         dv1394_open,
-       .write =        dv1394_write,
-       .read =         dv1394_read,
-       .release =      dv1394_release,
-       .fasync =       dv1394_fasync,
-       .llseek =       no_llseek,
-};
-
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id dv1394_id_table[] = {
-       {
-               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
-               .version        = AVC_SW_VERSION_ENTRY & 0xffffff
-       },
-       { }
-};
-
-MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver dv1394_driver = {
-       .name = "dv1394",
-};
-
-
-/*** IEEE1394 HPSB CALLBACKS ***********************************************/
-
-static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode)
-{
-       struct video_card *video;
-       unsigned long flags;
-       int i;
-
-       video = kzalloc(sizeof(*video), GFP_KERNEL);
-       if (!video) {
-               printk(KERN_ERR "dv1394: cannot allocate video_card\n");
-               return -1;
-       }
-
-       video->ohci = ohci;
-       /* lower 2 bits of id indicate which of four "plugs"
-          per host */
-       video->id = ohci->host->id << 2;
-       if (format == DV1394_NTSC)
-               video->id |= mode;
-       else
-               video->id |= 2 + mode;
-
-       video->ohci_it_ctx = -1;
-       video->ohci_ir_ctx = -1;
-
-       video->ohci_IsoXmitContextControlSet = 0;
-       video->ohci_IsoXmitContextControlClear = 0;
-       video->ohci_IsoXmitCommandPtr = 0;
-
-       video->ohci_IsoRcvContextControlSet = 0;
-       video->ohci_IsoRcvContextControlClear = 0;
-       video->ohci_IsoRcvCommandPtr = 0;
-       video->ohci_IsoRcvContextMatch = 0;
-
-       video->n_frames = 0; /* flag that video is not initialized */
-       video->channel = 63; /* default to broadcast channel */
-       video->active_frame = -1;
-
-       /* initialize the following */
-       video->pal_or_ntsc = format;
-       video->cip_n = 0; /* 0 = use builtin default */
-       video->cip_d = 0;
-       video->syt_offset = 0;
-       video->mode = mode;
-
-       for (i = 0; i < DV1394_MAX_FRAMES; i++)
-               video->frames[i] = NULL;
-
-       dma_region_init(&video->dv_buf);
-       video->dv_buf_size = 0;
-       dma_region_init(&video->packet_buf);
-       video->packet_buf_size = 0;
-
-       clear_bit(0, &video->open);
-       spin_lock_init(&video->spinlock);
-       video->dma_running = 0;
-       mutex_init(&video->mtx);
-       init_waitqueue_head(&video->waitq);
-       video->fasync = NULL;
-
-       spin_lock_irqsave(&dv1394_cards_lock, flags);
-       INIT_LIST_HEAD(&video->list);
-       list_add_tail(&video->list, &dv1394_cards);
-       spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-       debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
-       return 0;
-}
-
-static void dv1394_remove_host(struct hpsb_host *host)
-{
-       struct video_card *video, *tmp_video;
-       unsigned long flags;
-       int found_ohci_card = 0;
-
-       do {
-               video = NULL;
-               spin_lock_irqsave(&dv1394_cards_lock, flags);
-               list_for_each_entry(tmp_video, &dv1394_cards, list) {
-                       if ((tmp_video->id >> 2) == host->id) {
-                               list_del(&tmp_video->list);
-                               video = tmp_video;
-                               found_ohci_card = 1;
-                               break;
-                       }
-               }
-               spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-               if (video) {
-                       do_dv1394_shutdown(video, 1);
-                       kfree(video);
-               }
-       } while (video);
-
-       if (found_ohci_card)
-               device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-                          IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
-}
-
-static void dv1394_add_host(struct hpsb_host *host)
-{
-       struct ti_ohci *ohci;
-       int id = host->id;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       ohci = (struct ti_ohci *)host->hostdata;
-
-       device_create(hpsb_protocol_class, NULL,
-                     MKDEV(IEEE1394_MAJOR,
-                           IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
-                     NULL, "dv1394-%d", id);
-
-       dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
-       dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
-       dv1394_init(ohci, DV1394_PAL, MODE_RECEIVE);
-       dv1394_init(ohci, DV1394_PAL, MODE_TRANSMIT);
-}
-
-
-/* Bus reset handler. In the event of a bus reset, we may need to
-   re-start the DMA contexts - otherwise the user program would
-   end up waiting forever.
-*/
-
-static void dv1394_host_reset(struct hpsb_host *host)
-{
-       struct video_card *video = NULL, *tmp_vid;
-       unsigned long flags;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       /* find the corresponding video_cards */
-       spin_lock_irqsave(&dv1394_cards_lock, flags);
-       list_for_each_entry(tmp_vid, &dv1394_cards, list) {
-               if ((tmp_vid->id >> 2) == host->id) {
-                       video = tmp_vid;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-       if (!video)
-               return;
-
-
-       spin_lock_irqsave(&video->spinlock, flags);
-
-       if (!video->dma_running)
-               goto out;
-
-       /* check IT context */
-       if (video->ohci_it_ctx != -1) {
-               u32 ctx;
-
-               ctx = reg_read(video->ohci, video->ohci_IsoXmitContextControlSet);
-
-               /* if (RUN but not ACTIVE) */
-               if ( (ctx & (1<<15)) &&
-                   !(ctx & (1<<10)) ) {
-
-                       debug_printk("dv1394: IT context stopped due to bus reset; waking it up\n");
-
-                       /* to be safe, assume a frame has been dropped. User-space programs
-                          should handle this condition like an underflow. */
-                       video->dropped_frames++;
-
-                       /* for some reason you must clear, then re-set the RUN bit to restart DMA */
-
-                       /* clear RUN */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set RUN */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set the WAKE bit (just in case; this isn't strictly necessary) */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 12));
-                       flush_pci_write(video->ohci);
-
-                       irq_printk("dv1394: AFTER IT restart ctx 0x%08x ptr 0x%08x\n",
-                                  reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                                  reg_read(video->ohci, video->ohci_IsoXmitCommandPtr));
-               }
-       }
-
-       /* check IR context */
-       if (video->ohci_ir_ctx != -1) {
-               u32 ctx;
-
-               ctx = reg_read(video->ohci, video->ohci_IsoRcvContextControlSet);
-
-               /* if (RUN but not ACTIVE) */
-               if ( (ctx & (1<<15)) &&
-                   !(ctx & (1<<10)) ) {
-
-                       debug_printk("dv1394: IR context stopped due to bus reset; waking it up\n");
-
-                       /* to be safe, assume a frame has been dropped. User-space programs
-                          should handle this condition like an overflow. */
-                       video->dropped_frames++;
-
-                       /* for some reason you must clear, then re-set the RUN bit to restart DMA */
-                       /* XXX this doesn't work for me, I can't get IR DMA to restart :[ */
-
-                       /* clear RUN */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set RUN */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set the WAKE bit (just in case; this isn't strictly necessary) */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-                       flush_pci_write(video->ohci);
-
-                       irq_printk("dv1394: AFTER IR restart ctx 0x%08x ptr 0x%08x\n",
-                                  reg_read(video->ohci, video->ohci_IsoRcvContextControlSet),
-                                  reg_read(video->ohci, video->ohci_IsoRcvCommandPtr));
-               }
-       }
-
-out:
-       spin_unlock_irqrestore(&video->spinlock, flags);
-
-       /* wake readers/writers/ioctl'ers */
-       wake_up_interruptible(&video->waitq);
-}
-
-static struct hpsb_highlevel dv1394_highlevel = {
-       .name =         "dv1394",
-       .add_host =     dv1394_add_host,
-       .remove_host =  dv1394_remove_host,
-       .host_reset =   dv1394_host_reset,
-};
-
-#ifdef CONFIG_COMPAT
-
-#define DV1394_IOC32_INIT       _IOW('#', 0x06, struct dv1394_init32)
-#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
-
-struct dv1394_init32 {
-       u32 api_version;
-       u32 channel;
-       u32 n_frames;
-       u32 format;
-       u32 cip_n;
-       u32 cip_d;
-       u32 syt_offset;
-};
-
-struct dv1394_status32 {
-       struct dv1394_init32 init;
-       s32 active_frame;
-       u32 first_clear_frame;
-       u32 n_clear_frames;
-       u32 dropped_frames;
-};
-
-/* RED-PEN: this should use compat_alloc_userspace instead */
-
-static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct dv1394_init32 dv32;
-       struct dv1394_init dv;
-       mm_segment_t old_fs;
-       int ret;
-
-       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
-               return -EFAULT;
-
-       if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32)))
-               return -EFAULT;
-
-       dv.api_version = dv32.api_version;
-       dv.channel = dv32.channel;
-       dv.n_frames = dv32.n_frames;
-       dv.format = dv32.format;
-       dv.cip_n = (unsigned long)dv32.cip_n;
-       dv.cip_d = (unsigned long)dv32.cip_d;
-       dv.syt_offset = dv32.syt_offset;
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv);
-       set_fs(old_fs);
-
-       return ret;
-}
-
-static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct dv1394_status32 dv32;
-       struct dv1394_status dv;
-       mm_segment_t old_fs;
-       int ret;
-
-       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
-               return -EFAULT;
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv);
-       set_fs(old_fs);
-
-       if (!ret) {
-               dv32.init.api_version = dv.init.api_version;
-               dv32.init.channel = dv.init.channel;
-               dv32.init.n_frames = dv.init.n_frames;
-               dv32.init.format = dv.init.format;
-               dv32.init.cip_n = (u32)dv.init.cip_n;
-               dv32.init.cip_d = (u32)dv.init.cip_d;
-               dv32.init.syt_offset = dv.init.syt_offset;
-               dv32.active_frame = dv.active_frame;
-               dv32.first_clear_frame = dv.first_clear_frame;
-               dv32.n_clear_frames = dv.n_clear_frames;
-               dv32.dropped_frames = dv.dropped_frames;
-
-               if (copy_to_user((struct dv1394_status32 __user *)arg, &dv32, sizeof(dv32)))
-                       ret = -EFAULT;
-       }
-
-       return ret;
-}
-
-
-
-static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       switch (cmd) {
-       case DV1394_IOC_SHUTDOWN:
-       case DV1394_IOC_SUBMIT_FRAMES:
-       case DV1394_IOC_WAIT_FRAMES:
-       case DV1394_IOC_RECEIVE_FRAMES:
-       case DV1394_IOC_START_RECEIVE:
-               return dv1394_ioctl(file, cmd, arg);
-
-       case DV1394_IOC32_INIT:
-               return handle_dv1394_init(file, cmd, arg);
-       case DV1394_IOC32_GET_STATUS:
-               return handle_dv1394_get_status(file, cmd, arg);
-       default:
-               return -ENOIOCTLCMD;
-       }
-}
-
-#endif /* CONFIG_COMPAT */
-
-
-/*** KERNEL MODULE HANDLERS ************************************************/
-
-MODULE_AUTHOR("Dan Maas <dmaas@dcine.com>, Dan Dennedy <dan@dennedy.org>");
-MODULE_DESCRIPTION("driver for DV input/output on OHCI board");
-MODULE_SUPPORTED_DEVICE("dv1394");
-MODULE_LICENSE("GPL");
-
-static void __exit dv1394_exit_module(void)
-{
-       hpsb_unregister_protocol(&dv1394_driver);
-       hpsb_unregister_highlevel(&dv1394_highlevel);
-       cdev_del(&dv1394_cdev);
-}
-
-static int __init dv1394_init_module(void)
-{
-       int ret;
-
-       cdev_init(&dv1394_cdev, &dv1394_fops);
-       dv1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
-       if (ret) {
-               printk(KERN_ERR "dv1394: unable to register character device\n");
-               return ret;
-       }
-
-       hpsb_register_highlevel(&dv1394_highlevel);
-
-       ret = hpsb_register_protocol(&dv1394_driver);
-       if (ret) {
-               printk(KERN_ERR "dv1394: failed to register protocol\n");
-               hpsb_unregister_highlevel(&dv1394_highlevel);
-               cdev_del(&dv1394_cdev);
-               return ret;
-       }
-
-       return 0;
-}
-
-module_init(dv1394_init_module);
-module_exit(dv1394_exit_module);
diff --git a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h
deleted file mode 100644 (file)
index 5807f52..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * dv1394.h - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *   video1394.h - driver for OHCI 1394 boards
- *   Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                          Peter Schlaile <udbz@rz.uni-karlsruhe.de>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DV_1394_H
-#define _DV_1394_H
-
-/* This is the public user-space interface. Try not to break it. */
-
-#define DV1394_API_VERSION 0x20011127
-
-/* ********************
-   **                **
-   **   DV1394 API   **
-   **                **
-   ********************
-
-   There are two methods of operating the DV1394 DV output device.
-
-   1)
-
-   The simplest is an interface based on write(): simply write
-   full DV frames of data to the device, and they will be transmitted
-   as quickly as possible. The FD may be set for non-blocking I/O,
-   in which case you can use select() or poll() to wait for output
-   buffer space.
-
-   To set the DV output parameters (e.g. whether you want NTSC or PAL
-   video), use the DV1394_INIT ioctl, passing in the parameters you
-   want in a struct dv1394_init.
-
-   Example 1:
-         To play a raw .DV file:   cat foo.DV > /dev/dv1394
-        (cat will use write() internally)
-
-   Example 2:
-           static struct dv1394_init init = {
-             0x63,        (broadcast channel)
-              4,           (four-frame ringbuffer)
-             DV1394_NTSC, (send NTSC video)
-             0, 0         (default empty packet rate)
-           }
-
-          ioctl(fd, DV1394_INIT, &init);
-
-          while (1) {
-                 read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
-                 write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
-           }
-
-   2)
-
-   For more control over buffering, and to avoid unnecessary copies
-   of the DV data, you can use the more sophisticated the mmap() interface.
-   First, call the DV1394_INIT ioctl to specify your parameters,
-   including the number of frames in the ringbuffer. Then, calling mmap()
-   on the dv1394 device will give you direct access to the ringbuffer
-   from which the DV card reads your frame data.
-
-   The ringbuffer is simply one large, contiguous region of memory
-   containing two or more frames of packed DV data. Each frame of DV data
-   is 120000 bytes (NTSC) or 144000 bytes (PAL).
-
-   Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
-   ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
-   or select()/poll() to wait until the frames are transmitted. Next, you'll
-   need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
-   frames are clear (ready to be filled with new DV data). Finally, use
-   DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
-
-
-   Example: here is what a four-frame ringbuffer might look like
-            during DV transmission:
-
-
-         frame 0   frame 1   frame 2   frame 3
-
-       *--------------------------------------*
-        | CLEAR   | DV data | DV data | CLEAR  |
-        *--------------------------------------*
-                   <ACTIVE>
-
-       transmission goes in this direction --->>>
-
-
-   The DV hardware is currently transmitting the data in frame 1.
-   Once frame 1 is finished, it will automatically transmit frame 2.
-   (if frame 2 finishes before frame 3 is submitted, the device
-   will continue to transmit frame 2, and will increase the dropped_frames
-   counter each time it repeats the transmission).
-
-
-   If you called DV1394_GET_STATUS at this instant, you would
-   receive the following values:
-
-                  n_frames          = 4
-                 active_frame      = 1
-                 first_clear_frame = 3
-                 n_clear_frames    = 2
-
-   At this point, you should write new DV data into frame 3 and optionally
-   frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
-   it may transmit the new frames.
-
-   ERROR HANDLING
-
-   An error (buffer underflow/overflow or a break in the DV stream due
-   to a 1394 bus reset) can be detected by checking the dropped_frames
-   field of struct dv1394_status (obtained through the
-   DV1394_GET_STATUS ioctl).
-
-   The best way to recover from such an error is to re-initialize
-   dv1394, either by using the DV1394_INIT ioctl call, or closing the
-   file descriptor and opening it again. (note that you must unmap all
-   ringbuffer mappings when closing the file descriptor, or else
-   dv1394 will still be considered 'in use').
-
-   MAIN LOOP
-
-   For maximum efficiency and robustness against bus errors, you are
-   advised to model the main loop of your application after the
-   following pseudo-code example:
-
-   (checks of system call return values omitted for brevity; always
-   check return values in your code!)
-
-   while ( frames left ) {
-
-    struct pollfd *pfd = ...;
-
-    pfd->fd = dv1394_fd;
-    pfd->revents = 0;
-    pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
-
-    (add other sources of I/O here)
-
-    poll(pfd, 1, -1); (or select(); add a timeout if you want)
-
-    if (pfd->revents) {
-         struct dv1394_status status;
-
-         ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
-
-        if (status.dropped_frames > 0) {
-             reset_dv1394();
-         } else {
-              for (int i = 0; i < status.n_clear_frames; i++) {
-                 copy_DV_frame();
-              }
-         }
-    }
-   }
-
-   where copy_DV_frame() reads or writes on the dv1394 file descriptor
-   (read/write mode) or copies data to/from the mmap ringbuffer and
-   then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
-   frames are availble (mmap mode).
-
-   reset_dv1394() is called in the event of a buffer
-   underflow/overflow or a halt in the DV stream (e.g. due to a 1394
-   bus reset). To guarantee recovery from the error, this function
-   should close the dv1394 file descriptor (and munmap() all
-   ringbuffer mappings, if you are using them), then re-open the
-   dv1394 device (and re-map the ringbuffer).
-
-*/
-
-
-/* maximum number of frames in the ringbuffer */
-#define DV1394_MAX_FRAMES 32
-
-/* number of *full* isochronous packets per DV frame */
-#define DV1394_NTSC_PACKETS_PER_FRAME 250
-#define DV1394_PAL_PACKETS_PER_FRAME  300
-
-/* size of one frame's worth of DV data, in bytes */
-#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
-#define DV1394_PAL_FRAME_SIZE  (480 * DV1394_PAL_PACKETS_PER_FRAME)
-
-
-/* ioctl() commands */
-#include "ieee1394-ioctl.h"
-
-
-enum pal_or_ntsc {
-       DV1394_NTSC = 0,
-       DV1394_PAL
-};
-
-
-
-
-/* this is the argument to DV1394_INIT */
-struct dv1394_init {
-       /* DV1394_API_VERSION */
-       unsigned int api_version;
-
-       /* isochronous transmission channel to use */
-       unsigned int channel;
-
-       /* number of frames in the ringbuffer. Must be at least 2
-          and at most DV1394_MAX_FRAMES. */
-       unsigned int n_frames;
-
-       /* send/receive PAL or NTSC video format */
-       enum pal_or_ntsc format;
-
-       /* the following are used only for transmission */
-
-       /* set these to zero unless you want a
-          non-default empty packet rate (see below) */
-       unsigned long cip_n;
-       unsigned long cip_d;
-
-       /* set this to zero unless you want a
-          non-default SYT cycle offset (default = 3 cycles) */
-       unsigned int syt_offset;
-};
-
-/* NOTE: you may only allocate the DV frame ringbuffer once each time
-   you open the dv1394 device. DV1394_INIT will fail if you call it a
-   second time with different 'n_frames' or 'format' arguments (which
-   would imply a different size for the ringbuffer). If you need a
-   different buffer size, simply close and re-open the device, then
-   initialize it with your new settings. */
-
-/* Q: What are cip_n and cip_d? */
-
-/*
-  A: DV video streams do not utilize 100% of the potential bandwidth offered
-  by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
-  DV devices must periodically insert empty packets into the 1394 data stream.
-  Typically there is one empty packet per 14-16 data-carrying packets.
-
-  Some DV devices will accept a wide range of empty packet rates, while others
-  require a precise rate. If the dv1394 driver produces empty packets at
-  a rate that your device does not accept, you may see ugly patterns on the
-  DV output, or even no output at all.
-
-  The default empty packet insertion rate seems to work for many people; if
-  your DV output is stable, you can simply ignore this discussion. However,
-  we have exposed the empty packet rate as a parameter to support devices that
-  do not work with the default rate.
-
-  The decision to insert an empty packet is made with a numerator/denominator
-  algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
-  You can alter the empty packet rate by passing non-zero values for cip_n
-  and cip_d to the INIT ioctl.
-
- */
-
-
-
-struct dv1394_status {
-       /* this embedded init struct returns the current dv1394
-          parameters in use */
-       struct dv1394_init init;
-
-       /* the ringbuffer frame that is currently being
-          displayed. (-1 if the device is not transmitting anything) */
-       int active_frame;
-
-       /* index of the first buffer (ahead of active_frame) that
-          is ready to be filled with data */
-       unsigned int first_clear_frame;
-
-       /* how many buffers, including first_clear_buffer, are
-          ready to be filled with data */
-       unsigned int n_clear_frames;
-
-       /* how many times the DV stream has underflowed, overflowed,
-          or otherwise encountered an error, since the previous call
-          to DV1394_GET_STATUS */
-       unsigned int dropped_frames;
-
-       /* N.B. The dropped_frames counter is only a lower bound on the actual
-          number of dropped frames, with the special case that if dropped_frames
-          is zero, then it is guaranteed that NO frames have been dropped
-          since the last call to DV1394_GET_STATUS.
-       */
-};
-
-
-#endif /* _DV_1394_H */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
deleted file mode 100644 (file)
index 6340382..0000000
+++ /dev/null
@@ -1,1720 +0,0 @@
-/*
- * eth1394.c -- IPv4 driver for Linux IEEE-1394 Subsystem
- *
- * Copyright (C) 2001-2003 Ben Collins <bcollins@debian.org>
- *               2000 Bonin Franck <boninf@free.fr>
- *               2003 Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * This driver intends to support RFC 2734, which describes a method for
- * transporting IPv4 datagrams over IEEE-1394 serial busses.
- *
- * TODO:
- * RFC 2734 related:
- * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2.
- *
- * Non-RFC 2734 related:
- * - Handle fragmented skb's coming from the networking layer.
- * - Move generic GASP reception to core 1394 code
- * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
- * - Stability improvements
- * - Performance enhancements
- * - Consider garbage collecting old partial datagrams after X amount of time
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/workqueue.h>
-
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/tcp.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/unaligned.h>
-#include <net/arp.h>
-
-#include "config_roms.h"
-#include "csr1212.h"
-#include "eth1394.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "iso.h"
-#include "nodemgr.h"
-
-#define ETH1394_PRINT_G(level, fmt, args...) \
-       printk(level "%s: " fmt, driver_name, ## args)
-
-#define ETH1394_PRINT(level, dev_name, fmt, args...) \
-       printk(level "%s: %s: " fmt, driver_name, dev_name, ## args)
-
-struct fragment_info {
-       struct list_head list;
-       int offset;
-       int len;
-};
-
-struct partial_datagram {
-       struct list_head list;
-       u16 dgl;
-       u16 dg_size;
-       __be16 ether_type;
-       struct sk_buff *skb;
-       char *pbuf;
-       struct list_head frag_info;
-};
-
-struct pdg_list {
-       struct list_head list;  /* partial datagram list per node       */
-       unsigned int sz;        /* partial datagram list size per node  */
-       spinlock_t lock;        /* partial datagram lock                */
-};
-
-struct eth1394_host_info {
-       struct hpsb_host *host;
-       struct net_device *dev;
-};
-
-struct eth1394_node_ref {
-       struct unit_directory *ud;
-       struct list_head list;
-};
-
-struct eth1394_node_info {
-       u16 maxpayload;         /* max payload                  */
-       u8 sspd;                /* max speed                    */
-       u64 fifo;               /* FIFO address                 */
-       struct pdg_list pdg;    /* partial RX datagram lists    */
-       int dgl;                /* outgoing datagram label      */
-};
-
-static const char driver_name[] = "eth1394";
-
-static struct kmem_cache *packet_task_cache;
-
-static struct hpsb_highlevel eth1394_highlevel;
-
-/* Use common.lf to determine header len */
-static const int hdr_type_len[] = {
-       sizeof(struct eth1394_uf_hdr),
-       sizeof(struct eth1394_ff_hdr),
-       sizeof(struct eth1394_sf_hdr),
-       sizeof(struct eth1394_sf_hdr)
-};
-
-static const u16 eth1394_speedto_maxpayload[] = {
-/*     S100, S200, S400, S800, S1600, S3200 */
-       512, 1024, 2048, 4096,  4096,  4096
-};
-
-MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
-MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
-MODULE_LICENSE("GPL");
-
-/*
- * The max_partial_datagrams parameter is the maximum number of fragmented
- * datagrams per node that eth1394 will keep in memory.  Providing an upper
- * bound allows us to limit the amount of memory that partial datagrams
- * consume in the event that some partial datagrams are never completed.
- */
-static int max_partial_datagrams = 25;
-module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_partial_datagrams,
-                "Maximum number of partially received fragmented datagrams "
-                "(default = 25).");
-
-
-static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
-                           unsigned short type, const void *daddr,
-                           const void *saddr, unsigned len);
-static int ether1394_rebuild_header(struct sk_buff *skb);
-static int ether1394_header_parse(const struct sk_buff *skb,
-                                 unsigned char *haddr);
-static int ether1394_header_cache(const struct neighbour *neigh,
-                                 struct hh_cache *hh);
-static void ether1394_header_cache_update(struct hh_cache *hh,
-                                         const struct net_device *dev,
-                                         const unsigned char *haddr);
-static netdev_tx_t ether1394_tx(struct sk_buff *skb,
-                               struct net_device *dev);
-static void ether1394_iso(struct hpsb_iso *iso);
-
-static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
-                          quadlet_t *data, u64 addr, size_t len, u16 flags);
-static void ether1394_add_host(struct hpsb_host *host);
-static void ether1394_remove_host(struct hpsb_host *host);
-static void ether1394_host_reset(struct hpsb_host *host);
-
-/* Function for incoming 1394 packets */
-static const struct hpsb_address_ops addr_ops = {
-       .write =        ether1394_write,
-};
-
-/* Ieee1394 highlevel driver functions */
-static struct hpsb_highlevel eth1394_highlevel = {
-       .name =         driver_name,
-       .add_host =     ether1394_add_host,
-       .remove_host =  ether1394_remove_host,
-       .host_reset =   ether1394_host_reset,
-};
-
-static int ether1394_recv_init(struct eth1394_priv *priv)
-{
-       unsigned int iso_buf_size;
-
-       /* FIXME: rawiso limits us to PAGE_SIZE */
-       iso_buf_size = min((unsigned int)PAGE_SIZE,
-                          2 * (1U << (priv->host->csr.max_rec + 1)));
-
-       priv->iso = hpsb_iso_recv_init(priv->host,
-                                      ETHER1394_GASP_BUFFERS * iso_buf_size,
-                                      ETHER1394_GASP_BUFFERS,
-                                      priv->broadcast_channel,
-                                      HPSB_ISO_DMA_PACKET_PER_BUFFER,
-                                      1, ether1394_iso);
-       if (priv->iso == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Failed to allocate IR context\n");
-               priv->bc_state = ETHER1394_BC_ERROR;
-               return -EAGAIN;
-       }
-
-       if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)
-               priv->bc_state = ETHER1394_BC_STOPPED;
-       else
-               priv->bc_state = ETHER1394_BC_RUNNING;
-       return 0;
-}
-
-/* This is called after an "ifup" */
-static int ether1394_open(struct net_device *dev)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       int ret;
-
-       if (priv->bc_state == ETHER1394_BC_ERROR) {
-               ret = ether1394_recv_init(priv);
-               if (ret)
-                       return ret;
-       }
-       netif_start_queue(dev);
-       return 0;
-}
-
-/* This is called after an "ifdown" */
-static int ether1394_stop(struct net_device *dev)
-{
-       /* flush priv->wake */
-       flush_scheduled_work();
-
-       netif_stop_queue(dev);
-       return 0;
-}
-
-/* FIXME: What to do if we timeout? I think a host reset is probably in order,
- * so that's what we do. Should we increment the stat counters too?  */
-static void ether1394_tx_timeout(struct net_device *dev)
-{
-       struct hpsb_host *host =
-                       ((struct eth1394_priv *)netdev_priv(dev))->host;
-
-       ETH1394_PRINT(KERN_ERR, dev->name, "Timeout, resetting host\n");
-       ether1394_host_reset(host);
-}
-
-static inline int ether1394_max_mtu(struct hpsb_host* host)
-{
-       return (1 << (host->csr.max_rec + 1))
-                       - sizeof(union eth1394_hdr) - ETHER1394_GASP_OVERHEAD;
-}
-
-static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
-{
-       int max_mtu;
-
-       if (new_mtu < 68)
-               return -EINVAL;
-
-       max_mtu = ether1394_max_mtu(
-                       ((struct eth1394_priv *)netdev_priv(dev))->host);
-       if (new_mtu > max_mtu) {
-               ETH1394_PRINT(KERN_INFO, dev->name,
-                             "Local node constrains MTU to %d\n", max_mtu);
-               return -ERANGE;
-       }
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-static void purge_partial_datagram(struct list_head *old)
-{
-       struct partial_datagram *pd;
-       struct list_head *lh, *n;
-       struct fragment_info *fi;
-
-       pd = list_entry(old, struct partial_datagram, list);
-
-       list_for_each_safe(lh, n, &pd->frag_info) {
-               fi = list_entry(lh, struct fragment_info, list);
-               list_del(lh);
-               kfree(fi);
-       }
-       list_del(old);
-       kfree_skb(pd->skb);
-       kfree(pd);
-}
-
-/******************************************
- * 1394 bus activity functions
- ******************************************/
-
-static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl,
-                                                 struct unit_directory *ud)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud == ud)
-                       return node;
-
-       return NULL;
-}
-
-static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl,
-                                                      u64 guid)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud->ne->guid == guid)
-                       return node;
-
-       return NULL;
-}
-
-static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl,
-                                                        nodeid_t nodeid)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud->ne->nodeid == nodeid)
-                       return node;
-
-       return NULL;
-}
-
-static int eth1394_new_node(struct eth1394_host_info *hi,
-                           struct unit_directory *ud)
-{
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *new_node;
-       struct eth1394_node_info *node_info;
-
-       new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
-       if (!new_node)
-               return -ENOMEM;
-
-       node_info = kmalloc(sizeof(*node_info), GFP_KERNEL);
-       if (!node_info) {
-               kfree(new_node);
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&node_info->pdg.lock);
-       INIT_LIST_HEAD(&node_info->pdg.list);
-       node_info->pdg.sz = 0;
-       node_info->fifo = CSR1212_INVALID_ADDR_SPACE;
-
-       dev_set_drvdata(&ud->device, node_info);
-       new_node->ud = ud;
-
-       priv = netdev_priv(hi->dev);
-       list_add_tail(&new_node->list, &priv->ip_node_list);
-       return 0;
-}
-
-static int eth1394_probe(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct eth1394_host_info *hi;
-
-       ud = container_of(dev, struct unit_directory, device);
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       return eth1394_new_node(hi, ud);
-}
-
-static int eth1394_remove(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *old_node;
-       struct eth1394_node_info *node_info;
-       struct list_head *lh, *n;
-       unsigned long flags;
-
-       ud = container_of(dev, struct unit_directory, device);
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       priv = netdev_priv(hi->dev);
-
-       old_node = eth1394_find_node(&priv->ip_node_list, ud);
-       if (!old_node)
-               return 0;
-
-       list_del(&old_node->list);
-       kfree(old_node);
-
-       node_info = dev_get_drvdata(&ud->device);
-
-       spin_lock_irqsave(&node_info->pdg.lock, flags);
-       /* The partial datagram list should be empty, but we'll just
-        * make sure anyway... */
-       list_for_each_safe(lh, n, &node_info->pdg.list)
-               purge_partial_datagram(lh);
-       spin_unlock_irqrestore(&node_info->pdg.lock, flags);
-
-       kfree(node_info);
-       dev_set_drvdata(&ud->device, NULL);
-       return 0;
-}
-
-static int eth1394_update(struct unit_directory *ud)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *node;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       priv = netdev_priv(hi->dev);
-       node = eth1394_find_node(&priv->ip_node_list, ud);
-       if (node)
-               return 0;
-
-       return eth1394_new_node(hi, ud);
-}
-
-static const struct ieee1394_device_id eth1394_id_table[] = {
-       {
-               .match_flags = (IEEE1394_MATCH_SPECIFIER_ID |
-                               IEEE1394_MATCH_VERSION),
-               .specifier_id = ETHER1394_GASP_SPECIFIER_ID,
-               .version = ETHER1394_GASP_VERSION,
-       },
-       {}
-};
-
-MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
-
-static struct hpsb_protocol_driver eth1394_proto_driver = {
-       .name           = driver_name,
-       .id_table       = eth1394_id_table,
-       .update         = eth1394_update,
-       .driver         = {
-               .probe          = eth1394_probe,
-               .remove         = eth1394_remove,
-       },
-};
-
-static void ether1394_reset_priv(struct net_device *dev, int set_mtu)
-{
-       unsigned long flags;
-       int i;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       struct hpsb_host *host = priv->host;
-       u64 guid = get_unaligned((u64 *)&(host->csr.rom->bus_info_data[3]));
-       int max_speed = IEEE1394_SPEED_MAX;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       memset(priv->ud_list, 0, sizeof(priv->ud_list));
-       priv->bc_maxpayload = 512;
-
-       /* Determine speed limit */
-       /* FIXME: This is broken for nodes with link speed < PHY speed,
-        * and it is suboptimal for S200B...S800B hardware.
-        * The result of nodemgr's speed probe should be used somehow. */
-       for (i = 0; i < host->node_count; i++) {
-               /* take care of S100B...S400B PHY ports */
-               if (host->speed[i] == SELFID_SPEED_UNKNOWN) {
-                       max_speed = IEEE1394_SPEED_100;
-                       break;
-               }
-               if (max_speed > host->speed[i])
-                       max_speed = host->speed[i];
-       }
-       priv->bc_sspd = max_speed;
-
-       if (set_mtu) {
-               /* Use the RFC 2734 default 1500 octets or the maximum payload
-                * as initial MTU */
-               dev->mtu = min(1500, ether1394_max_mtu(host));
-
-               /* Set our hardware address while we're at it */
-               memcpy(dev->dev_addr, &guid, sizeof(u64));
-               memset(dev->broadcast, 0xff, sizeof(u64));
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static const struct header_ops ether1394_header_ops = {
-       .create         = ether1394_header,
-       .rebuild        = ether1394_rebuild_header,
-       .cache          = ether1394_header_cache,
-       .cache_update   = ether1394_header_cache_update,
-       .parse          = ether1394_header_parse,
-};
-
-static const struct net_device_ops ether1394_netdev_ops = {
-       .ndo_open       = ether1394_open,
-       .ndo_stop       = ether1394_stop,
-       .ndo_start_xmit = ether1394_tx,
-       .ndo_tx_timeout = ether1394_tx_timeout,
-       .ndo_change_mtu = ether1394_change_mtu,
-};
-
-static void ether1394_init_dev(struct net_device *dev)
-{
-
-       dev->header_ops         = &ether1394_header_ops;
-       dev->netdev_ops         = &ether1394_netdev_ops;
-
-       dev->watchdog_timeo     = ETHER1394_TIMEOUT;
-       dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
-       dev->features           = NETIF_F_HIGHDMA;
-       dev->addr_len           = ETH1394_ALEN;
-       dev->hard_header_len    = ETH1394_HLEN;
-       dev->type               = ARPHRD_IEEE1394;
-
-       /* FIXME: This value was copied from ether_setup(). Is it too much? */
-       dev->tx_queue_len       = 1000;
-}
-
-/*
- * Wake the queue up after commonly encountered transmit failure conditions are
- * hopefully over.  Currently only tlabel exhaustion is accounted for.
- */
-static void ether1394_wake_queue(struct work_struct *work)
-{
-       struct eth1394_priv *priv;
-       struct hpsb_packet *packet;
-
-       priv = container_of(work, struct eth1394_priv, wake);
-       packet = hpsb_alloc_packet(0);
-
-       /* This is really bad, but unjam the queue anyway. */
-       if (!packet)
-               goto out;
-
-       packet->host = priv->host;
-       packet->node_id = priv->wake_node;
-       /*
-        * A transaction label is all we really want.  If we get one, it almost
-        * always means we can get a lot more because the ieee1394 core recycled
-        * a whole batch of tlabels, at last.
-        */
-       if (hpsb_get_tlabel(packet) == 0)
-               hpsb_free_tlabel(packet);
-
-       hpsb_free_packet(packet);
-out:
-       netif_wake_queue(priv->wake_dev);
-}
-
-/*
- * This function is called every time a card is found. It is generally called
- * when the module is installed. This is where we add all of our ethernet
- * devices. One for each host.
- */
-static void ether1394_add_host(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi = NULL;
-       struct net_device *dev = NULL;
-       struct eth1394_priv *priv;
-       u64 fifo_addr;
-
-       if (hpsb_config_rom_ip1394_add(host) != 0) {
-               ETH1394_PRINT_G(KERN_ERR, "Can't add IP-over-1394 ROM entry\n");
-               return;
-       }
-
-       fifo_addr = hpsb_allocate_and_register_addrspace(
-                       &eth1394_highlevel, host, &addr_ops,
-                       ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN,
-                       CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE);
-       if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
-               ETH1394_PRINT_G(KERN_ERR, "Cannot register CSR space\n");
-               hpsb_config_rom_ip1394_remove(host);
-               return;
-       }
-
-       dev = alloc_netdev(sizeof(*priv), "eth%d", ether1394_init_dev);
-       if (dev == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-               goto out;
-       }
-
-       SET_NETDEV_DEV(dev, &host->device);
-
-       priv = netdev_priv(dev);
-       INIT_LIST_HEAD(&priv->ip_node_list);
-       spin_lock_init(&priv->lock);
-       priv->host = host;
-       priv->local_fifo = fifo_addr;
-       INIT_WORK(&priv->wake, ether1394_wake_queue);
-       priv->wake_dev = dev;
-
-       hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));
-       if (hi == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-               goto out;
-       }
-
-       ether1394_reset_priv(dev, 1);
-
-       if (register_netdev(dev)) {
-               ETH1394_PRINT_G(KERN_ERR, "Cannot register the driver\n");
-               goto out;
-       }
-
-       ETH1394_PRINT(KERN_INFO, dev->name, "IPv4 over IEEE 1394 (fw-host%d)\n",
-                     host->id);
-
-       hi->host = host;
-       hi->dev = dev;
-
-       /* Ignore validity in hopes that it will be set in the future.  It'll
-        * be checked when the eth device is opened. */
-       priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
-
-       ether1394_recv_init(priv);
-       return;
-out:
-       if (dev)
-               free_netdev(dev);
-       if (hi)
-               hpsb_destroy_hostinfo(&eth1394_highlevel, host);
-       hpsb_unregister_addrspace(&eth1394_highlevel, host, fifo_addr);
-       hpsb_config_rom_ip1394_remove(host);
-}
-
-/* Remove a card from our list */
-static void ether1394_remove_host(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-       if (!hi)
-               return;
-       priv = netdev_priv(hi->dev);
-       hpsb_unregister_addrspace(&eth1394_highlevel, host, priv->local_fifo);
-       hpsb_config_rom_ip1394_remove(host);
-       if (priv->iso)
-               hpsb_iso_shutdown(priv->iso);
-       unregister_netdev(hi->dev);
-       free_netdev(hi->dev);
-}
-
-/* A bus reset happened */
-static void ether1394_host_reset(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct net_device *dev;
-       struct list_head *lh, *n;
-       struct eth1394_node_ref *node;
-       struct eth1394_node_info *node_info;
-       unsigned long flags;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-
-       /* This can happen for hosts that we don't use */
-       if (!hi)
-               return;
-
-       dev = hi->dev;
-       priv = netdev_priv(dev);
-
-       /* Reset our private host data, but not our MTU */
-       netif_stop_queue(dev);
-       ether1394_reset_priv(dev, 0);
-
-       list_for_each_entry(node, &priv->ip_node_list, list) {
-               node_info = dev_get_drvdata(&node->ud->device);
-
-               spin_lock_irqsave(&node_info->pdg.lock, flags);
-
-               list_for_each_safe(lh, n, &node_info->pdg.list)
-                       purge_partial_datagram(lh);
-
-               INIT_LIST_HEAD(&(node_info->pdg.list));
-               node_info->pdg.sz = 0;
-
-               spin_unlock_irqrestore(&node_info->pdg.lock, flags);
-       }
-
-       netif_wake_queue(dev);
-}
-
-/******************************************
- * HW Header net device functions
- ******************************************/
-/* These functions have been adapted from net/ethernet/eth.c */
-
-/* Create a fake MAC header for an arbitrary protocol layer.
- * saddr=NULL means use device source address
- * daddr=NULL means leave destination address (eg unresolved arp). */
-static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
-                           unsigned short type, const void *daddr,
-                           const void *saddr, unsigned len)
-{
-       struct eth1394hdr *eth =
-                       (struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
-
-       eth->h_proto = htons(type);
-
-       if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
-               memset(eth->h_dest, 0, dev->addr_len);
-               return dev->hard_header_len;
-       }
-
-       if (daddr) {
-               memcpy(eth->h_dest, daddr, dev->addr_len);
-               return dev->hard_header_len;
-       }
-
-       return -dev->hard_header_len;
-}
-
-/* Rebuild the faked MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- *
- * This routine CANNOT use cached dst->neigh!
- * Really, it is used only when dst->neigh is wrong.
- */
-static int ether1394_rebuild_header(struct sk_buff *skb)
-{
-       struct eth1394hdr *eth = (struct eth1394hdr *)skb->data;
-
-       if (eth->h_proto == htons(ETH_P_IP))
-               return arp_find((unsigned char *)&eth->h_dest, skb);
-
-       ETH1394_PRINT(KERN_DEBUG, skb->dev->name,
-                     "unable to resolve type %04x addresses\n",
-                     ntohs(eth->h_proto));
-       return 0;
-}
-
-static int ether1394_header_parse(const struct sk_buff *skb,
-                                 unsigned char *haddr)
-{
-       memcpy(haddr, skb->dev->dev_addr, ETH1394_ALEN);
-       return ETH1394_ALEN;
-}
-
-static int ether1394_header_cache(const struct neighbour *neigh,
-                                 struct hh_cache *hh)
-{
-       __be16 type = hh->hh_type;
-       struct net_device *dev = neigh->dev;
-       struct eth1394hdr *eth =
-               (struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN);
-
-       if (type == htons(ETH_P_802_3))
-               return -1;
-
-       eth->h_proto = type;
-       memcpy(eth->h_dest, neigh->ha, dev->addr_len);
-
-       hh->hh_len = ETH1394_HLEN;
-       return 0;
-}
-
-/* Called by Address Resolution module to notify changes in address. */
-static void ether1394_header_cache_update(struct hh_cache *hh,
-                                         const struct net_device *dev,
-                                         const unsigned char * haddr)
-{
-       memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
-}
-
-/******************************************
- * Datagram reception code
- ******************************************/
-
-/* Copied from net/ethernet/eth.c */
-static __be16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-       struct eth1394hdr *eth;
-       unsigned char *rawp;
-
-       skb_reset_mac_header(skb);
-       skb_pull(skb, ETH1394_HLEN);
-       eth = eth1394_hdr(skb);
-
-       if (*eth->h_dest & 1) {
-               if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len) == 0)
-                       skb->pkt_type = PACKET_BROADCAST;
-#if 0
-               else
-                       skb->pkt_type = PACKET_MULTICAST;
-#endif
-       } else {
-               if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len))
-                       skb->pkt_type = PACKET_OTHERHOST;
-       }
-
-       if (ntohs(eth->h_proto) >= 1536)
-               return eth->h_proto;
-
-       rawp = skb->data;
-
-       if (*(unsigned short *)rawp == 0xFFFF)
-               return htons(ETH_P_802_3);
-
-       return htons(ETH_P_802_2);
-}
-
-/* Parse an encapsulated IP1394 header into an ethernet frame packet.
- * We also perform ARP translation here, if need be.  */
-static __be16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
-                                nodeid_t srcid, nodeid_t destid,
-                                __be16 ether_type)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       __be64 dest_hw;
-       __be16 ret = 0;
-
-       /* Setup our hw addresses. We use these to build the ethernet header. */
-       if (destid == (LOCAL_BUS | ALL_NODES))
-               dest_hw = ~cpu_to_be64(0);  /* broadcast */
-       else
-               dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 |
-                                     priv->host->csr.guid_lo);
-
-       /* If this is an ARP packet, convert it. First, we want to make
-        * use of some of the fields, since they tell us a little bit
-        * about the sending machine.  */
-       if (ether_type == htons(ETH_P_ARP)) {
-               struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
-               struct arphdr *arp = (struct arphdr *)skb->data;
-               unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-               u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 |
-                                          ntohl(arp1394->fifo_lo);
-               u8 max_rec = min(priv->host->csr.max_rec,
-                                (u8)(arp1394->max_rec));
-               int sspd = arp1394->sspd;
-               u16 maxpayload;
-               struct eth1394_node_ref *node;
-               struct eth1394_node_info *node_info;
-               __be64 guid;
-
-               /* Sanity check. MacOSX seems to be sending us 131 in this
-                * field (atleast on my Panther G5). Not sure why. */
-               if (sspd > 5 || sspd < 0)
-                       sspd = 0;
-
-               maxpayload = min(eth1394_speedto_maxpayload[sspd],
-                                (u16)(1 << (max_rec + 1)));
-
-               guid = get_unaligned(&arp1394->s_uniq_id);
-               node = eth1394_find_node_guid(&priv->ip_node_list,
-                                             be64_to_cpu(guid));
-               if (!node)
-                       return cpu_to_be16(0);
-
-               node_info = dev_get_drvdata(&node->ud->device);
-
-               /* Update our speed/payload/fifo_offset table */
-               node_info->maxpayload = maxpayload;
-               node_info->sspd =       sspd;
-               node_info->fifo =       fifo_addr;
-
-               /* Now that we're done with the 1394 specific stuff, we'll
-                * need to alter some of the data.  Believe it or not, all
-                * that needs to be done is sender_IP_address needs to be
-                * moved, the destination hardware address get stuffed
-                * in and the hardware address length set to 8.
-                *
-                * IMPORTANT: The code below overwrites 1394 specific data
-                * needed above so keep the munging of the data for the
-                * higher level IP stack last. */
-
-               arp->ar_hln = 8;
-               arp_ptr += arp->ar_hln;         /* skip over sender unique id */
-               *(u32 *)arp_ptr = arp1394->sip; /* move sender IP addr */
-               arp_ptr += arp->ar_pln;         /* skip over sender IP addr */
-
-               if (arp->ar_op == htons(ARPOP_REQUEST))
-                       memset(arp_ptr, 0, sizeof(u64));
-               else
-                       memcpy(arp_ptr, dev->dev_addr, sizeof(u64));
-       }
-
-       /* Now add the ethernet header. */
-       if (dev_hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL,
-                           skb->len) >= 0)
-               ret = ether1394_type_trans(skb, dev);
-
-       return ret;
-}
-
-static int fragment_overlap(struct list_head *frag_list, int offset, int len)
-{
-       struct fragment_info *fi;
-       int end = offset + len;
-
-       list_for_each_entry(fi, frag_list, list)
-               if (offset < fi->offset + fi->len && end > fi->offset)
-                       return 1;
-
-       return 0;
-}
-
-static struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl)
-{
-       struct partial_datagram *pd;
-
-       list_for_each_entry(pd, pdgl, list)
-               if (pd->dgl == dgl)
-                       return &pd->list;
-
-       return NULL;
-}
-
-/* Assumes that new fragment does not overlap any existing fragments */
-static int new_fragment(struct list_head *frag_info, int offset, int len)
-{
-       struct list_head *lh;
-       struct fragment_info *fi, *fi2, *new;
-
-       list_for_each(lh, frag_info) {
-               fi = list_entry(lh, struct fragment_info, list);
-               if (fi->offset + fi->len == offset) {
-                       /* The new fragment can be tacked on to the end */
-                       fi->len += len;
-                       /* Did the new fragment plug a hole? */
-                       fi2 = list_entry(lh->next, struct fragment_info, list);
-                       if (fi->offset + fi->len == fi2->offset) {
-                               /* glue fragments together */
-                               fi->len += fi2->len;
-                               list_del(lh->next);
-                               kfree(fi2);
-                       }
-                       return 0;
-               } else if (offset + len == fi->offset) {
-                       /* The new fragment can be tacked on to the beginning */
-                       fi->offset = offset;
-                       fi->len += len;
-                       /* Did the new fragment plug a hole? */
-                       fi2 = list_entry(lh->prev, struct fragment_info, list);
-                       if (fi2->offset + fi2->len == fi->offset) {
-                               /* glue fragments together */
-                               fi2->len += fi->len;
-                               list_del(lh);
-                               kfree(fi);
-                       }
-                       return 0;
-               } else if (offset > fi->offset + fi->len) {
-                       break;
-               } else if (offset + len < fi->offset) {
-                       lh = lh->prev;
-                       break;
-               }
-       }
-
-       new = kmalloc(sizeof(*new), GFP_ATOMIC);
-       if (!new)
-               return -ENOMEM;
-
-       new->offset = offset;
-       new->len = len;
-
-       list_add(&new->list, lh);
-       return 0;
-}
-
-static int new_partial_datagram(struct net_device *dev, struct list_head *pdgl,
-                               int dgl, int dg_size, char *frag_buf,
-                               int frag_off, int frag_len)
-{
-       struct partial_datagram *new;
-
-       new = kmalloc(sizeof(*new), GFP_ATOMIC);
-       if (!new)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&new->frag_info);
-
-       if (new_fragment(&new->frag_info, frag_off, frag_len) < 0) {
-               kfree(new);
-               return -ENOMEM;
-       }
-
-       new->dgl = dgl;
-       new->dg_size = dg_size;
-
-       new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15);
-       if (!new->skb) {
-               struct fragment_info *fi = list_entry(new->frag_info.next,
-                                                     struct fragment_info,
-                                                     list);
-               kfree(fi);
-               kfree(new);
-               return -ENOMEM;
-       }
-
-       skb_reserve(new->skb, (dev->hard_header_len + 15) & ~15);
-       new->pbuf = skb_put(new->skb, dg_size);
-       memcpy(new->pbuf + frag_off, frag_buf, frag_len);
-
-       list_add(&new->list, pdgl);
-       return 0;
-}
-
-static int update_partial_datagram(struct list_head *pdgl, struct list_head *lh,
-                                  char *frag_buf, int frag_off, int frag_len)
-{
-       struct partial_datagram *pd =
-                       list_entry(lh, struct partial_datagram, list);
-
-       if (new_fragment(&pd->frag_info, frag_off, frag_len) < 0)
-               return -ENOMEM;
-
-       memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
-
-       /* Move list entry to beginnig of list so that oldest partial
-        * datagrams percolate to the end of the list */
-       list_move(lh, pdgl);
-       return 0;
-}
-
-static int is_datagram_complete(struct list_head *lh, int dg_size)
-{
-       struct partial_datagram *pd;
-       struct fragment_info *fi;
-
-       pd = list_entry(lh, struct partial_datagram, list);
-       fi = list_entry(pd->frag_info.next, struct fragment_info, list);
-
-       return (fi->len == dg_size);
-}
-
-/* Packet reception. We convert the IP1394 encapsulation header to an
- * ethernet header, and fill it with some of our other fields. This is
- * an incoming packet from the 1394 bus.  */
-static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
-                                 char *buf, int len)
-{
-       struct sk_buff *skb;
-       unsigned long flags;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
-       __be16 ether_type = cpu_to_be16(0);  /* initialized to clear warning */
-       int hdr_len;
-       struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)];
-       struct eth1394_node_info *node_info;
-
-       if (!ud) {
-               struct eth1394_node_ref *node;
-               node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid);
-               if (unlikely(!node)) {
-                       HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid "
-                                  "lookup failure: " NODE_BUS_FMT,
-                                  NODE_BUS_ARGS(priv->host, srcid));
-                       dev->stats.rx_dropped++;
-                       return -1;
-               }
-               ud = node->ud;
-
-               priv->ud_list[NODEID_TO_NODE(srcid)] = ud;
-       }
-
-       node_info = dev_get_drvdata(&ud->device);
-
-       /* First, did we receive a fragmented or unfragmented datagram? */
-       hdr->words.word1 = ntohs(hdr->words.word1);
-
-       hdr_len = hdr_type_len[hdr->common.lf];
-
-       if (hdr->common.lf == ETH1394_HDR_LF_UF) {
-               /* An unfragmented datagram has been received by the ieee1394
-                * bus. Build an skbuff around it so we can pass it to the
-                * high level network layer. */
-
-               skb = dev_alloc_skb(len + dev->hard_header_len + 15);
-               if (unlikely(!skb)) {
-                       ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-                       dev->stats.rx_dropped++;
-                       return -1;
-               }
-               skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-               memcpy(skb_put(skb, len - hdr_len), buf + hdr_len,
-                      len - hdr_len);
-               ether_type = hdr->uf.ether_type;
-       } else {
-               /* A datagram fragment has been received, now the fun begins. */
-
-               struct list_head *pdgl, *lh;
-               struct partial_datagram *pd;
-               int fg_off;
-               int fg_len = len - hdr_len;
-               int dg_size;
-               int dgl;
-               int retval;
-               struct pdg_list *pdg = &(node_info->pdg);
-
-               hdr->words.word3 = ntohs(hdr->words.word3);
-               /* The 4th header word is reserved so no need to do ntohs() */
-
-               if (hdr->common.lf == ETH1394_HDR_LF_FF) {
-                       ether_type = hdr->ff.ether_type;
-                       dgl = hdr->ff.dgl;
-                       dg_size = hdr->ff.dg_size + 1;
-                       fg_off = 0;
-               } else {
-                       hdr->words.word2 = ntohs(hdr->words.word2);
-                       dgl = hdr->sf.dgl;
-                       dg_size = hdr->sf.dg_size + 1;
-                       fg_off = hdr->sf.fg_off;
-               }
-               spin_lock_irqsave(&pdg->lock, flags);
-
-               pdgl = &(pdg->list);
-               lh = find_partial_datagram(pdgl, dgl);
-
-               if (lh == NULL) {
-                       while (pdg->sz >= max_partial_datagrams) {
-                               /* remove the oldest */
-                               purge_partial_datagram(pdgl->prev);
-                               pdg->sz--;
-                       }
-
-                       retval = new_partial_datagram(dev, pdgl, dgl, dg_size,
-                                                     buf + hdr_len, fg_off,
-                                                     fg_len);
-                       if (retval < 0) {
-                               spin_unlock_irqrestore(&pdg->lock, flags);
-                               goto bad_proto;
-                       }
-                       pdg->sz++;
-                       lh = find_partial_datagram(pdgl, dgl);
-               } else {
-                       pd = list_entry(lh, struct partial_datagram, list);
-
-                       if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) {
-                               /* Overlapping fragments, obliterate old
-                                * datagram and start new one. */
-                               purge_partial_datagram(lh);
-                               retval = new_partial_datagram(dev, pdgl, dgl,
-                                                             dg_size,
-                                                             buf + hdr_len,
-                                                             fg_off, fg_len);
-                               if (retval < 0) {
-                                       pdg->sz--;
-                                       spin_unlock_irqrestore(&pdg->lock, flags);
-                                       goto bad_proto;
-                               }
-                       } else {
-                               retval = update_partial_datagram(pdgl, lh,
-                                                                buf + hdr_len,
-                                                                fg_off, fg_len);
-                               if (retval < 0) {
-                                       /* Couldn't save off fragment anyway
-                                        * so might as well obliterate the
-                                        * datagram now. */
-                                       purge_partial_datagram(lh);
-                                       pdg->sz--;
-                                       spin_unlock_irqrestore(&pdg->lock, flags);
-                                       goto bad_proto;
-                               }
-                       } /* fragment overlap */
-               } /* new datagram or add to existing one */
-
-               pd = list_entry(lh, struct partial_datagram, list);
-
-               if (hdr->common.lf == ETH1394_HDR_LF_FF)
-                       pd->ether_type = ether_type;
-
-               if (is_datagram_complete(lh, dg_size)) {
-                       ether_type = pd->ether_type;
-                       pdg->sz--;
-                       skb = skb_get(pd->skb);
-                       purge_partial_datagram(lh);
-                       spin_unlock_irqrestore(&pdg->lock, flags);
-               } else {
-                       /* Datagram is not complete, we're done for the
-                        * moment. */
-                       spin_unlock_irqrestore(&pdg->lock, flags);
-                       return 0;
-               }
-       } /* unframgented datagram or fragmented one */
-
-       /* Write metadata, and then pass to the receive level */
-       skb->dev = dev;
-       skb->ip_summed = CHECKSUM_UNNECESSARY;  /* don't check it */
-
-       /* Parse the encapsulation header. This actually does the job of
-        * converting to an ethernet frame header, aswell as arp
-        * conversion if needed. ARP conversion is easier in this
-        * direction, since we are using ethernet as our backend.  */
-       skb->protocol = ether1394_parse_encap(skb, dev, srcid, destid,
-                                             ether_type);
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       if (!skb->protocol) {
-               dev->stats.rx_errors++;
-               dev->stats.rx_dropped++;
-               dev_kfree_skb_any(skb);
-       } else if (netif_rx(skb) == NET_RX_DROP) {
-               dev->stats.rx_errors++;
-               dev->stats.rx_dropped++;
-       } else {
-               dev->stats.rx_packets++;
-               dev->stats.rx_bytes += skb->len;
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-bad_proto:
-       if (netif_queue_stopped(dev))
-               netif_wake_queue(dev);
-
-       return 0;
-}
-
-static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
-                          quadlet_t *data, u64 addr, size_t len, u16 flags)
-{
-       struct eth1394_host_info *hi;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-       if (unlikely(!hi)) {
-               ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
-                               host->id);
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       if (ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len))
-               return RCODE_ADDRESS_ERROR;
-       else
-               return RCODE_COMPLETE;
-}
-
-static void ether1394_iso(struct hpsb_iso *iso)
-{
-       __be32 *data;
-       char *buf;
-       struct eth1394_host_info *hi;
-       struct net_device *dev;
-       unsigned int len;
-       u32 specifier_id;
-       u16 source_id;
-       int i;
-       int nready;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
-       if (unlikely(!hi)) {
-               ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
-                               iso->host->id);
-               return;
-       }
-
-       dev = hi->dev;
-
-       nready = hpsb_iso_n_ready(iso);
-       for (i = 0; i < nready; i++) {
-               struct hpsb_iso_packet_info *info =
-                       &iso->infos[(iso->first_packet + i) % iso->buf_packets];
-               data = (__be32 *)(iso->data_buf.kvirt + info->offset);
-
-               /* skip over GASP header */
-               buf = (char *)data + 8;
-               len = info->len - 8;
-
-               specifier_id = (be32_to_cpu(data[0]) & 0xffff) << 8 |
-                              (be32_to_cpu(data[1]) & 0xff000000) >> 24;
-               source_id = be32_to_cpu(data[0]) >> 16;
-
-               if (info->channel != (iso->host->csr.broadcast_channel & 0x3f)
-                   || specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
-                       /* This packet is not for us */
-                       continue;
-               }
-               ether1394_data_handler(dev, source_id, LOCAL_BUS | ALL_NODES,
-                                      buf, len);
-       }
-
-       hpsb_iso_recv_release_packets(iso, i);
-
-}
-
-/******************************************
- * Datagram transmission code
- ******************************************/
-
-/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the entire
- * arphdr) is the same format as the ip1394 header, so they overlap.  The rest
- * needs to be munged a bit.  The remainder of the arphdr is formatted based
- * on hwaddr len and ipaddr len.  We know what they'll be, so it's easy to
- * judge.
- *
- * Now that the EUI is used for the hardware address all we need to do to make
- * this work for 1394 is to insert 2 quadlets that contain max_rec size,
- * speed, and unicast FIFO address information between the sender_unique_id
- * and the IP addresses.
- */
-static void ether1394_arp_to_1394arp(struct sk_buff *skb,
-                                    struct net_device *dev)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       struct arphdr *arp = (struct arphdr *)skb->data;
-       unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-       struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
-
-       arp1394->hw_addr_len    = 16;
-       arp1394->sip            = *(u32*)(arp_ptr + ETH1394_ALEN);
-       arp1394->max_rec        = priv->host->csr.max_rec;
-       arp1394->sspd           = priv->host->csr.lnk_spd;
-       arp1394->fifo_hi        = htons(priv->local_fifo >> 32);
-       arp1394->fifo_lo        = htonl(priv->local_fifo & ~0x0);
-}
-
-/* We need to encapsulate the standard header with our own. We use the
- * ethernet header's proto for our own. */
-static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
-                                              __be16 proto,
-                                              union eth1394_hdr *hdr,
-                                              u16 dg_size, u16 dgl)
-{
-       unsigned int adj_max_payload =
-                               max_payload - hdr_type_len[ETH1394_HDR_LF_UF];
-
-       /* Does it all fit in one packet? */
-       if (dg_size <= adj_max_payload) {
-               hdr->uf.lf = ETH1394_HDR_LF_UF;
-               hdr->uf.ether_type = proto;
-       } else {
-               hdr->ff.lf = ETH1394_HDR_LF_FF;
-               hdr->ff.ether_type = proto;
-               hdr->ff.dg_size = dg_size - 1;
-               hdr->ff.dgl = dgl;
-               adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
-       }
-       return DIV_ROUND_UP(dg_size, adj_max_payload);
-}
-
-static unsigned int ether1394_encapsulate(struct sk_buff *skb,
-                                         unsigned int max_payload,
-                                         union eth1394_hdr *hdr)
-{
-       union eth1394_hdr *bufhdr;
-       int ftype = hdr->common.lf;
-       int hdrsz = hdr_type_len[ftype];
-       unsigned int adj_max_payload = max_payload - hdrsz;
-
-       switch (ftype) {
-       case ETH1394_HDR_LF_UF:
-               bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = hdr->words.word2;
-               break;
-
-       case ETH1394_HDR_LF_FF:
-               bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = hdr->words.word2;
-               bufhdr->words.word3 = htons(hdr->words.word3);
-               bufhdr->words.word4 = 0;
-
-               /* Set frag type here for future interior fragments */
-               hdr->common.lf = ETH1394_HDR_LF_IF;
-               hdr->sf.fg_off = 0;
-               break;
-
-       default:
-               hdr->sf.fg_off += adj_max_payload;
-               bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload);
-               if (max_payload >= skb->len)
-                       hdr->common.lf = ETH1394_HDR_LF_LF;
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = htons(hdr->words.word2);
-               bufhdr->words.word3 = htons(hdr->words.word3);
-               bufhdr->words.word4 = 0;
-       }
-       return min(max_payload, skb->len);
-}
-
-static struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(0);
-       if (p) {
-               p->host = host;
-               p->generation = get_hpsb_generation(host);
-               p->type = hpsb_async;
-       }
-       return p;
-}
-
-static int ether1394_prep_write_packet(struct hpsb_packet *p,
-                                      struct hpsb_host *host, nodeid_t node,
-                                      u64 addr, void *data, int tx_len)
-{
-       p->node_id = node;
-
-       if (hpsb_get_tlabel(p))
-               return -EAGAIN;
-
-       p->tcode = TCODE_WRITEB;
-       p->header_size = 16;
-       p->expect_response = 1;
-       p->header[0] =
-               p->node_id << 16 | p->tlabel << 10 | 1 << 8 | TCODE_WRITEB << 4;
-       p->header[1] = host->node_id << 16 | addr >> 32;
-       p->header[2] = addr & 0xffffffff;
-       p->header[3] = tx_len << 16;
-       p->data_size = (tx_len + 3) & ~3;
-       p->data = data;
-
-       return 0;
-}
-
-static void ether1394_prep_gasp_packet(struct hpsb_packet *p,
-                                      struct eth1394_priv *priv,
-                                      struct sk_buff *skb, int length)
-{
-       p->header_size = 4;
-       p->tcode = TCODE_STREAM_DATA;
-
-       p->header[0] = length << 16 | 3 << 14 | priv->broadcast_channel << 8 |
-                      TCODE_STREAM_DATA << 4;
-       p->data_size = length;
-       p->data = (quadlet_t *)skb->data - 2;
-       p->data[0] = cpu_to_be32(priv->host->node_id << 16 |
-                                ETHER1394_GASP_SPECIFIER_ID_HI);
-       p->data[1] = cpu_to_be32(ETHER1394_GASP_SPECIFIER_ID_LO << 24 |
-                                ETHER1394_GASP_VERSION);
-
-       p->speed_code = priv->bc_sspd;
-
-       /* prevent hpsb_send_packet() from overriding our speed code */
-       p->node_id = LOCAL_BUS | ALL_NODES;
-}
-
-static void ether1394_free_packet(struct hpsb_packet *packet)
-{
-       if (packet->tcode != TCODE_STREAM_DATA)
-               hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-}
-
-static void ether1394_complete_cb(void *__ptask);
-
-static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
-{
-       struct eth1394_priv *priv = ptask->priv;
-       struct hpsb_packet *packet = NULL;
-
-       packet = ether1394_alloc_common_packet(priv->host);
-       if (!packet)
-               return -ENOMEM;
-
-       if (ptask->tx_type == ETH1394_GASP) {
-               int length = tx_len + 2 * sizeof(quadlet_t);
-
-               ether1394_prep_gasp_packet(packet, priv, ptask->skb, length);
-       } else if (ether1394_prep_write_packet(packet, priv->host,
-                                              ptask->dest_node,
-                                              ptask->addr, ptask->skb->data,
-                                              tx_len)) {
-               hpsb_free_packet(packet);
-               return -EAGAIN;
-       }
-
-       ptask->packet = packet;
-       hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb,
-                                     ptask);
-
-       if (hpsb_send_packet(packet) < 0) {
-               ether1394_free_packet(packet);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/* Task function to be run when a datagram transmission is completed */
-static void ether1394_dg_complete(struct packet_task *ptask, int fail)
-{
-       struct sk_buff *skb = ptask->skb;
-       struct net_device *dev = skb->dev;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       unsigned long flags;
-
-       /* Statistics */
-       spin_lock_irqsave(&priv->lock, flags);
-       if (fail) {
-               dev->stats.tx_dropped++;
-               dev->stats.tx_errors++;
-       } else {
-               dev->stats.tx_bytes += skb->len;
-               dev->stats.tx_packets++;
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       dev_kfree_skb_any(skb);
-       kmem_cache_free(packet_task_cache, ptask);
-}
-
-/* Callback for when a packet has been sent and the status of that packet is
- * known */
-static void ether1394_complete_cb(void *__ptask)
-{
-       struct packet_task *ptask = (struct packet_task *)__ptask;
-       struct hpsb_packet *packet = ptask->packet;
-       int fail = 0;
-
-       if (packet->tcode != TCODE_STREAM_DATA)
-               fail = hpsb_packet_success(packet);
-
-       ether1394_free_packet(packet);
-
-       ptask->outstanding_pkts--;
-       if (ptask->outstanding_pkts > 0 && !fail) {
-               int tx_len, err;
-
-               /* Add the encapsulation header to the fragment */
-               tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload,
-                                              &ptask->hdr);
-               err = ether1394_send_packet(ptask, tx_len);
-               if (err) {
-                       if (err == -EAGAIN)
-                               ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n");
-
-                       ether1394_dg_complete(ptask, 1);
-               }
-       } else {
-               ether1394_dg_complete(ptask, fail);
-       }
-}
-
-/* Transmit a packet (called by kernel) */
-static netdev_tx_t ether1394_tx(struct sk_buff *skb,
-                               struct net_device *dev)
-{
-       struct eth1394hdr hdr_buf;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       __be16 proto;
-       unsigned long flags;
-       nodeid_t dest_node;
-       eth1394_tx_type tx_type;
-       unsigned int tx_len;
-       unsigned int max_payload;
-       u16 dg_size;
-       u16 dgl;
-       struct packet_task *ptask;
-       struct eth1394_node_ref *node;
-       struct eth1394_node_info *node_info = NULL;
-
-       ptask = kmem_cache_alloc(packet_task_cache, GFP_ATOMIC);
-       if (ptask == NULL)
-               goto fail;
-
-       /* XXX Ignore this for now. Noticed that when MacOSX is the IRM,
-        * it does not set our validity bit. We need to compensate for
-        * that somewhere else, but not in eth1394. */
-#if 0
-       if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000)
-               goto fail;
-#endif
-
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (!skb)
-               goto fail;
-
-       /* Get rid of the fake eth1394 header, but first make a copy.
-        * We might need to rebuild the header on tx failure. */
-       memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
-       skb_pull(skb, ETH1394_HLEN);
-
-       proto = hdr_buf.h_proto;
-       dg_size = skb->len;
-
-       /* Set the transmission type for the packet.  ARP packets and IP
-        * broadcast packets are sent via GASP. */
-       if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
-           proto == htons(ETH_P_ARP) ||
-           (proto == htons(ETH_P_IP) &&
-            IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
-               tx_type = ETH1394_GASP;
-               dest_node = LOCAL_BUS | ALL_NODES;
-               max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD;
-               BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD);
-               dgl = priv->bc_dgl;
-               if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
-                       priv->bc_dgl++;
-       } else {
-               __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
-
-               node = eth1394_find_node_guid(&priv->ip_node_list,
-                                             be64_to_cpu(guid));
-               if (!node)
-                       goto fail;
-
-               node_info = dev_get_drvdata(&node->ud->device);
-               if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE)
-                       goto fail;
-
-               dest_node = node->ud->ne->nodeid;
-               max_payload = node_info->maxpayload;
-               BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD);
-
-               dgl = node_info->dgl;
-               if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
-                       node_info->dgl++;
-               tx_type = ETH1394_WRREQ;
-       }
-
-       /* If this is an ARP packet, convert it */
-       if (proto == htons(ETH_P_ARP))
-               ether1394_arp_to_1394arp(skb, dev);
-
-       ptask->hdr.words.word1 = 0;
-       ptask->hdr.words.word2 = 0;
-       ptask->hdr.words.word3 = 0;
-       ptask->hdr.words.word4 = 0;
-       ptask->skb = skb;
-       ptask->priv = priv;
-       ptask->tx_type = tx_type;
-
-       if (tx_type != ETH1394_GASP) {
-               u64 addr;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               addr = node_info->fifo;
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               ptask->addr = addr;
-               ptask->dest_node = dest_node;
-       }
-
-       ptask->tx_type = tx_type;
-       ptask->max_payload = max_payload;
-       ptask->outstanding_pkts = ether1394_encapsulate_prep(max_payload,
-                                       proto, &ptask->hdr, dg_size, dgl);
-
-       /* Add the encapsulation header to the fragment */
-       tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr);
-       dev->trans_start = jiffies;
-       if (ether1394_send_packet(ptask, tx_len)) {
-               if (dest_node == (LOCAL_BUS | ALL_NODES))
-                       goto fail;
-
-               /* At this point we want to restore the packet.  When we return
-                * here with NETDEV_TX_BUSY we will get another entrance in this
-                * routine with the same skb and we need it to look the same.
-                * So we pull 4 more bytes, then build the header again. */
-               skb_pull(skb, 4);
-               ether1394_header(skb, dev, ntohs(hdr_buf.h_proto),
-                                hdr_buf.h_dest, NULL, 0);
-
-               /* Most failures of ether1394_send_packet are recoverable. */
-               netif_stop_queue(dev);
-               priv->wake_node = dest_node;
-               schedule_work(&priv->wake);
-               kmem_cache_free(packet_task_cache, ptask);
-               return NETDEV_TX_BUSY;
-       }
-
-       return NETDEV_TX_OK;
-fail:
-       if (ptask)
-               kmem_cache_free(packet_task_cache, ptask);
-
-       if (skb != NULL)
-               dev_kfree_skb(skb);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       dev->stats.tx_dropped++;
-       dev->stats.tx_errors++;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return NETDEV_TX_OK;
-}
-
-static int __init ether1394_init_module(void)
-{
-       int err;
-
-       packet_task_cache = kmem_cache_create("packet_task",
-                                             sizeof(struct packet_task),
-                                             0, 0, NULL);
-       if (!packet_task_cache)
-               return -ENOMEM;
-
-       hpsb_register_highlevel(&eth1394_highlevel);
-       err = hpsb_register_protocol(&eth1394_proto_driver);
-       if (err) {
-               hpsb_unregister_highlevel(&eth1394_highlevel);
-               kmem_cache_destroy(packet_task_cache);
-       }
-       return err;
-}
-
-static void __exit ether1394_exit_module(void)
-{
-       hpsb_unregister_protocol(&eth1394_proto_driver);
-       hpsb_unregister_highlevel(&eth1394_highlevel);
-       kmem_cache_destroy(packet_task_cache);
-}
-
-module_init(ether1394_init_module);
-module_exit(ether1394_exit_module);
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
deleted file mode 100644 (file)
index d53bac4..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * eth1394.h -- Ethernet driver for Linux IEEE-1394 Subsystem
- *
- * Copyright (C) 2000 Bonin Franck <boninf@free.fr>
- *           (C) 2001 Ben Collins <bcollins@debian.org>
- *
- * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __ETH1394_H
-#define __ETH1394_H
-
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <asm/byteorder.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-
-/* Register for incoming packets. This is 4096 bytes, which supports up to
- * S3200 (per Table 16-3 of IEEE 1394b-2002). */
-#define ETHER1394_REGION_ADDR_LEN      4096
-
-/* GASP identifier numbers for IPv4 over IEEE 1394 */
-#define ETHER1394_GASP_SPECIFIER_ID    0x00005E
-#define ETHER1394_GASP_SPECIFIER_ID_HI ((0x00005E >> 8) & 0xffff)
-#define ETHER1394_GASP_SPECIFIER_ID_LO (0x00005E & 0xff)
-#define ETHER1394_GASP_VERSION         1
-
-#define ETHER1394_GASP_OVERHEAD        (2 * sizeof(quadlet_t)) /* for GASP header */
-
-#define ETHER1394_GASP_BUFFERS 16
-
-#define NODE_SET               (ALL_NODES + 1)         /* Node set == 64 */
-
-enum eth1394_bc_states { ETHER1394_BC_ERROR,
-                        ETHER1394_BC_RUNNING,
-                        ETHER1394_BC_STOPPED };
-
-
-/* Private structure for our ethernet driver */
-struct eth1394_priv {
-       struct hpsb_host *host;         /* The card for this dev         */
-       u16 bc_maxpayload;              /* Max broadcast payload         */
-       u8 bc_sspd;                     /* Max broadcast speed           */
-       u64 local_fifo;                 /* Local FIFO Address            */
-       spinlock_t lock;                /* Private lock                  */
-       int broadcast_channel;          /* Async stream Broadcast Channel */
-       enum eth1394_bc_states bc_state; /* broadcast channel state      */
-       struct hpsb_iso *iso;           /* Async stream recv handle      */
-       int bc_dgl;                     /* Outgoing broadcast datagram label */
-       struct list_head ip_node_list;  /* List of IP capable nodes      */
-       struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */
-
-       struct work_struct wake;        /* Wake up after xmit failure    */
-       struct net_device *wake_dev;    /* Stupid backlink for .wake     */
-       nodeid_t wake_node;             /* Destination of failed xmit    */
-};
-
-
-/* Define a fake hardware header format for the networking core.  Note that
- * header size cannot exceed 16 bytes as that is the size of the header cache.
- * Also, we do not need the source address in the header so we omit it and
- * keep the header to under 16 bytes */
-#define ETH1394_ALEN (8)
-#define ETH1394_HLEN (10)
-
-struct eth1394hdr {
-       unsigned char   h_dest[ETH1394_ALEN];   /* destination eth1394 addr     */
-       __be16          h_proto;                /* packet type ID field */
-}  __attribute__((packed));
-
-static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
-{
-       return (struct eth1394hdr *)skb_mac_header(skb);
-}
-
-typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
-
-/* IP1394 headers */
-
-/* Unfragmented */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_uf_hdr {
-       u16 lf:2;
-       u16 res:14;
-       __be16 ether_type;              /* Ethernet packet type */
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_uf_hdr {
-       u16 res:14;
-       u16 lf:2;
-       __be16 ether_type;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-/* First fragment */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_ff_hdr {
-       u16 lf:2;
-       u16 res1:2;
-       u16 dg_size:12;         /* Datagram size */
-       __be16 ether_type;              /* Ethernet packet type */
-       u16 dgl;                /* Datagram label */
-       u16 res2;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_ff_hdr {
-       u16 dg_size:12;
-       u16 res1:2;
-       u16 lf:2;
-       __be16 ether_type;
-       u16 dgl;
-       u16 res2;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-/* XXX: Subsequent fragments, including last */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_sf_hdr {
-       u16 lf:2;
-       u16 res1:2;
-       u16 dg_size:12;         /* Datagram size */
-       u16 res2:4;
-       u16 fg_off:12;          /* Fragment offset */
-       u16 dgl;                /* Datagram label */
-       u16 res3;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_sf_hdr {
-       u16 dg_size:12;
-       u16 res1:2;
-       u16 lf:2;
-       u16 fg_off:12;
-       u16 res2:4;
-       u16 dgl;
-       u16 res3;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_common_hdr {
-       u16 lf:2;
-       u16 pad1:14;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_common_hdr {
-       u16 pad1:14;
-       u16 lf:2;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-struct eth1394_hdr_words {
-       u16 word1;
-       u16 word2;
-       u16 word3;
-       u16 word4;
-};
-
-union eth1394_hdr {
-       struct eth1394_common_hdr common;
-       struct eth1394_uf_hdr uf;
-       struct eth1394_ff_hdr ff;
-       struct eth1394_sf_hdr sf;
-       struct eth1394_hdr_words words;
-};
-
-/* End of IP1394 headers */
-
-/* Fragment types */
-#define ETH1394_HDR_LF_UF      0       /* unfragmented         */
-#define ETH1394_HDR_LF_FF      1       /* first fragment       */
-#define ETH1394_HDR_LF_LF      2       /* last fragment        */
-#define ETH1394_HDR_LF_IF      3       /* interior fragment    */
-
-#define IP1394_HW_ADDR_LEN     16      /* As per RFC           */
-
-/* Our arp packet (ARPHRD_IEEE1394) */
-struct eth1394_arp {
-       u16 hw_type;            /* 0x0018       */
-       u16 proto_type;         /* 0x0806       */
-       u8 hw_addr_len;         /* 16           */
-       u8 ip_addr_len;         /* 4            */
-       u16 opcode;             /* ARP Opcode   */
-       /* Above is exactly the same format as struct arphdr */
-
-       __be64 s_uniq_id;       /* Sender's 64bit EUI           */
-       u8 max_rec;             /* Sender's max packet size             */
-       u8 sspd;                /* Sender's max speed                   */
-       __be16 fifo_hi;         /* hi 16bits of sender's FIFO addr      */
-       __be32 fifo_lo;         /* lo 32bits of sender's FIFO addr      */
-       u32 sip;                /* Sender's IP Address                  */
-       u32 tip;                /* IP Address of requested hw addr      */
-};
-
-/* Network timeout */
-#define ETHER1394_TIMEOUT      100000
-
-/* This is our task struct. It's used for the packet complete callback.  */
-struct packet_task {
-       struct sk_buff *skb;
-       int outstanding_pkts;
-       eth1394_tx_type tx_type;
-       int max_payload;
-       struct hpsb_packet *packet;
-       struct eth1394_priv *priv;
-       union eth1394_hdr hdr;
-       u64 addr;
-       u16 dest_node;
-};
-
-#endif /* __ETH1394_H */
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
deleted file mode 100644 (file)
index 4bc4435..0000000
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Christian Toegel <christian.toegel@gmx.at>
- *        unregister address space
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        unregister address space
- *
- */
-
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "nodemgr.h"
-
-
-struct hl_host_info {
-       struct list_head list;
-       struct hpsb_host *host;
-       size_t size;
-       unsigned long key;
-       void *data;
-};
-
-
-static LIST_HEAD(hl_drivers);
-static DECLARE_RWSEM(hl_drivers_sem);
-
-static LIST_HEAD(hl_irqs);
-static DEFINE_RWLOCK(hl_irqs_lock);
-
-static DEFINE_RWLOCK(addr_space_lock);
-
-
-static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
-                                           struct hpsb_host *host)
-{
-       struct hl_host_info *hi = NULL;
-
-       if (!hl || !host)
-               return NULL;
-
-       read_lock(&hl->host_info_lock);
-       list_for_each_entry(hi, &hl->host_info_list, list) {
-               if (hi->host == host) {
-                       read_unlock(&hl->host_info_lock);
-                       return hi;
-               }
-       }
-       read_unlock(&hl->host_info_lock);
-       return NULL;
-}
-
-/**
- * hpsb_get_hostinfo - retrieve a hostinfo pointer bound to this driver/host
- *
- * Returns a per @host and @hl driver data structure that was previously stored
- * by hpsb_create_hostinfo.
- */
-void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
-       struct hl_host_info *hi = hl_get_hostinfo(hl, host);
-
-       return hi ? hi->data : NULL;
-}
-
-/**
- * hpsb_create_hostinfo - allocate a hostinfo pointer bound to this driver/host
- *
- * Allocate a hostinfo pointer backed by memory with @data_size and bind it to
- * to this @hl driver and @host.  If @data_size is zero, then the return here is
- * only valid for error checking.
- */
-void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          size_t data_size)
-{
-       struct hl_host_info *hi;
-       void *data;
-       unsigned long flags;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already"
-                        " exists", hl->name);
-               return NULL;
-       }
-
-       hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
-       if (!hi)
-               return NULL;
-
-       if (data_size) {
-               data = hi->data = hi + 1;
-               hi->size = data_size;
-       } else
-               data = hi;
-
-       hi->host = host;
-
-       write_lock_irqsave(&hl->host_info_lock, flags);
-       list_add_tail(&hi->list, &hl->host_info_list);
-       write_unlock_irqrestore(&hl->host_info_lock, flags);
-
-       return data;
-}
-
-/**
- * hpsb_set_hostinfo - set the hostinfo pointer to something useful
- *
- * Usually follows a call to hpsb_create_hostinfo, where the size is 0.
- */
-int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                     void *data)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               if (!hi->size && !hi->data) {
-                       hi->data = data;
-                       return 0;
-               } else
-                       HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo "
-                                "already has data", hl->name);
-       } else
-               HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists",
-                        hl->name);
-       return -EINVAL;
-}
-
-/**
- * hpsb_destroy_hostinfo - free and remove a hostinfo pointer
- *
- * Free and remove the hostinfo pointer bound to this @hl driver and @host.
- */
-void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               unsigned long flags;
-               write_lock_irqsave(&hl->host_info_lock, flags);
-               list_del(&hi->list);
-               write_unlock_irqrestore(&hl->host_info_lock, flags);
-               kfree(hi);
-       }
-       return;
-}
-
-/**
- * hpsb_set_hostinfo_key - set an alternate lookup key for an hostinfo
- *
- * Sets an alternate lookup key for the hostinfo bound to this @hl driver and
- * @host.
- */
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          unsigned long key)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi)
-               hi->key = key;
-       return;
-}
-
-/**
- * hpsb_get_hostinfo_bykey - retrieve a hostinfo pointer by its alternate key
- */
-void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
-{
-       struct hl_host_info *hi;
-       void *data = NULL;
-
-       if (!hl)
-               return NULL;
-
-       read_lock(&hl->host_info_lock);
-       list_for_each_entry(hi, &hl->host_info_list, list) {
-               if (hi->key == key) {
-                       data = hi->data;
-                       break;
-               }
-       }
-       read_unlock(&hl->host_info_lock);
-       return data;
-}
-
-static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
-{
-       struct hpsb_highlevel *hl = __data;
-
-       hl->add_host(host);
-
-       if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-       return 0;
-}
-
-/**
- * hpsb_register_highlevel - register highlevel driver
- *
- * The name pointer in @hl has to stay valid at all times because the string is
- * not copied.
- */
-void hpsb_register_highlevel(struct hpsb_highlevel *hl)
-{
-       unsigned long flags;
-
-       hpsb_init_highlevel(hl);
-       INIT_LIST_HEAD(&hl->addr_list);
-
-       down_write(&hl_drivers_sem);
-       list_add_tail(&hl->hl_list, &hl_drivers);
-       up_write(&hl_drivers_sem);
-
-       write_lock_irqsave(&hl_irqs_lock, flags);
-       list_add_tail(&hl->irq_list, &hl_irqs);
-       write_unlock_irqrestore(&hl_irqs_lock, flags);
-
-       if (hl->add_host)
-               nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
-       return;
-}
-
-static void __delete_addr(struct hpsb_address_serve *as)
-{
-       list_del(&as->host_list);
-       list_del(&as->hl_list);
-       kfree(as);
-}
-
-static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             int update_cr)
-{
-       unsigned long flags;
-       struct list_head *lh, *next;
-       struct hpsb_address_serve *as;
-
-       /* First, let the highlevel driver unreg */
-       if (hl->remove_host)
-               hl->remove_host(host);
-
-       /* Remove any addresses that are matched for this highlevel driver
-        * and this particular host. */
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each_safe (lh, next, &hl->addr_list) {
-               as = list_entry(lh, struct hpsb_address_serve, hl_list);
-               if (as->host == host)
-                       __delete_addr(as);
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       /* Now update the config-rom to reflect anything removed by the
-        * highlevel driver. */
-       if (update_cr && host->update_config_rom &&
-           hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-
-       /* Finally remove all the host info associated between these two. */
-       hpsb_destroy_hostinfo(hl, host);
-}
-
-static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
-{
-       struct hpsb_highlevel *hl = __data;
-
-       __unregister_host(hl, host, 1);
-       return 0;
-}
-
-/**
- * hpsb_unregister_highlevel - unregister highlevel driver
- */
-void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
-{
-       unsigned long flags;
-
-       write_lock_irqsave(&hl_irqs_lock, flags);
-       list_del(&hl->irq_list);
-       write_unlock_irqrestore(&hl_irqs_lock, flags);
-
-       down_write(&hl_drivers_sem);
-       list_del(&hl->hl_list);
-       up_write(&hl_drivers_sem);
-
-       nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
-}
-
-/**
- * hpsb_allocate_and_register_addrspace - alloc' and reg' a host address space
- *
- * @start and @end are 48 bit pointers and have to be quadlet aligned.
- * @end points to the first address behind the handled addresses.  This
- * function can be called multiple times for a single hpsb_highlevel @hl to
- * implement sparse register sets.  The requested region must not overlap any
- * previously allocated region, otherwise registering will fail.
- *
- * It returns true for successful allocation.  Address spaces can be
- * unregistered with hpsb_unregister_addrspace.  All remaining address spaces
- * are automatically deallocated together with the hpsb_highlevel @hl.
- */
-u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
-                                        struct hpsb_host *host,
-                                        const struct hpsb_address_ops *ops,
-                                        u64 size, u64 alignment,
-                                        u64 start, u64 end)
-{
-       struct hpsb_address_serve *as, *a1, *a2;
-       struct list_head *entry;
-       u64 retval = CSR1212_INVALID_ADDR_SPACE;
-       unsigned long flags;
-       u64 align_mask = ~(alignment - 1);
-
-       if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
-           (hweight64(alignment) != 1)) {
-               HPSB_ERR("%s called with invalid alignment: 0x%048llx",
-                        __func__, (unsigned long long)alignment);
-               return retval;
-       }
-
-       /* default range,
-        * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */
-       if (start == CSR1212_INVALID_ADDR_SPACE &&
-           end   == CSR1212_INVALID_ADDR_SPACE) {
-               start = host->middle_addr_space;
-               end   = CSR1212_ALL_SPACE_END;
-       }
-
-       if (((start|end) & ~align_mask) || (start >= end) ||
-           (end > CSR1212_ALL_SPACE_END)) {
-               HPSB_ERR("%s called with invalid addresses "
-                        "(start = %012Lx  end = %012Lx)", __func__,
-                        (unsigned long long)start,(unsigned long long)end);
-               return retval;
-       }
-
-       as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (!as)
-               return retval;
-
-       INIT_LIST_HEAD(&as->host_list);
-       INIT_LIST_HEAD(&as->hl_list);
-       as->op = ops;
-       as->host = host;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each(entry, &host->addr_space) {
-               u64 a1sa, a1ea;
-               u64 a2sa, a2ea;
-
-               a1 = list_entry(entry, struct hpsb_address_serve, host_list);
-               a2 = list_entry(entry->next, struct hpsb_address_serve,
-                               host_list);
-
-               a1sa = a1->start & align_mask;
-               a1ea = (a1->end + alignment -1) & align_mask;
-               a2sa = a2->start & align_mask;
-               a2ea = (a2->end + alignment -1) & align_mask;
-
-               if ((a2sa - a1ea >= size) && (a2sa - start >= size) &&
-                   (a2sa > start)) {
-                       as->start = max(start, a1ea);
-                       as->end = as->start + size;
-                       list_add(&as->host_list, entry);
-                       list_add_tail(&as->hl_list, &hl->addr_list);
-                       retval = as->start;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       if (retval == CSR1212_INVALID_ADDR_SPACE)
-               kfree(as);
-       return retval;
-}
-
-/**
- * hpsb_register_addrspace - register a host address space
- *
- * @start and @end are 48 bit pointers and have to be quadlet aligned.
- * @end points to the first address behind the handled addresses.  This
- * function can be called multiple times for a single hpsb_highlevel @hl to
- * implement sparse register sets.  The requested region must not overlap any
- * previously allocated region, otherwise registering will fail.
- *
- * It returns true for successful allocation.  Address spaces can be
- * unregistered with hpsb_unregister_addrspace.  All remaining address spaces
- * are automatically deallocated together with the hpsb_highlevel @hl.
- */
-int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           const struct hpsb_address_ops *ops,
-                           u64 start, u64 end)
-{
-       struct hpsb_address_serve *as;
-       struct list_head *lh;
-       int retval = 0;
-       unsigned long flags;
-
-       if (((start|end) & 3) || (start >= end) ||
-           (end > CSR1212_ALL_SPACE_END)) {
-               HPSB_ERR("%s called with invalid addresses", __func__);
-               return 0;
-       }
-
-       as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (!as)
-               return 0;
-
-       INIT_LIST_HEAD(&as->host_list);
-       INIT_LIST_HEAD(&as->hl_list);
-       as->op = ops;
-       as->start = start;
-       as->end = end;
-       as->host = host;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each(lh, &host->addr_space) {
-               struct hpsb_address_serve *as_this =
-                       list_entry(lh, struct hpsb_address_serve, host_list);
-               struct hpsb_address_serve *as_next =
-                       list_entry(lh->next, struct hpsb_address_serve,
-                                  host_list);
-
-               if (as_this->end > as->start)
-                       break;
-
-               if (as_next->start >= as->end) {
-                       list_add(&as->host_list, lh);
-                       list_add_tail(&as->hl_list, &hl->addr_list);
-                       retval = 1;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       if (retval == 0)
-               kfree(as);
-       return retval;
-}
-
-int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             u64 start)
-{
-       int retval = 0;
-       struct hpsb_address_serve *as;
-       struct list_head *lh, *next;
-       unsigned long flags;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each_safe (lh, next, &hl->addr_list) {
-               as = list_entry(lh, struct hpsb_address_serve, hl_list);
-               if (as->start == start && as->host == host) {
-                       __delete_addr(as);
-                       retval = 1;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-       return retval;
-}
-
-static const struct hpsb_address_ops dummy_ops;
-
-/* dummy address spaces as lower and upper bounds of the host's a.s. list */
-static void init_hpsb_highlevel(struct hpsb_host *host)
-{
-       INIT_LIST_HEAD(&host->dummy_zero_addr.host_list);
-       INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list);
-       INIT_LIST_HEAD(&host->dummy_max_addr.host_list);
-       INIT_LIST_HEAD(&host->dummy_max_addr.hl_list);
-
-       host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops;
-
-       host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0;
-       host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48;
-
-       list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space);
-       list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space);
-}
-
-void highlevel_add_host(struct hpsb_host *host)
-{
-       struct hpsb_highlevel *hl;
-
-       init_hpsb_highlevel(host);
-
-       down_read(&hl_drivers_sem);
-       list_for_each_entry(hl, &hl_drivers, hl_list) {
-               if (hl->add_host)
-                       hl->add_host(host);
-       }
-       up_read(&hl_drivers_sem);
-       if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-}
-
-void highlevel_remove_host(struct hpsb_host *host)
-{
-       struct hpsb_highlevel *hl;
-
-       down_read(&hl_drivers_sem);
-       list_for_each_entry(hl, &hl_drivers, hl_list)
-               __unregister_host(hl, host, 0);
-       up_read(&hl_drivers_sem);
-}
-
-void highlevel_host_reset(struct hpsb_host *host)
-{
-       unsigned long flags;
-       struct hpsb_highlevel *hl;
-
-       read_lock_irqsave(&hl_irqs_lock, flags);
-       list_for_each_entry(hl, &hl_irqs, irq_list) {
-               if (hl->host_reset)
-                       hl->host_reset(host);
-       }
-       read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
-void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                          void *data, size_t length)
-{
-       unsigned long flags;
-       struct hpsb_highlevel *hl;
-       int cts = ((quadlet_t *)data)[0] >> 4;
-
-       read_lock_irqsave(&hl_irqs_lock, flags);
-       list_for_each_entry(hl, &hl_irqs, irq_list) {
-               if (hl->fcp_request)
-                       hl->fcp_request(host, nodeid, direction, cts, data,
-                                       length);
-       }
-       read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
-/*
- * highlevel_read, highlevel_write, highlevel_lock, highlevel_lock64:
- *
- * These functions are called to handle transactions. They are called when a
- * packet arrives.  The flags argument contains the second word of the first
- * header quadlet of the incoming packet (containing transaction label, retry
- * code, transaction code and priority).  These functions either return a
- * response code or a negative number.  In the first case a response will be
- * generated.  In the latter case, no response will be sent and the driver which
- * handled the request will send the response itself.
- */
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
-                  unsigned int length, u16 flags)
-{
-       struct hpsb_address_serve *as;
-       unsigned int partlength;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       partlength = min(as->end - addr, (u64) length);
-
-                       if (as->op->read)
-                               rcode = as->op->read(host, nodeid, data,
-                                                    addr, partlength, flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-
-                       data += partlength;
-                       length -= partlength;
-                       addr += partlength;
-
-                       if ((rcode != RCODE_COMPLETE) || !length)
-                               break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-
-       if (length && (rcode == RCODE_COMPLETE))
-               rcode = RCODE_ADDRESS_ERROR;
-       return rcode;
-}
-
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
-                   u64 addr, unsigned int length, u16 flags)
-{
-       struct hpsb_address_serve *as;
-       unsigned int partlength;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       partlength = min(as->end - addr, (u64) length);
-
-                       if (as->op->write)
-                               rcode = as->op->write(host, nodeid, destid,
-                                                     data, addr, partlength,
-                                                     flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-
-                       data += partlength;
-                       length -= partlength;
-                       addr += partlength;
-
-                       if ((rcode != RCODE_COMPLETE) || !length)
-                               break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-
-       if (length && (rcode == RCODE_COMPLETE))
-               rcode = RCODE_ADDRESS_ERROR;
-       return rcode;
-}
-
-int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                  u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                  u16 flags)
-{
-       struct hpsb_address_serve *as;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       if (as->op->lock)
-                               rcode = as->op->lock(host, nodeid, store, addr,
-                                                    data, arg, ext_tcode,
-                                                    flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-                       break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-       return rcode;
-}
-
-int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                    u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                    u16 flags)
-{
-       struct hpsb_address_serve *as;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       if (as->op->lock64)
-                               rcode = as->op->lock64(host, nodeid, store,
-                                                      addr, data, arg,
-                                                      ext_tcode, flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-                       break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-       return rcode;
-}
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
deleted file mode 100644 (file)
index 9dba89f..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#ifndef IEEE1394_HIGHLEVEL_H
-#define IEEE1394_HIGHLEVEL_H
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-struct module;
-
-#include "ieee1394_types.h"
-
-struct hpsb_host;
-
-/* internal to ieee1394 core */
-struct hpsb_address_serve {
-       struct list_head host_list;     /* per host list */
-       struct list_head hl_list;       /* hpsb_highlevel list */
-       const struct hpsb_address_ops *op;
-       struct hpsb_host *host;
-       u64 start;      /* first address handled, quadlet aligned */
-       u64 end;        /* first address behind, quadlet aligned */
-};
-
-/* Only the following structures are of interest to actual highlevel drivers. */
-
-struct hpsb_highlevel {
-       const char *name;
-
-       /* Any of the following pointers can legally be NULL. */
-
-       /* New host initialized.  Will also be called during
-        * hpsb_register_highlevel for all hosts already installed. */
-       void (*add_host)(struct hpsb_host *host);
-
-       /* Host about to be removed.  Will also be called during
-        * hpsb_unregister_highlevel once for each host. */
-       void (*remove_host)(struct hpsb_host *host);
-
-       /* Host experienced bus reset with possible configuration changes.
-        * Note that this one may occur during interrupt/bottom half handling.
-        * You can not expect to be able to do stock hpsb_reads. */
-       void (*host_reset)(struct hpsb_host *host);
-
-       /* A write request was received on either the FCP_COMMAND (direction =
-        * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
-        * contains the cts field (first byte of data). */
-       void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction,
-                           int cts, u8 *data, size_t length);
-
-       /* These are initialized by the subsystem when the
-        * hpsb_higlevel is registered. */
-       struct list_head hl_list;
-       struct list_head irq_list;
-       struct list_head addr_list;
-
-       struct list_head host_info_list;
-       rwlock_t host_info_lock;
-};
-
-struct hpsb_address_ops {
-       /*
-        * Null function pointers will make the respective operation complete
-        * with RCODE_TYPE_ERROR.  Makes for easy to implement read-only
-        * registers (just leave everything but read NULL).
-        *
-        * All functions shall return appropriate IEEE 1394 rcodes.
-        */
-
-       /* These functions have to implement block reads for themselves.
-        *
-        * These functions either return a response code or a negative number.
-        * In the first case a response will be generated.  In the latter case,
-        * no response will be sent and the driver which handled the request
-        * will send the response itself. */
-       int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                   u64 addr, size_t length, u16 flags);
-       int (*write)(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags);
-
-       /* Lock transactions: write results of ext_tcode operation into
-        * *store. */
-       int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags);
-       int (*lock64)(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags);
-};
-
-void highlevel_add_host(struct hpsb_host *host);
-void highlevel_remove_host(struct hpsb_host *host);
-void highlevel_host_reset(struct hpsb_host *host);
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
-                  unsigned int length, u16 flags);
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
-                   u64 addr, unsigned int length, u16 flags);
-int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                  u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                  u16 flags);
-int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                    u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                    u16 flags);
-void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                          void *data, size_t length);
-
-/**
- * hpsb_init_highlevel - initialize a struct hpsb_highlevel
- *
- * This is only necessary if hpsb_get_hostinfo_bykey can be called
- * before hpsb_register_highlevel.
- */
-static inline void hpsb_init_highlevel(struct hpsb_highlevel *hl)
-{
-       rwlock_init(&hl->host_info_lock);
-       INIT_LIST_HEAD(&hl->host_info_list);
-}
-void hpsb_register_highlevel(struct hpsb_highlevel *hl);
-void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
-
-u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
-                                        struct hpsb_host *host,
-                                        const struct hpsb_address_ops *ops,
-                                        u64 size, u64 alignment,
-                                        u64 start, u64 end);
-int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           const struct hpsb_address_ops *ops,
-                           u64 start, u64 end);
-int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             u64 start);
-
-void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
-void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          size_t data_size);
-void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          unsigned long key);
-void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key);
-int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                     void *data);
-
-#endif /* IEEE1394_HIGHLEVEL_H */
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
deleted file mode 100644 (file)
index e947d8f..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Low level (host adapter) management.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- * Copyright (C) 1999 Emanuel Pirker
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/mutex.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "nodemgr.h"
-#include "csr.h"
-#include "config_roms.h"
-
-
-static void delayed_reset_bus(struct work_struct *work)
-{
-       struct hpsb_host *host =
-               container_of(work, struct hpsb_host, delayed_reset.work);
-       u8 generation = host->csr.generation + 1;
-
-       /* The generation field rolls over to 2 rather than 0 per IEEE
-        * 1394a-2000. */
-       if (generation > 0xf || generation < 2)
-               generation = 2;
-
-       csr_set_bus_info_generation(host->csr.rom, generation);
-       if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
-               /* CSR image creation failed.
-                * Reset generation field and do not issue a bus reset. */
-               csr_set_bus_info_generation(host->csr.rom,
-                                           host->csr.generation);
-               return;
-       }
-
-       host->csr.generation = generation;
-
-       host->update_config_rom = 0;
-       if (host->driver->set_hw_config_rom)
-               host->driver->set_hw_config_rom(host,
-                                               host->csr.rom->bus_info_data);
-
-       host->csr.gen_timestamp[host->csr.generation] = jiffies;
-       hpsb_reset_bus(host, SHORT_RESET);
-}
-
-static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
-{
-       return 0;
-}
-
-static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
-{
-       return -1;
-}
-
-static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command,
-                       unsigned long arg)
-{
-       return -1;
-}
-
-static struct hpsb_host_driver dummy_driver = {
-       .transmit_packet = dummy_transmit_packet,
-       .devctl =          dummy_devctl,
-       .isoctl =          dummy_isoctl
-};
-
-static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
-{
-       int *hostnum = __data;
-
-       if (host->id == *hostnum)
-               return 1;
-
-       return 0;
-}
-
-static DEFINE_MUTEX(host_num_alloc);
-
-/**
- * hpsb_alloc_host - allocate a new host controller.
- * @drv: the driver that will manage the host controller
- * @extra: number of extra bytes to allocate for the driver
- *
- * Allocate a &hpsb_host and initialize the general subsystem specific
- * fields.  If the driver needs to store per host data, as drivers
- * usually do, the amount of memory required can be specified by the
- * @extra parameter.  Once allocated, the driver should initialize the
- * driver specific parts, enable the controller and make it available
- * to the general subsystem using hpsb_add_host().
- *
- * Return Value: a pointer to the &hpsb_host if successful, %NULL if
- * no memory was available.
- */
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
-                                 struct device *dev)
-{
-       struct hpsb_host *h;
-       int i;
-       int hostnum = 0;
-
-       h = kzalloc(sizeof(*h) + extra, GFP_KERNEL);
-       if (!h)
-               return NULL;
-
-       h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
-       if (!h->csr.rom)
-               goto fail;
-
-       h->hostdata = h + 1;
-       h->driver = drv;
-
-       INIT_LIST_HEAD(&h->pending_packets);
-       INIT_LIST_HEAD(&h->addr_space);
-
-       for (i = 2; i < 16; i++)
-               h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
-
-       atomic_set(&h->generation, 0);
-
-       INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus);
-       
-       init_timer(&h->timeout);
-       h->timeout.data = (unsigned long) h;
-       h->timeout.function = abort_timedouts;
-       h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */
-
-       h->topology_map = h->csr.topology_map + 3;
-       h->speed_map = (u8 *)(h->csr.speed_map + 2);
-
-       mutex_lock(&host_num_alloc);
-       while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
-               hostnum++;
-       mutex_unlock(&host_num_alloc);
-       h->id = hostnum;
-
-       memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
-       h->device.parent = dev;
-       set_dev_node(&h->device, dev_to_node(dev));
-       dev_set_name(&h->device, "fw-host%d", h->id);
-
-       h->host_dev.parent = &h->device;
-       h->host_dev.class = &hpsb_host_class;
-       dev_set_name(&h->host_dev, "fw-host%d", h->id);
-
-       if (device_register(&h->device))
-               goto fail;
-       if (device_register(&h->host_dev)) {
-               device_unregister(&h->device);
-               goto fail;
-       }
-       get_device(&h->device);
-
-       return h;
-
-fail:
-       kfree(h);
-       return NULL;
-}
-
-int hpsb_add_host(struct hpsb_host *host)
-{
-       if (hpsb_default_host_entry(host))
-               return -ENOMEM;
-
-       highlevel_add_host(host);
-       return 0;
-}
-
-void hpsb_resume_host(struct hpsb_host *host)
-{
-       if (host->driver->set_hw_config_rom)
-               host->driver->set_hw_config_rom(host,
-                                               host->csr.rom->bus_info_data);
-       host->driver->devctl(host, RESET_BUS, SHORT_RESET);
-}
-
-void hpsb_remove_host(struct hpsb_host *host)
-{
-       host->is_shutdown = 1;
-
-       cancel_delayed_work(&host->delayed_reset);
-       flush_scheduled_work();
-
-       host->driver = &dummy_driver;
-       highlevel_remove_host(host);
-
-       device_unregister(&host->host_dev);
-       device_unregister(&host->device);
-}
-
-/**
- * hpsb_update_config_rom_image - updates configuration ROM image of a host
- *
- * Updates the configuration ROM image of a host.  rom_version must be the
- * current version, otherwise it will fail with return value -1. If this
- * host does not support config-rom-update, it will return -%EINVAL.
- * Return value 0 indicates success.
- */
-int hpsb_update_config_rom_image(struct hpsb_host *host)
-{
-       unsigned long reset_delay;
-       int next_gen = host->csr.generation + 1;
-
-       if (!host->update_config_rom)
-               return -EINVAL;
-
-       if (next_gen > 0xf)
-               next_gen = 2;
-
-       /* Stop the delayed interrupt, we're about to change the config rom and
-        * it would be a waste to do a bus reset twice. */
-       cancel_delayed_work(&host->delayed_reset);
-
-       /* IEEE 1394a-2000 prohibits using the same generation number
-        * twice in a 60 second period. */
-       if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
-               /* Wait 60 seconds from the last time this generation number was
-                * used. */
-               reset_delay =
-                       (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
-       else
-               /* Wait 1 second in case some other code wants to change the
-                * Config ROM in the near future. */
-               reset_delay = HZ;
-
-       PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus);
-       schedule_delayed_work(&host->delayed_reset, reset_delay);
-
-       return 0;
-}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
deleted file mode 100644 (file)
index 49c3590..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef _IEEE1394_HOSTS_H
-#define _IEEE1394_HOSTS_H
-
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-#include <asm/atomic.h>
-
-struct pci_dev;
-struct module;
-
-#include "ieee1394_types.h"
-#include "csr.h"
-#include "highlevel.h"
-
-struct hpsb_packet;
-struct hpsb_iso;
-
-struct hpsb_host {
-       struct list_head host_list;
-
-       void *hostdata;
-
-       atomic_t generation;
-
-       struct list_head pending_packets;
-       struct timer_list timeout;
-       unsigned long timeout_interval;
-
-       int node_count;      /* number of identified nodes on this bus */
-       int selfid_count;    /* total number of SelfIDs received */
-       int nodes_active;    /* number of nodes with active link layer */
-
-       nodeid_t node_id;    /* node ID of this host */
-       nodeid_t irm_id;     /* ID of this bus' isochronous resource manager */
-       nodeid_t busmgr_id;  /* ID of this bus' bus manager */
-
-       /* this nodes state */
-       unsigned in_bus_reset:1;
-       unsigned is_shutdown:1;
-       unsigned resume_packet_sent:1;
-
-       /* this nodes' duties on the bus */
-       unsigned is_root:1;
-       unsigned is_cycmst:1;
-       unsigned is_irm:1;
-       unsigned is_busmgr:1;
-
-       int reset_retries;
-       quadlet_t *topology_map;
-       u8 *speed_map;
-
-       int id;
-       struct hpsb_host_driver *driver;
-       struct pci_dev *pdev;
-       struct device device;
-       struct device host_dev;
-
-       struct delayed_work delayed_reset;
-       unsigned config_roms:31;
-       unsigned update_config_rom:1;
-
-       struct list_head addr_space;
-       u64 low_addr_space;     /* upper bound of physical DMA area */
-       u64 middle_addr_space;  /* upper bound of posted write area */
-
-       u8 speed[ALL_NODES];    /* speed between each node and local node */
-
-       /* per node tlabel allocation */
-       u8 next_tl[ALL_NODES];
-       struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
-
-       struct csr_control csr;
-
-       struct hpsb_address_serve dummy_zero_addr;
-       struct hpsb_address_serve dummy_max_addr;
-};
-
-enum devctl_cmd {
-       /* Host is requested to reset its bus and cancel all outstanding async
-        * requests.  If arg == 1, it shall also attempt to become root on the
-        * bus.  Return void. */
-       RESET_BUS,
-
-       /* Arg is void, return value is the hardware cycle counter value. */
-       GET_CYCLE_COUNTER,
-
-       /* Set the hardware cycle counter to the value in arg, return void.
-        * FIXME - setting is probably not required. */
-       SET_CYCLE_COUNTER,
-
-       /* Configure hardware for new bus ID in arg, return void. */
-       SET_BUS_ID,
-
-       /* If arg true, start sending cycle start packets, stop if arg == 0.
-        * Return void. */
-       ACT_CYCLE_MASTER,
-
-       /* Cancel all outstanding async requests without resetting the bus.
-        * Return void. */
-       CANCEL_REQUESTS,
-};
-
-enum isoctl_cmd {
-       /* rawiso API - see iso.h for the meanings of these commands
-        * (they correspond exactly to the hpsb_iso_* API functions)
-        * INIT = allocate resources
-        * START = begin transmission/reception
-        * STOP = halt transmission/reception
-        * QUEUE/RELEASE = produce/consume packets
-        * SHUTDOWN = deallocate resources
-        */
-
-       XMIT_INIT,
-       XMIT_START,
-       XMIT_STOP,
-       XMIT_QUEUE,
-       XMIT_SHUTDOWN,
-
-       RECV_INIT,
-       RECV_LISTEN_CHANNEL,   /* multi-channel only */
-       RECV_UNLISTEN_CHANNEL, /* multi-channel only */
-       RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */
-       RECV_START,
-       RECV_STOP,
-       RECV_RELEASE,
-       RECV_SHUTDOWN,
-       RECV_FLUSH
-};
-
-enum reset_types {
-       /* 166 microsecond reset -- only type of reset available on
-          non-1394a capable controllers */
-       LONG_RESET,
-
-       /* Short (arbitrated) reset -- only available on 1394a capable
-          controllers */
-       SHORT_RESET,
-
-       /* Variants that set force_root before issueing the bus reset */
-       LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
-
-       /* Variants that clear force_root before issueing the bus reset */
-       LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT
-};
-
-struct hpsb_host_driver {
-       struct module *owner;
-       const char *name;
-
-       /* The hardware driver may optionally support a function that is used
-        * to set the hardware ConfigROM if the hardware supports handling
-        * reads to the ConfigROM on its own. */
-       void (*set_hw_config_rom)(struct hpsb_host *host,
-                                 __be32 *config_rom);
-
-       /* This function shall implement packet transmission based on
-        * packet->type.  It shall CRC both parts of the packet (unless
-        * packet->type == raw) and do byte-swapping as necessary or instruct
-        * the hardware to do so.  It can return immediately after the packet
-        * was queued for sending.  After sending, hpsb_sent_packet() has to be
-        * called.  Return 0 on success, negative errno on failure.
-        * NOTE: The function must be callable in interrupt context.
-        */
-       int (*transmit_packet)(struct hpsb_host *host,
-                              struct hpsb_packet *packet);
-
-       /* This function requests miscellanous services from the driver, see
-        * above for command codes and expected actions.  Return -1 for unknown
-        * command, though that should never happen.
-        */
-       int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg);
-
-        /* ISO transmission/reception functions. Return 0 on success, -1
-         * (or -EXXX errno code) on failure. If the low-level driver does not
-         * support the new ISO API, set isoctl to NULL.
-         */
-       int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command,
-                     unsigned long arg);
-
-       /* This function is mainly to redirect local CSR reads/locks to the iso
-        * management registers (bus manager id, bandwidth available, channels
-        * available) to the hardware registers in OHCI.  reg is 0,1,2,3 for bus
-        * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
-        * as OHCI uses).  data and compare are the new data and expected data
-        * respectively, return value is the old value.
-        */
-       quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
-                                quadlet_t data, quadlet_t compare);
-};
-
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
-                                 struct device *dev);
-int hpsb_add_host(struct hpsb_host *host);
-void hpsb_resume_host(struct hpsb_host *host);
-void hpsb_remove_host(struct hpsb_host *host);
-int hpsb_update_config_rom_image(struct hpsb_host *host);
-
-#endif /* _IEEE1394_HOSTS_H */
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
deleted file mode 100644 (file)
index 46878fe..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Base file for all ieee1394 ioctl's.
- * Linux-1394 has allocated base '#' with a range of 0x00-0x3f.
- */
-
-#ifndef __IEEE1394_IOCTL_H
-#define __IEEE1394_IOCTL_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/* DV1394 Gets 10 */
-
-/* Get the driver ready to transmit video.  pass a struct dv1394_init* as
- * the parameter (see below), or NULL to get default parameters */
-#define DV1394_IOC_INIT                        _IOW('#', 0x06, struct dv1394_init)
-
-/* Stop transmitting video and free the ringbuffer */
-#define DV1394_IOC_SHUTDOWN            _IO ('#', 0x07)
-
-/* Submit N new frames to be transmitted, where the index of the first new
- * frame is first_clear_buffer, and the index of the last new frame is
- * (first_clear_buffer + N) % n_frames */
-#define DV1394_IOC_SUBMIT_FRAMES       _IO ('#', 0x08)
-
-/* Block until N buffers are clear (pass N as the parameter) Because we
- * re-transmit the last frame on underrun, there will at most be n_frames
- * - 1 clear frames at any time */
-#define DV1394_IOC_WAIT_FRAMES         _IO ('#', 0x09)
-
-/* Capture new frames that have been received, where the index of the
- * first new frame is first_clear_buffer, and the index of the last new
- * frame is (first_clear_buffer + N) % n_frames */
-#define DV1394_IOC_RECEIVE_FRAMES      _IO ('#', 0x0a)
-
-/* Tell card to start receiving DMA */
-#define DV1394_IOC_START_RECEIVE       _IO ('#', 0x0b)
-
-/* Pass a struct dv1394_status* as the parameter */
-#define DV1394_IOC_GET_STATUS          _IOR('#', 0x0c, struct dv1394_status)
-
-
-/* Video1394 Gets 10 */
-
-#define VIDEO1394_IOC_LISTEN_CHANNEL           \
-       _IOWR('#', 0x10, struct video1394_mmap)
-#define VIDEO1394_IOC_UNLISTEN_CHANNEL         \
-       _IOW ('#', 0x11, int)
-#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER      \
-       _IOW ('#', 0x12, struct video1394_wait)
-#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER       \
-       _IOWR('#', 0x13, struct video1394_wait)
-#define VIDEO1394_IOC_TALK_CHANNEL             \
-       _IOWR('#', 0x14, struct video1394_mmap)
-#define VIDEO1394_IOC_UNTALK_CHANNEL           \
-       _IOW ('#', 0x15, int)
-/*
- * This one is broken: it really wanted
- * "sizeof (struct video1394_wait) + sizeof (struct video1394_queue_variable)"
- * but got just a "size_t"
- */
-#define VIDEO1394_IOC_TALK_QUEUE_BUFFER        \
-       _IOW ('#', 0x16, size_t)
-#define VIDEO1394_IOC_TALK_WAIT_BUFFER         \
-       _IOW ('#', 0x17, struct video1394_wait)
-#define VIDEO1394_IOC_LISTEN_POLL_BUFFER       \
-       _IOWR('#', 0x18, struct video1394_wait)
-
-
-/* Raw1394's ISO interface */
-#define RAW1394_IOC_ISO_XMIT_INIT              \
-       _IOW ('#', 0x1a, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_RECV_INIT              \
-       _IOWR('#', 0x1b, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_RECV_START             \
-       _IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3)
-#define RAW1394_IOC_ISO_XMIT_START             \
-       _IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2)
-#define RAW1394_IOC_ISO_XMIT_RECV_STOP         \
-       _IO  ('#', 0x1e)
-#define RAW1394_IOC_ISO_GET_STATUS             \
-       _IOR ('#', 0x1f, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_SHUTDOWN               \
-       _IO  ('#', 0x20)
-#define RAW1394_IOC_ISO_QUEUE_ACTIVITY         \
-       _IO  ('#', 0x21)
-#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL    \
-       _IOW ('#', 0x22, unsigned char)
-#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL  \
-       _IOW ('#', 0x23, unsigned char)
-#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK  \
-       _IOW ('#', 0x24, __u64)
-#define RAW1394_IOC_ISO_RECV_PACKETS           \
-       _IOW ('#', 0x25, struct raw1394_iso_packets)
-#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS   \
-       _IOW ('#', 0x26, unsigned int)
-#define RAW1394_IOC_ISO_XMIT_PACKETS           \
-       _IOW ('#', 0x27, struct raw1394_iso_packets)
-#define RAW1394_IOC_ISO_XMIT_SYNC              \
-       _IO  ('#', 0x28)
-#define RAW1394_IOC_ISO_RECV_FLUSH             \
-       _IO  ('#', 0x29)
-#define RAW1394_IOC_GET_CYCLE_TIMER            \
-       _IOR ('#', 0x30, struct raw1394_cycle_timer)
-
-#endif /* __IEEE1394_IOCTL_H */
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
deleted file mode 100644 (file)
index af320e2..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Generic IEEE 1394 definitions
- */
-
-#ifndef _IEEE1394_IEEE1394_H
-#define _IEEE1394_IEEE1394_H
-
-#define TCODE_WRITEQ           0x0
-#define TCODE_WRITEB           0x1
-#define TCODE_WRITE_RESPONSE   0x2
-#define TCODE_READQ            0x4
-#define TCODE_READB            0x5
-#define TCODE_READQ_RESPONSE   0x6
-#define TCODE_READB_RESPONSE   0x7
-#define TCODE_CYCLE_START      0x8
-#define TCODE_LOCK_REQUEST     0x9
-#define TCODE_ISO_DATA         0xa
-#define TCODE_STREAM_DATA      0xa
-#define TCODE_LOCK_RESPONSE    0xb
-
-#define RCODE_COMPLETE         0x0
-#define RCODE_CONFLICT_ERROR   0x4
-#define RCODE_DATA_ERROR       0x5
-#define RCODE_TYPE_ERROR       0x6
-#define RCODE_ADDRESS_ERROR    0x7
-
-#define EXTCODE_MASK_SWAP      0x1
-#define EXTCODE_COMPARE_SWAP   0x2
-#define EXTCODE_FETCH_ADD      0x3
-#define EXTCODE_LITTLE_ADD     0x4
-#define EXTCODE_BOUNDED_ADD    0x5
-#define EXTCODE_WRAP_ADD       0x6
-
-#define ACK_COMPLETE           0x1
-#define ACK_PENDING            0x2
-#define ACK_BUSY_X             0x4
-#define ACK_BUSY_A             0x5
-#define ACK_BUSY_B             0x6
-#define ACK_TARDY              0xb
-#define ACK_CONFLICT_ERROR     0xc
-#define ACK_DATA_ERROR         0xd
-#define ACK_TYPE_ERROR         0xe
-#define ACK_ADDRESS_ERROR      0xf
-
-/* Non-standard "ACK codes" for internal use */
-#define ACKX_NONE              (-1)
-#define ACKX_SEND_ERROR                (-2)
-#define ACKX_ABORTED           (-3)
-#define ACKX_TIMEOUT           (-4)
-
-#define IEEE1394_SPEED_100     0x00
-#define IEEE1394_SPEED_200     0x01
-#define IEEE1394_SPEED_400     0x02
-#define IEEE1394_SPEED_800     0x03
-#define IEEE1394_SPEED_1600    0x04
-#define IEEE1394_SPEED_3200    0x05
-#define IEEE1394_SPEED_MAX     IEEE1394_SPEED_3200
-
-/* Maps speed values above to a string representation */
-extern const char *hpsb_speedto_str[];
-
-/* 1394a cable PHY packets */
-#define SELFID_PWRCL_NO_POWER          0x0
-#define SELFID_PWRCL_PROVIDE_15W       0x1
-#define SELFID_PWRCL_PROVIDE_30W       0x2
-#define SELFID_PWRCL_PROVIDE_45W       0x3
-#define SELFID_PWRCL_USE_1W            0x4
-#define SELFID_PWRCL_USE_3W            0x5
-#define SELFID_PWRCL_USE_6W            0x6
-#define SELFID_PWRCL_USE_10W           0x7
-
-#define SELFID_PORT_CHILD              0x3
-#define SELFID_PORT_PARENT             0x2
-#define SELFID_PORT_NCONN              0x1
-#define SELFID_PORT_NONE               0x0
-
-#define SELFID_SPEED_UNKNOWN           0x3     /* 1394b PHY */
-
-#define PHYPACKET_LINKON                       0x40000000
-#define PHYPACKET_PHYCONFIG_R                  0x00800000
-#define PHYPACKET_PHYCONFIG_T                  0x00400000
-#define EXTPHYPACKET_TYPE_PING                 0x00000000
-#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE    0x00040000
-#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED   0x00140000
-#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE     0x000C0000
-#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED    0x001C0000
-#define EXTPHYPACKET_TYPE_REMOTECOMMAND                0x00200000
-#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION   0x00280000
-#define EXTPHYPACKET_TYPE_RESUME               0x003C0000
-
-#define EXTPHYPACKET_TYPEMASK                  0xC0FC0000
-
-#define PHYPACKET_PORT_SHIFT           24
-#define PHYPACKET_GAPCOUNT_SHIFT       16
-
-/* 1394a PHY register map bitmasks */
-#define PHY_00_PHYSICAL_ID     0xFC
-#define PHY_00_R               0x02 /* Root */
-#define PHY_00_PS              0x01 /* Power Status*/
-#define PHY_01_RHB             0x80 /* Root Hold-Off */
-#define PHY_01_IBR             0x80 /* Initiate Bus Reset */
-#define PHY_01_GAP_COUNT       0x3F
-#define PHY_02_EXTENDED                0xE0 /* 0x7 for 1394a-compliant PHY */
-#define PHY_02_TOTAL_PORTS     0x1F
-#define PHY_03_MAX_SPEED       0xE0
-#define PHY_03_DELAY           0x0F
-#define PHY_04_LCTRL           0x80 /* Link Active Report Control */
-#define PHY_04_CONTENDER       0x40
-#define PHY_04_JITTER          0x38
-#define PHY_04_PWR_CLASS       0x07 /* Power Class */
-#define PHY_05_WATCHDOG                0x80
-#define PHY_05_ISBR            0x40 /* Initiate Short Bus Reset */
-#define PHY_05_LOOP            0x20 /* Loop Detect */
-#define PHY_05_PWR_FAIL                0x10 /* Cable Power Failure Detect */
-#define PHY_05_TIMEOUT         0x08 /* Arbitration State Machine Timeout */
-#define PHY_05_PORT_EVENT      0x04 /* Port Event Detect */
-#define PHY_05_ENAB_ACCEL      0x02 /* Enable Arbitration Acceleration */
-#define PHY_05_ENAB_MULTI      0x01 /* Ena. Multispeed Packet Concatenation */
-
-#include <asm/byteorder.h>
-
-/* '1' '3' '9' '4' in ASCII */
-#define IEEE1394_BUSID_MAGIC   cpu_to_be32(0x31333934)
-
-#ifdef __BIG_ENDIAN_BITFIELD
-
-struct selfid {
-       u32 packet_identifier:2; /* always binary 10 */
-       u32 phy_id:6;
-       /* byte */
-       u32 extended:1; /* if true is struct ext_selfid */
-       u32 link_active:1;
-       u32 gap_count:6;
-       /* byte */
-       u32 speed:2;
-       u32 phy_delay:2;
-       u32 contender:1;
-       u32 power_class:3;
-       /* byte */
-       u32 port0:2;
-       u32 port1:2;
-       u32 port2:2;
-       u32 initiated_reset:1;
-       u32 more_packets:1;
-} __attribute__((packed));
-
-struct ext_selfid {
-       u32 packet_identifier:2; /* always binary 10 */
-       u32 phy_id:6;
-       /* byte */
-       u32 extended:1; /* if false is struct selfid */
-       u32 seq_nr:3;
-       u32 reserved:2;
-       u32 porta:2;
-       /* byte */
-       u32 portb:2;
-       u32 portc:2;
-       u32 portd:2;
-       u32 porte:2;
-       /* byte */
-       u32 portf:2;
-       u32 portg:2;
-       u32 porth:2;
-       u32 reserved2:1;
-       u32 more_packets:1;
-} __attribute__((packed));
-
-#elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */
-
-/*
- * Note: these mean to be bit fields of a big endian SelfID as seen on a little
- * endian machine.  Without swapping.
- */
-
-struct selfid {
-       u32 phy_id:6;
-       u32 packet_identifier:2; /* always binary 10 */
-       /* byte */
-       u32 gap_count:6;
-       u32 link_active:1;
-       u32 extended:1; /* if true is struct ext_selfid */
-       /* byte */
-       u32 power_class:3;
-       u32 contender:1;
-       u32 phy_delay:2;
-       u32 speed:2;
-       /* byte */
-       u32 more_packets:1;
-       u32 initiated_reset:1;
-       u32 port2:2;
-       u32 port1:2;
-       u32 port0:2;
-} __attribute__((packed));
-
-struct ext_selfid {
-       u32 phy_id:6;
-       u32 packet_identifier:2; /* always binary 10 */
-       /* byte */
-       u32 porta:2;
-       u32 reserved:2;
-       u32 seq_nr:3;
-       u32 extended:1; /* if false is struct selfid */
-       /* byte */
-       u32 porte:2;
-       u32 portd:2;
-       u32 portc:2;
-       u32 portb:2;
-       /* byte */
-       u32 more_packets:1;
-       u32 reserved2:1;
-       u32 porth:2;
-       u32 portg:2;
-       u32 portf:2;
-} __attribute__((packed));
-
-#else
-#error What? PDP endian?
-#endif /* __BIG_ENDIAN_BITFIELD */
-
-#endif /* _IEEE1394_IEEE1394_H */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
deleted file mode 100644 (file)
index 8723380..0000000
+++ /dev/null
@@ -1,1380 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Core support: hpsb_packet management, packet handling and forwarding to
- *               highlevel or lowlevel code
- *
- * Copyright (C) 1999, 2000 Andreas E. Bombe
- *                     2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        loopback functionality in hpsb_send_packet
- *        allow highlevel drivers to disable automatic response generation
- *              and to generate responses themselves (deferred)
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/bitops.h>
-#include <linux/kdev_t.h>
-#include <linux/freezer.h>
-#include <linux/suspend.h>
-#include <linux/kthread.h>
-#include <linux/preempt.h>
-#include <linux/time.h>
-
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include "ieee1394_types.h"
-#include "ieee1394.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "ieee1394_transactions.h"
-#include "csr.h"
-#include "nodemgr.h"
-#include "dma.h"
-#include "iso.h"
-#include "config_roms.h"
-
-/*
- * Disable the nodemgr detection and config rom reading functionality.
- */
-static int disable_nodemgr;
-module_param(disable_nodemgr, int, 0444);
-MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
-
-/* Disable Isochronous Resource Manager functionality */
-int hpsb_disable_irm = 0;
-module_param_named(disable_irm, hpsb_disable_irm, bool, 0444);
-MODULE_PARM_DESC(disable_irm,
-                "Disable Isochronous Resource Manager functionality.");
-
-/* We are GPL, so treat us special */
-MODULE_LICENSE("GPL");
-
-/* Some globals used */
-const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
-struct class *hpsb_protocol_class;
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
-{
-       int i;
-
-       size /= 4;
-       size = (size > 4 ? 4 : size);
-
-       printk(KERN_DEBUG "ieee1394: %s", text);
-       if (speed > -1 && speed < 6)
-               printk(" at %s", hpsb_speedto_str[speed]);
-       printk(":");
-       for (i = 0; i < size; i++)
-               printk(" %08x", data[i]);
-       printk("\n");
-}
-#else
-#define dump_packet(a,b,c,d) do {} while (0)
-#endif
-
-static void abort_requests(struct hpsb_host *host);
-static void queue_packet_complete(struct hpsb_packet *packet);
-
-
-/**
- * hpsb_set_packet_complete_task - set task that runs when a packet completes
- * @packet: the packet whose completion we want the task added to
- * @routine: function to call
- * @data: data (if any) to pass to the above function
- *
- * Set the task that runs when a packet completes. You cannot call this more
- * than once on a single packet before it is sent.
- *
- * Typically, the complete @routine is responsible to call hpsb_free_packet().
- */
-void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
-                                  void (*routine)(void *), void *data)
-{
-       WARN_ON(packet->complete_routine != NULL);
-       packet->complete_routine = routine;
-       packet->complete_data = data;
-       return;
-}
-
-/**
- * hpsb_alloc_packet - allocate new packet structure
- * @data_size: size of the data block to be allocated, in bytes
- *
- * This function allocates, initializes and returns a new &struct hpsb_packet.
- * It can be used in interrupt context.  A header block is always included and
- * initialized with zeros.  Its size is big enough to contain all possible 1394
- * headers.  The data block is only allocated if @data_size is not zero.
- *
- * For packets for which responses will be received the @data_size has to be big
- * enough to contain the response's data block since no further allocation
- * occurs at response matching time.
- *
- * The packet's generation value will be set to the current generation number
- * for ease of use.  Remember to overwrite it with your own recorded generation
- * number if you can not be sure that your code will not race with a bus reset.
- *
- * Return value: A pointer to a &struct hpsb_packet or NULL on allocation
- * failure.
- */
-struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
-{
-       struct hpsb_packet *packet;
-
-       data_size = ((data_size + 3) & ~3);
-
-       packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC);
-       if (!packet)
-               return NULL;
-
-       packet->state = hpsb_unused;
-       packet->generation = -1;
-       INIT_LIST_HEAD(&packet->driver_list);
-       INIT_LIST_HEAD(&packet->queue);
-       atomic_set(&packet->refcnt, 1);
-
-       if (data_size) {
-               packet->data = packet->embedded_data;
-               packet->allocated_data_size = data_size;
-       }
-       return packet;
-}
-
-/**
- * hpsb_free_packet - free packet and data associated with it
- * @packet: packet to free (is NULL safe)
- *
- * Frees @packet->data only if it was allocated through hpsb_alloc_packet().
- */
-void hpsb_free_packet(struct hpsb_packet *packet)
-{
-       if (packet && atomic_dec_and_test(&packet->refcnt)) {
-               BUG_ON(!list_empty(&packet->driver_list) ||
-                      !list_empty(&packet->queue));
-               kfree(packet);
-       }
-}
-
-/**
- * hpsb_reset_bus - initiate bus reset on the given host
- * @host: host controller whose bus to reset
- * @type: one of enum reset_types
- *
- * Returns 1 if bus reset already in progress, 0 otherwise.
- */
-int hpsb_reset_bus(struct hpsb_host *host, int type)
-{
-       if (!host->in_bus_reset) {
-               host->driver->devctl(host, RESET_BUS, type);
-               return 0;
-       } else {
-               return 1;
-       }
-}
-
-/**
- * hpsb_read_cycle_timer - read cycle timer register and system time
- * @host: host whose isochronous cycle timer register is read
- * @cycle_timer: address of bitfield to return the register contents
- * @local_time: address to return the system time
- *
- * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
- * format is also read from non-OHCI controllers. * @local_time contains the
- * system time in microseconds since the Epoch, read at the moment when the
- * cycle timer was read.
- *
- * Return value: 0 for success or error number otherwise.
- */
-int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
-                         u64 *local_time)
-{
-       int ctr;
-       struct timeval tv;
-       unsigned long flags;
-
-       if (!host || !cycle_timer || !local_time)
-               return -EINVAL;
-
-       preempt_disable();
-       local_irq_save(flags);
-
-       ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-       if (ctr)
-               do_gettimeofday(&tv);
-
-       local_irq_restore(flags);
-       preempt_enable();
-
-       if (!ctr)
-               return -EIO;
-       *cycle_timer = ctr;
-       *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
-       return 0;
-}
-
-/**
- * hpsb_bus_reset - notify a bus reset to the core
- *
- * For host driver module usage.  Safe to use in interrupt context, although
- * quite complex; so you may want to run it in the bottom rather than top half.
- *
- * Returns 1 if bus reset already in progress, 0 otherwise.
- */
-int hpsb_bus_reset(struct hpsb_host *host)
-{
-       if (host->in_bus_reset) {
-               HPSB_NOTICE("%s called while bus reset already in progress",
-                           __func__);
-               return 1;
-       }
-
-       abort_requests(host);
-       host->in_bus_reset = 1;
-       host->irm_id = -1;
-       host->is_irm = 0;
-       host->busmgr_id = -1;
-       host->is_busmgr = 0;
-       host->is_cycmst = 0;
-       host->node_count = 0;
-       host->selfid_count = 0;
-
-       return 0;
-}
-
-
-/*
- * Verify num_of_selfids SelfIDs and return number of nodes.  Return zero in
- * case verification failed.
- */
-static int check_selfids(struct hpsb_host *host)
-{
-       int nodeid = -1;
-       int rest_of_selfids = host->selfid_count;
-       struct selfid *sid = (struct selfid *)host->topology_map;
-       struct ext_selfid *esid;
-       int esid_seq = 23;
-
-       host->nodes_active = 0;
-
-       while (rest_of_selfids--) {
-               if (!sid->extended) {
-                       nodeid++;
-                       esid_seq = 0;
-
-                       if (sid->phy_id != nodeid) {
-                               HPSB_INFO("SelfIDs failed monotony check with "
-                                         "%d", sid->phy_id);
-                               return 0;
-                       }
-
-                       if (sid->link_active) {
-                               host->nodes_active++;
-                               if (sid->contender)
-                                       host->irm_id = LOCAL_BUS | sid->phy_id;
-                       }
-               } else {
-                       esid = (struct ext_selfid *)sid;
-
-                       if ((esid->phy_id != nodeid)
-                           || (esid->seq_nr != esid_seq)) {
-                               HPSB_INFO("SelfIDs failed monotony check with "
-                                         "%d/%d", esid->phy_id, esid->seq_nr);
-                               return 0;
-                       }
-                       esid_seq++;
-               }
-               sid++;
-       }
-
-       esid = (struct ext_selfid *)(sid - 1);
-       while (esid->extended) {
-               if ((esid->porta == SELFID_PORT_PARENT) ||
-                   (esid->portb == SELFID_PORT_PARENT) ||
-                   (esid->portc == SELFID_PORT_PARENT) ||
-                   (esid->portd == SELFID_PORT_PARENT) ||
-                   (esid->porte == SELFID_PORT_PARENT) ||
-                   (esid->portf == SELFID_PORT_PARENT) ||
-                   (esid->portg == SELFID_PORT_PARENT) ||
-                   (esid->porth == SELFID_PORT_PARENT)) {
-                       HPSB_INFO("SelfIDs failed root check on "
-                                 "extended SelfID");
-                       return 0;
-               }
-               esid--;
-       }
-
-       sid = (struct selfid *)esid;
-       if ((sid->port0 == SELFID_PORT_PARENT) ||
-           (sid->port1 == SELFID_PORT_PARENT) ||
-           (sid->port2 == SELFID_PORT_PARENT)) {
-               HPSB_INFO("SelfIDs failed root check");
-               return 0;
-       }
-
-       host->node_count = nodeid + 1;
-       return 1;
-}
-
-static void build_speed_map(struct hpsb_host *host, int nodecount)
-{
-       u8 cldcnt[nodecount];
-       u8 *map = host->speed_map;
-       u8 *speedcap = host->speed;
-       u8 local_link_speed = host->csr.lnk_spd;
-       struct selfid *sid;
-       struct ext_selfid *esid;
-       int i, j, n;
-
-       for (i = 0; i < (nodecount * 64); i += 64) {
-               for (j = 0; j < nodecount; j++) {
-                       map[i+j] = IEEE1394_SPEED_MAX;
-               }
-       }
-
-       for (i = 0; i < nodecount; i++) {
-               cldcnt[i] = 0;
-       }
-
-       /* find direct children count and speed */
-       for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
-                    n = nodecount - 1;
-            (void *)sid >= (void *)host->topology_map; sid--) {
-               if (sid->extended) {
-                       esid = (struct ext_selfid *)sid;
-
-                       if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
-                } else {
-                       if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
-
-                       speedcap[n] = sid->speed;
-                       if (speedcap[n] > local_link_speed)
-                               speedcap[n] = local_link_speed;
-                       n--;
-               }
-       }
-
-       /* set self mapping */
-       for (i = 0; i < nodecount; i++) {
-               map[64*i + i] = speedcap[i];
-       }
-
-       /* fix up direct children count to total children count;
-        * also fix up speedcaps for sibling and parent communication */
-       for (i = 1; i < nodecount; i++) {
-               for (j = cldcnt[i], n = i - 1; j > 0; j--) {
-                       cldcnt[i] += cldcnt[n];
-                       speedcap[n] = min(speedcap[n], speedcap[i]);
-                       n -= cldcnt[n] + 1;
-               }
-       }
-
-       for (n = 0; n < nodecount; n++) {
-               for (i = n - cldcnt[n]; i <= n; i++) {
-                       for (j = 0; j < (n - cldcnt[n]); j++) {
-                               map[j*64 + i] = map[i*64 + j] =
-                                       min(map[i*64 + j], speedcap[n]);
-                       }
-                       for (j = n + 1; j < nodecount; j++) {
-                               map[j*64 + i] = map[i*64 + j] =
-                                       min(map[i*64 + j], speedcap[n]);
-                       }
-               }
-       }
-
-       /* assume a maximum speed for 1394b PHYs, nodemgr will correct it */
-       if (local_link_speed > SELFID_SPEED_UNKNOWN)
-               for (i = 0; i < nodecount; i++)
-                       if (speedcap[i] == SELFID_SPEED_UNKNOWN)
-                               speedcap[i] = local_link_speed;
-}
-
-
-/**
- * hpsb_selfid_received - hand over received selfid packet to the core
- *
- * For host driver module usage.  Safe to use in interrupt context.
- *
- * The host driver should have done a successful complement check (second
- * quadlet is complement of first) beforehand.
- */
-void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
-{
-       if (host->in_bus_reset) {
-               HPSB_VERBOSE("Including SelfID 0x%x", sid);
-               host->topology_map[host->selfid_count++] = sid;
-       } else {
-               HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
-                           sid, NODEID_TO_BUS(host->node_id));
-       }
-}
-
-/**
- * hpsb_selfid_complete - notify completion of SelfID stage to the core
- *
- * For host driver module usage.  Safe to use in interrupt context, although
- * quite complex; so you may want to run it in the bottom rather than top half.
- *
- * Notify completion of SelfID stage to the core and report new physical ID
- * and whether host is root now.
- */
-void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
-{
-       if (!host->in_bus_reset)
-               HPSB_NOTICE("SelfID completion called outside of bus reset!");
-
-       host->node_id = LOCAL_BUS | phyid;
-       host->is_root = isroot;
-
-       if (!check_selfids(host)) {
-               if (host->reset_retries++ < 20) {
-                       /* selfid stage did not complete without error */
-                       HPSB_NOTICE("Error in SelfID stage, resetting");
-                       host->in_bus_reset = 0;
-                       /* this should work from ohci1394 now... */
-                       hpsb_reset_bus(host, LONG_RESET);
-                       return;
-               } else {
-                       HPSB_NOTICE("Stopping out-of-control reset loop");
-                       HPSB_NOTICE("Warning - topology map and speed map will not be valid");
-                       host->reset_retries = 0;
-               }
-       } else {
-               host->reset_retries = 0;
-               build_speed_map(host, host->node_count);
-       }
-
-       HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
-                    "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
-
-       /* irm_id is kept up to date by check_selfids() */
-       if (host->irm_id == host->node_id) {
-               host->is_irm = 1;
-       } else {
-               host->is_busmgr = 0;
-               host->is_irm = 0;
-       }
-
-       if (isroot) {
-               host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
-               host->is_cycmst = 1;
-       }
-       atomic_inc(&host->generation);
-       host->in_bus_reset = 0;
-       highlevel_host_reset(host);
-}
-
-static DEFINE_SPINLOCK(pending_packets_lock);
-
-/**
- * hpsb_packet_sent - notify core of sending a packet
- *
- * For host driver module usage.  Safe to call from within a transmit packet
- * routine.
- *
- * Notify core of sending a packet.  Ackcode is the ack code returned for async
- * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
- * for other cases (internal errors that don't justify a panic).
- */
-void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                     int ackcode)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       packet->ack_code = ackcode;
-
-       if (packet->no_waiter || packet->state == hpsb_complete) {
-               /* if packet->no_waiter, must not have a tlabel allocated */
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               hpsb_free_packet(packet);
-               return;
-       }
-
-       atomic_dec(&packet->refcnt);    /* drop HC's reference */
-       /* here the packet must be on the host->pending_packets queue */
-
-       if (ackcode != ACK_PENDING || !packet->expect_response) {
-               packet->state = hpsb_complete;
-               list_del_init(&packet->queue);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               queue_packet_complete(packet);
-               return;
-       }
-
-       packet->state = hpsb_pending;
-       packet->sendtime = jiffies;
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       mod_timer(&host->timeout, jiffies + host->timeout_interval);
-}
-
-/**
- * hpsb_send_phy_config - transmit a PHY configuration packet on the bus
- * @host: host that PHY config packet gets sent through
- * @rootid: root whose force_root bit should get set (-1 = don't set force_root)
- * @gapcnt: gap count value to set (-1 = don't set gap count)
- *
- * This function sends a PHY config packet on the bus through the specified
- * host.
- *
- * Return value: 0 for success or negative error number otherwise.
- */
-int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
-{
-       struct hpsb_packet *packet;
-       quadlet_t d = 0;
-       int retval = 0;
-
-       if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
-          (rootid == -1 && gapcnt == -1)) {
-               HPSB_DEBUG("Invalid Parameter: rootid = %d   gapcnt = %d",
-                          rootid, gapcnt);
-               return -EINVAL;
-       }
-
-       if (rootid != -1)
-               d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
-       if (gapcnt != -1)
-               d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
-
-       packet = hpsb_make_phypacket(host, d);
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = get_hpsb_generation(host);
-       retval = hpsb_send_packet_and_wait(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-/**
- * hpsb_send_packet - transmit a packet on the bus
- * @packet: packet to send
- *
- * The packet is sent through the host specified in the packet->host field.
- * Before sending, the packet's transmit speed is automatically determined
- * using the local speed map when it is an async, non-broadcast packet.
- *
- * Possibilities for failure are that host is either not initialized, in bus
- * reset, the packet's generation number doesn't match the current generation
- * number or the host reports a transmit error.
- *
- * Return value: 0 on success, negative errno on failure.
- */
-int hpsb_send_packet(struct hpsb_packet *packet)
-{
-       struct hpsb_host *host = packet->host;
-
-       if (host->is_shutdown)
-               return -EINVAL;
-       if (host->in_bus_reset ||
-           (packet->generation != get_hpsb_generation(host)))
-               return -EAGAIN;
-
-       packet->state = hpsb_queued;
-
-       /* This just seems silly to me */
-       WARN_ON(packet->no_waiter && packet->expect_response);
-
-       if (!packet->no_waiter || packet->expect_response) {
-               unsigned long flags;
-
-               atomic_inc(&packet->refcnt);
-               /* Set the initial "sendtime" to 10 seconds from now, to
-                  prevent premature expiry.  If a packet takes more than
-                  10 seconds to hit the wire, we have bigger problems :) */
-               packet->sendtime = jiffies + 10 * HZ;
-               spin_lock_irqsave(&pending_packets_lock, flags);
-               list_add_tail(&packet->queue, &host->pending_packets);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-       }
-
-       if (packet->node_id == host->node_id) {
-               /* it is a local request, so handle it locally */
-
-               quadlet_t *data;
-               size_t size = packet->data_size + packet->header_size;
-
-               data = kmalloc(size, GFP_ATOMIC);
-               if (!data) {
-                       HPSB_ERR("unable to allocate memory for concatenating header and data");
-                       return -ENOMEM;
-               }
-
-               memcpy(data, packet->header, packet->header_size);
-
-               if (packet->data_size)
-                       memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
-
-               dump_packet("send packet local", packet->header, packet->header_size, -1);
-
-               hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
-               hpsb_packet_received(host, data, size, 0);
-
-               kfree(data);
-
-               return 0;
-       }
-
-       if (packet->type == hpsb_async &&
-           NODEID_TO_NODE(packet->node_id) != ALL_NODES)
-               packet->speed_code =
-                       host->speed[NODEID_TO_NODE(packet->node_id)];
-
-       dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
-
-       return host->driver->transmit_packet(host, packet);
-}
-
-/* We could just use complete() directly as the packet complete
- * callback, but this is more typesafe, in the sense that we get a
- * compiler error if the prototype for complete() changes. */
-
-static void complete_packet(void *data)
-{
-       complete((struct completion *) data);
-}
-
-/**
- * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes
- * @packet: packet to send
- *
- * Return value: 0 on success, negative errno on failure.
- */
-int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
-{
-       struct completion done;
-       int retval;
-
-       init_completion(&done);
-       hpsb_set_packet_complete_task(packet, complete_packet, &done);
-       retval = hpsb_send_packet(packet);
-       if (retval == 0)
-               wait_for_completion(&done);
-
-       return retval;
-}
-
-static void send_packet_nocare(struct hpsb_packet *packet)
-{
-       if (hpsb_send_packet(packet) < 0) {
-               hpsb_free_packet(packet);
-       }
-}
-
-static size_t packet_size_to_data_size(size_t packet_size, size_t header_size,
-                                      size_t buffer_size, int tcode)
-{
-       size_t ret = packet_size <= header_size ? 0 : packet_size - header_size;
-
-       if (unlikely(ret > buffer_size))
-               ret = buffer_size;
-
-       if (unlikely(ret + header_size != packet_size))
-               HPSB_ERR("unexpected packet size %zd (tcode %d), bug?",
-                        packet_size, tcode);
-       return ret;
-}
-
-static void handle_packet_response(struct hpsb_host *host, int tcode,
-                                  quadlet_t *data, size_t size)
-{
-       struct hpsb_packet *packet;
-       int tlabel = (data[0] >> 10) & 0x3f;
-       size_t header_size;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       list_for_each_entry(packet, &host->pending_packets, queue)
-               if (packet->tlabel == tlabel &&
-                   packet->node_id == (data[1] >> 16))
-                       goto found;
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-       HPSB_DEBUG("unsolicited response packet received - %s",
-                  "no tlabel match");
-       dump_packet("contents", data, 16, -1);
-       return;
-
-found:
-       switch (packet->tcode) {
-       case TCODE_WRITEQ:
-       case TCODE_WRITEB:
-               if (unlikely(tcode != TCODE_WRITE_RESPONSE))
-                       break;
-               header_size = 12;
-               size = 0;
-               goto dequeue;
-
-       case TCODE_READQ:
-               if (unlikely(tcode != TCODE_READQ_RESPONSE))
-                       break;
-               header_size = 16;
-               size = 0;
-               goto dequeue;
-
-       case TCODE_READB:
-               if (unlikely(tcode != TCODE_READB_RESPONSE))
-                       break;
-               header_size = 16;
-               size = packet_size_to_data_size(size, header_size,
-                                               packet->allocated_data_size,
-                                               tcode);
-               goto dequeue;
-
-       case TCODE_LOCK_REQUEST:
-               if (unlikely(tcode != TCODE_LOCK_RESPONSE))
-                       break;
-               header_size = 16;
-               size = packet_size_to_data_size(min(size, (size_t)(16 + 8)),
-                                               header_size,
-                                               packet->allocated_data_size,
-                                               tcode);
-               goto dequeue;
-       }
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-       HPSB_DEBUG("unsolicited response packet received - %s",
-                  "tcode mismatch");
-       dump_packet("contents", data, 16, -1);
-       return;
-
-dequeue:
-       list_del_init(&packet->queue);
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       if (packet->state == hpsb_queued) {
-               packet->sendtime = jiffies;
-               packet->ack_code = ACK_PENDING;
-       }
-       packet->state = hpsb_complete;
-
-       memcpy(packet->header, data, header_size);
-       if (size)
-               memcpy(packet->data, data + 4, size);
-
-       queue_packet_complete(packet);
-}
-
-
-static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
-                                              quadlet_t *data, size_t dsize)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(dsize);
-       if (unlikely(p == NULL)) {
-               /* FIXME - send data_error response */
-               HPSB_ERR("out of memory, cannot send response packet");
-               return NULL;
-       }
-
-       p->type = hpsb_async;
-       p->state = hpsb_unused;
-       p->host = host;
-       p->node_id = data[1] >> 16;
-       p->tlabel = (data[0] >> 10) & 0x3f;
-       p->no_waiter = 1;
-
-       p->generation = get_hpsb_generation(host);
-
-       if (dsize % 4)
-               p->data[dsize / 4] = 0;
-
-       return p;
-}
-
-#define PREP_ASYNC_HEAD_RCODE(tc) \
-       packet->tcode = tc; \
-       packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
-               | (1 << 8) | (tc << 4); \
-       packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \
-       packet->header[2] = 0
-
-static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
-                             quadlet_t data)
-{
-       PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
-       packet->header[3] = data;
-       packet->header_size = 16;
-       packet->data_size = 0;
-}
-
-static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
-                              int length)
-{
-       if (rcode != RCODE_COMPLETE)
-               length = 0;
-
-       PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
-}
-
-static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
-{
-       PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
-       packet->header_size = 12;
-       packet->data_size = 0;
-}
-
-static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
-                         int length)
-{
-       if (rcode != RCODE_COMPLETE)
-               length = 0;
-
-       PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);
-       packet->header[3] = (length << 16) | extcode;
-       packet->header_size = 16;
-       packet->data_size = length;
-}
-
-static void handle_incoming_packet(struct hpsb_host *host, int tcode,
-                                  quadlet_t *data, size_t size,
-                                  int write_acked)
-{
-       struct hpsb_packet *packet;
-       int length, rcode, extcode;
-       quadlet_t buffer;
-       nodeid_t source = data[1] >> 16;
-       nodeid_t dest = data[0] >> 16;
-       u16 flags = (u16) data[0];
-       u64 addr;
-
-       /* FIXME?
-        * Out-of-bounds lengths are left for highlevel_read|write to cap. */
-
-       switch (tcode) {
-       case TCODE_WRITEQ:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_write(host, source, dest, data + 3,
-                                       addr, 4, flags);
-               goto handle_write_request;
-
-       case TCODE_WRITEB:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_write(host, source, dest, data + 4,
-                                       addr, data[3] >> 16, flags);
-handle_write_request:
-               if (rcode < 0 || write_acked ||
-                   NODEID_TO_NODE(data[0] >> 16) == NODE_MASK)
-                       return;
-               /* not a broadcast write, reply */
-               packet = create_reply_packet(host, data, 0);
-               if (packet) {
-                       fill_async_write_resp(packet, rcode);
-                       send_packet_nocare(packet);
-               }
-               return;
-
-       case TCODE_READQ:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
-               if (rcode < 0)
-                       return;
-
-               packet = create_reply_packet(host, data, 0);
-               if (packet) {
-                       fill_async_readquad_resp(packet, rcode, buffer);
-                       send_packet_nocare(packet);
-               }
-               return;
-
-       case TCODE_READB:
-               length = data[3] >> 16;
-               packet = create_reply_packet(host, data, length);
-               if (!packet)
-                       return;
-
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_read(host, source, packet->data, addr,
-                                      length, flags);
-               if (rcode < 0) {
-                       hpsb_free_packet(packet);
-                       return;
-               }
-               fill_async_readblock_resp(packet, rcode, length);
-               send_packet_nocare(packet);
-               return;
-
-       case TCODE_LOCK_REQUEST:
-               length = data[3] >> 16;
-               extcode = data[3] & 0xffff;
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-
-               packet = create_reply_packet(host, data, 8);
-               if (!packet)
-                       return;
-
-               if (extcode == 0 || extcode >= 7) {
-                       /* let switch default handle error */
-                       length = 0;
-               }
-
-               switch (length) {
-               case 4:
-                       rcode = highlevel_lock(host, source, packet->data, addr,
-                                              data[4], 0, extcode, flags);
-                       fill_async_lock_resp(packet, rcode, extcode, 4);
-                       break;
-               case 8:
-                       if (extcode != EXTCODE_FETCH_ADD &&
-                           extcode != EXTCODE_LITTLE_ADD) {
-                               rcode = highlevel_lock(host, source,
-                                                      packet->data, addr,
-                                                      data[5], data[4],
-                                                      extcode, flags);
-                               fill_async_lock_resp(packet, rcode, extcode, 4);
-                       } else {
-                               rcode = highlevel_lock64(host, source,
-                                            (octlet_t *)packet->data, addr,
-                                            *(octlet_t *)(data + 4), 0ULL,
-                                            extcode, flags);
-                               fill_async_lock_resp(packet, rcode, extcode, 8);
-                       }
-                       break;
-               case 16:
-                       rcode = highlevel_lock64(host, source,
-                                                (octlet_t *)packet->data, addr,
-                                                *(octlet_t *)(data + 6),
-                                                *(octlet_t *)(data + 4),
-                                                extcode, flags);
-                       fill_async_lock_resp(packet, rcode, extcode, 8);
-                       break;
-               default:
-                       rcode = RCODE_TYPE_ERROR;
-                       fill_async_lock_resp(packet, rcode, extcode, 0);
-               }
-
-               if (rcode < 0)
-                       hpsb_free_packet(packet);
-               else
-                       send_packet_nocare(packet);
-               return;
-       }
-}
-
-/**
- * hpsb_packet_received - hand over received packet to the core
- *
- * For host driver module usage.
- *
- * The contents of data are expected to be the full packet but with the CRCs
- * left out (data block follows header immediately), with the header (i.e. the
- * first four quadlets) in machine byte order and the data block in big endian.
- * *@data can be safely overwritten after this call.
- *
- * If the packet is a write request, @write_acked is to be set to true if it was
- * ack_complete'd already, false otherwise.  This argument is ignored for any
- * other packet type.
- */
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                         int write_acked)
-{
-       int tcode;
-
-       if (unlikely(host->in_bus_reset)) {
-               HPSB_DEBUG("received packet during reset; ignoring");
-               return;
-       }
-
-       dump_packet("received packet", data, size, -1);
-
-       tcode = (data[0] >> 4) & 0xf;
-
-       switch (tcode) {
-       case TCODE_WRITE_RESPONSE:
-       case TCODE_READQ_RESPONSE:
-       case TCODE_READB_RESPONSE:
-       case TCODE_LOCK_RESPONSE:
-               handle_packet_response(host, tcode, data, size);
-               break;
-
-       case TCODE_WRITEQ:
-       case TCODE_WRITEB:
-       case TCODE_READQ:
-       case TCODE_READB:
-       case TCODE_LOCK_REQUEST:
-               handle_incoming_packet(host, tcode, data, size, write_acked);
-               break;
-
-       case TCODE_CYCLE_START:
-               /* simply ignore this packet if it is passed on */
-               break;
-
-       default:
-               HPSB_DEBUG("received packet with bogus transaction code %d",
-                          tcode);
-               break;
-       }
-}
-
-static void abort_requests(struct hpsb_host *host)
-{
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       unsigned long flags;
-
-       host->driver->devctl(host, CANCEL_REQUESTS, 0);
-
-       INIT_LIST_HEAD(&tmp);
-       spin_lock_irqsave(&pending_packets_lock, flags);
-       list_splice_init(&host->pending_packets, &tmp);
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &tmp, queue) {
-               list_del_init(&packet->queue);
-               packet->state = hpsb_complete;
-               packet->ack_code = ACKX_ABORTED;
-               queue_packet_complete(packet);
-       }
-}
-
-void abort_timedouts(unsigned long __opaque)
-{
-       struct hpsb_host *host = (struct hpsb_host *)__opaque;
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       unsigned long flags, expire, j;
-
-       spin_lock_irqsave(&host->csr.lock, flags);
-       expire = host->csr.expire;
-       spin_unlock_irqrestore(&host->csr.lock, flags);
-
-       j = jiffies;
-       INIT_LIST_HEAD(&tmp);
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &host->pending_packets, queue) {
-               if (time_before(packet->sendtime + expire, j))
-                       list_move_tail(&packet->queue, &tmp);
-               else
-                       /* Since packets are added to the tail, the oldest
-                        * ones are first, always. When we get to one that
-                        * isn't timed out, the rest aren't either. */
-                       break;
-       }
-       if (!list_empty(&host->pending_packets))
-               mod_timer(&host->timeout, j + host->timeout_interval);
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &tmp, queue) {
-               list_del_init(&packet->queue);
-               packet->state = hpsb_complete;
-               packet->ack_code = ACKX_TIMEOUT;
-               queue_packet_complete(packet);
-       }
-}
-
-static struct task_struct *khpsbpkt_thread;
-static LIST_HEAD(hpsbpkt_queue);
-
-static void queue_packet_complete(struct hpsb_packet *packet)
-{
-       unsigned long flags;
-
-       if (packet->no_waiter) {
-               hpsb_free_packet(packet);
-               return;
-       }
-       if (packet->complete_routine != NULL) {
-               spin_lock_irqsave(&pending_packets_lock, flags);
-               list_add_tail(&packet->queue, &hpsbpkt_queue);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               wake_up_process(khpsbpkt_thread);
-       }
-       return;
-}
-
-/*
- * Kernel thread which handles packets that are completed.  This way the
- * packet's "complete" function is asynchronously run in process context.
- * Only packets which have a "complete" function may be sent here.
- */
-static int hpsbpkt_thread(void *__hi)
-{
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       int may_schedule;
-
-       while (!kthread_should_stop()) {
-
-               INIT_LIST_HEAD(&tmp);
-               spin_lock_irq(&pending_packets_lock);
-               list_splice_init(&hpsbpkt_queue, &tmp);
-               spin_unlock_irq(&pending_packets_lock);
-
-               list_for_each_entry_safe(packet, p, &tmp, queue) {
-                       list_del_init(&packet->queue);
-                       packet->complete_routine(packet->complete_data);
-               }
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               spin_lock_irq(&pending_packets_lock);
-               may_schedule = list_empty(&hpsbpkt_queue);
-               spin_unlock_irq(&pending_packets_lock);
-               if (may_schedule)
-                       schedule();
-               __set_current_state(TASK_RUNNING);
-       }
-       return 0;
-}
-
-static int __init ieee1394_init(void)
-{
-       int i, ret;
-
-       /* non-fatal error */
-       if (hpsb_init_config_roms()) {
-               HPSB_ERR("Failed to initialize some config rom entries.\n");
-               HPSB_ERR("Some features may not be available\n");
-       }
-
-       khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt");
-       if (IS_ERR(khpsbpkt_thread)) {
-               HPSB_ERR("Failed to start hpsbpkt thread!\n");
-               ret = PTR_ERR(khpsbpkt_thread);
-               goto exit_cleanup_config_roms;
-       }
-
-       if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
-               HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
-               ret = -ENODEV;
-               goto exit_release_kernel_thread;
-       }
-
-       ret = bus_register(&ieee1394_bus_type);
-       if (ret < 0) {
-               HPSB_INFO("bus register failed");
-               goto release_chrdev;
-       }
-
-       for (i = 0; fw_bus_attrs[i]; i++) {
-               ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-               if (ret < 0) {
-                       while (i >= 0) {
-                               bus_remove_file(&ieee1394_bus_type,
-                                               fw_bus_attrs[i--]);
-                       }
-                       bus_unregister(&ieee1394_bus_type);
-                       goto release_chrdev;
-               }
-       }
-
-       ret = class_register(&hpsb_host_class);
-       if (ret < 0)
-               goto release_all_bus;
-
-       hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
-       if (IS_ERR(hpsb_protocol_class)) {
-               ret = PTR_ERR(hpsb_protocol_class);
-               goto release_class_host;
-       }
-
-       ret = init_csr();
-       if (ret) {
-               HPSB_INFO("init csr failed");
-               ret = -ENOMEM;
-               goto release_class_protocol;
-       }
-
-       if (disable_nodemgr) {
-               HPSB_INFO("nodemgr and IRM functionality disabled");
-               /* We shouldn't contend for IRM with nodemgr disabled, since
-                  nodemgr implements functionality required of ieee1394a-2000
-                  IRMs */
-               hpsb_disable_irm = 1;
-
-               return 0;
-       }
-
-       if (hpsb_disable_irm) {
-               HPSB_INFO("IRM functionality disabled");
-       }
-
-       ret = init_ieee1394_nodemgr();
-       if (ret < 0) {
-               HPSB_INFO("init nodemgr failed");
-               goto cleanup_csr;
-       }
-
-       return 0;
-
-cleanup_csr:
-       cleanup_csr();
-release_class_protocol:
-       class_destroy(hpsb_protocol_class);
-release_class_host:
-       class_unregister(&hpsb_host_class);
-release_all_bus:
-       for (i = 0; fw_bus_attrs[i]; i++)
-               bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-       bus_unregister(&ieee1394_bus_type);
-release_chrdev:
-       unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
-exit_release_kernel_thread:
-       kthread_stop(khpsbpkt_thread);
-exit_cleanup_config_roms:
-       hpsb_cleanup_config_roms();
-       return ret;
-}
-
-static void __exit ieee1394_cleanup(void)
-{
-       int i;
-
-       if (!disable_nodemgr)
-               cleanup_ieee1394_nodemgr();
-
-       cleanup_csr();
-
-       class_destroy(hpsb_protocol_class);
-       class_unregister(&hpsb_host_class);
-       for (i = 0; fw_bus_attrs[i]; i++)
-               bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-       bus_unregister(&ieee1394_bus_type);
-
-       kthread_stop(khpsbpkt_thread);
-
-       hpsb_cleanup_config_roms();
-
-       unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
-}
-
-fs_initcall(ieee1394_init);
-module_exit(ieee1394_cleanup);
-
-/* Exported symbols */
-
-/** hosts.c **/
-EXPORT_SYMBOL(hpsb_alloc_host);
-EXPORT_SYMBOL(hpsb_add_host);
-EXPORT_SYMBOL(hpsb_resume_host);
-EXPORT_SYMBOL(hpsb_remove_host);
-EXPORT_SYMBOL(hpsb_update_config_rom_image);
-
-/** ieee1394_core.c **/
-EXPORT_SYMBOL(hpsb_speedto_str);
-EXPORT_SYMBOL(hpsb_protocol_class);
-EXPORT_SYMBOL(hpsb_set_packet_complete_task);
-EXPORT_SYMBOL(hpsb_alloc_packet);
-EXPORT_SYMBOL(hpsb_free_packet);
-EXPORT_SYMBOL(hpsb_send_packet);
-EXPORT_SYMBOL(hpsb_reset_bus);
-EXPORT_SYMBOL(hpsb_read_cycle_timer);
-EXPORT_SYMBOL(hpsb_bus_reset);
-EXPORT_SYMBOL(hpsb_selfid_received);
-EXPORT_SYMBOL(hpsb_selfid_complete);
-EXPORT_SYMBOL(hpsb_packet_sent);
-EXPORT_SYMBOL(hpsb_packet_received);
-EXPORT_SYMBOL_GPL(hpsb_disable_irm);
-
-/** ieee1394_transactions.c **/
-EXPORT_SYMBOL(hpsb_get_tlabel);
-EXPORT_SYMBOL(hpsb_free_tlabel);
-EXPORT_SYMBOL(hpsb_make_readpacket);
-EXPORT_SYMBOL(hpsb_make_writepacket);
-EXPORT_SYMBOL(hpsb_make_streampacket);
-EXPORT_SYMBOL(hpsb_make_lockpacket);
-EXPORT_SYMBOL(hpsb_make_lock64packet);
-EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_read);
-EXPORT_SYMBOL(hpsb_write);
-EXPORT_SYMBOL(hpsb_lock);
-EXPORT_SYMBOL(hpsb_packet_success);
-
-/** highlevel.c **/
-EXPORT_SYMBOL(hpsb_register_highlevel);
-EXPORT_SYMBOL(hpsb_unregister_highlevel);
-EXPORT_SYMBOL(hpsb_register_addrspace);
-EXPORT_SYMBOL(hpsb_unregister_addrspace);
-EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_get_hostinfo);
-EXPORT_SYMBOL(hpsb_create_hostinfo);
-EXPORT_SYMBOL(hpsb_destroy_hostinfo);
-EXPORT_SYMBOL(hpsb_set_hostinfo_key);
-EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
-EXPORT_SYMBOL(hpsb_set_hostinfo);
-
-/** nodemgr.c **/
-EXPORT_SYMBOL(hpsb_node_fill_packet);
-EXPORT_SYMBOL(hpsb_node_write);
-EXPORT_SYMBOL(__hpsb_register_protocol);
-EXPORT_SYMBOL(hpsb_unregister_protocol);
-
-/** csr.c **/
-EXPORT_SYMBOL(hpsb_update_config_rom);
-
-/** dma.c **/
-EXPORT_SYMBOL(dma_prog_region_init);
-EXPORT_SYMBOL(dma_prog_region_alloc);
-EXPORT_SYMBOL(dma_prog_region_free);
-EXPORT_SYMBOL(dma_region_init);
-EXPORT_SYMBOL(dma_region_alloc);
-EXPORT_SYMBOL(dma_region_free);
-EXPORT_SYMBOL(dma_region_sync_for_cpu);
-EXPORT_SYMBOL(dma_region_sync_for_device);
-EXPORT_SYMBOL(dma_region_mmap);
-EXPORT_SYMBOL(dma_region_offset_to_bus);
-
-/** iso.c **/
-EXPORT_SYMBOL(hpsb_iso_xmit_init);
-EXPORT_SYMBOL(hpsb_iso_recv_init);
-EXPORT_SYMBOL(hpsb_iso_xmit_start);
-EXPORT_SYMBOL(hpsb_iso_recv_start);
-EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);
-EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);
-EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);
-EXPORT_SYMBOL(hpsb_iso_stop);
-EXPORT_SYMBOL(hpsb_iso_shutdown);
-EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);
-EXPORT_SYMBOL(hpsb_iso_xmit_sync);
-EXPORT_SYMBOL(hpsb_iso_recv_release_packets);
-EXPORT_SYMBOL(hpsb_iso_n_ready);
-EXPORT_SYMBOL(hpsb_iso_packet_sent);
-EXPORT_SYMBOL(hpsb_iso_packet_received);
-EXPORT_SYMBOL(hpsb_iso_wake);
-EXPORT_SYMBOL(hpsb_iso_recv_flush);
-
-/** csr1212.c **/
-EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
-EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
-EXPORT_SYMBOL(csr1212_get_keyval);
-EXPORT_SYMBOL(csr1212_new_directory);
-EXPORT_SYMBOL(csr1212_parse_keyval);
-EXPORT_SYMBOL(csr1212_read);
-EXPORT_SYMBOL(csr1212_release_keyval);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
deleted file mode 100644 (file)
index 28b9f58..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#ifndef _IEEE1394_CORE_H
-#define _IEEE1394_CORE_H
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <asm/atomic.h>
-
-#include "hosts.h"
-#include "ieee1394_types.h"
-
-struct hpsb_packet {
-       /* This struct is basically read-only for hosts with the exception of
-        * the data buffer contents and driver_list. */
-
-       /* This can be used for host driver internal linking.
-        *
-        * NOTE: This must be left in init state when the driver is done
-        * with it (e.g. by using list_del_init()), since the core does
-        * some sanity checks to make sure the packet is not on a
-        * driver_list when free'ing it. */
-       struct list_head driver_list;
-
-       nodeid_t node_id;
-
-       /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
-       enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
-
-       /* Okay, this is core internal and a no care for hosts.
-        * queued   = queued for sending
-        * pending  = sent, waiting for response
-        * complete = processing completed, successful or not
-        */
-       enum {
-               hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
-       } __attribute__((packed)) state;
-
-       /* These are core-internal. */
-       signed char tlabel;
-       signed char ack_code;
-       unsigned char tcode;
-
-       unsigned expect_response:1;
-       unsigned no_waiter:1;
-
-       /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
-       unsigned speed_code:2;
-
-       struct hpsb_host *host;
-       unsigned int generation;
-
-       atomic_t refcnt;
-       struct list_head queue;
-
-       /* Function (and possible data to pass to it) to call when this
-        * packet is completed.  */
-       void (*complete_routine)(void *);
-       void *complete_data;
-
-       /* Store jiffies for implementing bus timeouts. */
-       unsigned long sendtime;
-
-       /* Core-internal.  */
-       size_t allocated_data_size;     /* as allocated */
-
-       /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
-       size_t data_size;               /* as filled in */
-       size_t header_size;             /* as filled in, not counting the CRC */
-
-       /* Buffers */
-       quadlet_t *data;                /* can be DMA-mapped */
-       quadlet_t header[5];
-       quadlet_t embedded_data[0];     /* keep as last member */
-};
-
-void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
-                                  void (*routine)(void *), void *data);
-static inline struct hpsb_packet *driver_packet(struct list_head *l)
-{
-       return list_entry(l, struct hpsb_packet, driver_list);
-}
-void abort_timedouts(unsigned long __opaque);
-struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
-void hpsb_free_packet(struct hpsb_packet *packet);
-
-/**
- * get_hpsb_generation - generation counter for the complete 1394 subsystem
- *
- * Generation gets incremented on every change in the subsystem (notably on bus
- * resets). Use the functions, not the variable.
- */
-static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
-{
-       return atomic_read(&host->generation);
-}
-
-int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt);
-int hpsb_send_packet(struct hpsb_packet *packet);
-int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
-int hpsb_reset_bus(struct hpsb_host *host, int type);
-int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
-                         u64 *local_time);
-
-int hpsb_bus_reset(struct hpsb_host *host);
-void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid);
-void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
-void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                     int ackcode);
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                         int write_acked);
-
-/*
- * CHARACTER DEVICE DISPATCHING
- *
- * All ieee1394 character device drivers share the same major number
- * (major 171).  The 256 minor numbers are allocated to the various
- * task-specific interfaces (raw1394, video1394, dv1394, etc) in
- * blocks of 16.
- *
- * The core ieee1394.o module allocates the device number region
- * 171:0-255, the various drivers must then cdev_add() their cdev
- * objects to handle their respective sub-regions.
- *
- * Minor device number block allocations:
- *
- * Block 0  (  0- 15)  raw1394
- * Block 1  ( 16- 31)  video1394
- * Block 2  ( 32- 47)  dv1394
- *
- * Blocks 3-14 free for future allocation
- *
- * Block 15 (240-255)  reserved for drivers under development, etc.
- */
-
-#define IEEE1394_MAJOR                  171
-
-#define IEEE1394_MINOR_BLOCK_RAW1394      0
-#define IEEE1394_MINOR_BLOCK_VIDEO1394    1
-#define IEEE1394_MINOR_BLOCK_DV1394       2
-#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
-
-#define IEEE1394_CORE_DEV        MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV     MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV   MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV      MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
-
-/**
- * ieee1394_file_to_instance - get the index within a minor number block
- */
-static inline unsigned char ieee1394_file_to_instance(struct file *file)
-{
-       int idx = cdev_index(file->f_path.dentry->d_inode);
-       if (idx < 0)
-               idx = 0;
-       return idx;
-}
-
-extern int hpsb_disable_irm;
-
-/* Our sysfs bus entry */
-extern struct bus_type ieee1394_bus_type;
-extern struct class hpsb_host_class;
-extern struct class *hpsb_protocol_class;
-
-#endif /* _IEEE1394_CORE_H */
diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h
deleted file mode 100644 (file)
index dd5500e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _IEEE1394_HOTPLUG_H
-#define _IEEE1394_HOTPLUG_H
-
-/* Unit spec id and sw version entry for some protocols */
-#define AVC_UNIT_SPEC_ID_ENTRY         0x0000A02D
-#define AVC_SW_VERSION_ENTRY           0x00010001
-#define CAMERA_UNIT_SPEC_ID_ENTRY      0x0000A02D
-#define CAMERA_SW_VERSION_ENTRY                0x00000100
-
-/* /include/linux/mod_devicetable.h defines:
- *     IEEE1394_MATCH_VENDOR_ID
- *     IEEE1394_MATCH_MODEL_ID
- *     IEEE1394_MATCH_SPECIFIER_ID
- *     IEEE1394_MATCH_VERSION
- *     struct ieee1394_device_id
- */
-#include <linux/mod_devicetable.h>
-
-#endif /* _IEEE1394_HOTPLUG_H */
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
deleted file mode 100644 (file)
index 675b313..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Transaction support.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/hardirq.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/sched.h>  /* because linux/wait.h is broken if CONFIG_SMP=n */
-#include <linux/wait.h>
-
-#include <asm/bug.h>
-#include <asm/errno.h>
-#include <asm/system.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "ieee1394_transactions.h"
-
-#define PREP_ASYNC_HEAD_ADDRESS(tc) \
-        packet->tcode = tc; \
-        packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
-                | (1 << 8) | (tc << 4); \
-        packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
-        packet->header[2] = addr & 0xffffffff
-
-#ifndef HPSB_DEBUG_TLABELS
-static
-#endif
-DEFINE_SPINLOCK(hpsb_tlabel_lock);
-
-static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
-
-static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
-       packet->header_size = 12;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_readblock(struct hpsb_packet *packet, u64 addr,
-                                int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_writequad(struct hpsb_packet *packet, u64 addr,
-                                quadlet_t data)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
-       packet->header[3] = data;
-       packet->header_size = 16;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr,
-                                 int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->expect_response = 1;
-       packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
-}
-
-static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
-                           int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
-       packet->header[3] = (length << 16) | extcode;
-       packet->header_size = 16;
-       packet->data_size = length;
-       packet->expect_response = 1;
-}
-
-static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
-{
-       packet->header[0] = data;
-       packet->header[1] = ~data;
-       packet->header_size = 8;
-       packet->data_size = 0;
-       packet->expect_response = 0;
-       packet->type = hpsb_raw;        /* No CRC added */
-       packet->speed_code = IEEE1394_SPEED_100;        /* Force speed to be 100Mbps */
-}
-
-static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
-                                    int channel, int tag, int sync)
-{
-       packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-           | (TCODE_STREAM_DATA << 4) | sync;
-
-       packet->header_size = 4;
-       packet->data_size = length;
-       packet->type = hpsb_async;
-       packet->tcode = TCODE_ISO_DATA;
-}
-
-/* same as hpsb_get_tlabel, except that it returns immediately */
-static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
-{
-       unsigned long flags, *tp;
-       u8 *next;
-       int tlabel, n = NODEID_TO_NODE(packet->node_id);
-
-       /* Broadcast transactions are complete once the request has been sent.
-        * Use the same transaction label for all broadcast transactions. */
-       if (unlikely(n == ALL_NODES)) {
-               packet->tlabel = 0;
-               return 0;
-       }
-       tp = packet->host->tl_pool[n].map;
-       next = &packet->host->next_tl[n];
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       tlabel = find_next_zero_bit(tp, 64, *next);
-       if (tlabel > 63)
-               tlabel = find_first_zero_bit(tp, 64);
-       if (tlabel > 63) {
-               spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-               return -EAGAIN;
-       }
-       __set_bit(tlabel, tp);
-       *next = (tlabel + 1) & 63;
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       packet->tlabel = tlabel;
-       return 0;
-}
-
-/**
- * hpsb_get_tlabel - allocate a transaction label
- * @packet: the packet whose tlabel and tl_pool we set
- *
- * Every asynchronous transaction on the 1394 bus needs a transaction
- * label to match the response to the request.  This label has to be
- * different from any other transaction label in an outstanding request to
- * the same node to make matching possible without ambiguity.
- *
- * There are 64 different tlabels, so an allocated tlabel has to be freed
- * with hpsb_free_tlabel() after the transaction is complete (unless it's
- * reused again for the same target node).
- *
- * Return value: Zero on success, otherwise non-zero. A non-zero return
- * generally means there are no available tlabels. If this is called out
- * of interrupt or atomic context, then it will sleep until can return a
- * tlabel or a signal is received.
- */
-int hpsb_get_tlabel(struct hpsb_packet *packet)
-{
-       if (irqs_disabled() || in_atomic())
-               return hpsb_get_tlabel_atomic(packet);
-
-       /* NB: The macro wait_event_interruptible() is called with a condition
-        * argument with side effect.  This is only possible because the side
-        * effect does not occur until the condition became true, and
-        * wait_event_interruptible() won't evaluate the condition again after
-        * that. */
-       return wait_event_interruptible(tlabel_wq,
-                                       !hpsb_get_tlabel_atomic(packet));
-}
-
-/**
- * hpsb_free_tlabel - free an allocated transaction label
- * @packet: packet whose tlabel and tl_pool needs to be cleared
- *
- * Frees the transaction label allocated with hpsb_get_tlabel().  The
- * tlabel has to be freed after the transaction is complete (i.e. response
- * was received for a split transaction or packet was sent for a unified
- * transaction).
- *
- * A tlabel must not be freed twice.
- */
-void hpsb_free_tlabel(struct hpsb_packet *packet)
-{
-       unsigned long flags, *tp;
-       int tlabel, n = NODEID_TO_NODE(packet->node_id);
-
-       if (unlikely(n == ALL_NODES))
-               return;
-       tp = packet->host->tl_pool[n].map;
-       tlabel = packet->tlabel;
-       BUG_ON(tlabel > 63 || tlabel < 0);
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       BUG_ON(!__test_and_clear_bit(tlabel, tp));
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       wake_up_interruptible(&tlabel_wq);
-}
-
-/**
- * hpsb_packet_success - Make sense of the ack and reply codes
- *
- * Make sense of the ack and reply codes and return more convenient error codes:
- * 0 = success.  -%EBUSY = node is busy, try again.  -%EAGAIN = error which can
- * probably resolved by retry.  -%EREMOTEIO = node suffers from an internal
- * error.  -%EACCES = this transaction is not allowed on requested address.
- * -%EINVAL = invalid address at node.
- */
-int hpsb_packet_success(struct hpsb_packet *packet)
-{
-       switch (packet->ack_code) {
-       case ACK_PENDING:
-               switch ((packet->header[1] >> 12) & 0xf) {
-               case RCODE_COMPLETE:
-                       return 0;
-               case RCODE_CONFLICT_ERROR:
-                       return -EAGAIN;
-               case RCODE_DATA_ERROR:
-                       return -EREMOTEIO;
-               case RCODE_TYPE_ERROR:
-                       return -EACCES;
-               case RCODE_ADDRESS_ERROR:
-                       return -EINVAL;
-               default:
-                       HPSB_ERR("received reserved rcode %d from node %d",
-                                (packet->header[1] >> 12) & 0xf,
-                                packet->node_id);
-                       return -EAGAIN;
-               }
-
-       case ACK_BUSY_X:
-       case ACK_BUSY_A:
-       case ACK_BUSY_B:
-               return -EBUSY;
-
-       case ACK_TYPE_ERROR:
-               return -EACCES;
-
-       case ACK_COMPLETE:
-               if (packet->tcode == TCODE_WRITEQ
-                   || packet->tcode == TCODE_WRITEB) {
-                       return 0;
-               } else {
-                       HPSB_ERR("impossible ack_complete from node %d "
-                                "(tcode %d)", packet->node_id, packet->tcode);
-                       return -EAGAIN;
-               }
-
-       case ACK_DATA_ERROR:
-               if (packet->tcode == TCODE_WRITEB
-                   || packet->tcode == TCODE_LOCK_REQUEST) {
-                       return -EAGAIN;
-               } else {
-                       HPSB_ERR("impossible ack_data_error from node %d "
-                                "(tcode %d)", packet->node_id, packet->tcode);
-                       return -EAGAIN;
-               }
-
-       case ACK_ADDRESS_ERROR:
-               return -EINVAL;
-
-       case ACK_TARDY:
-       case ACK_CONFLICT_ERROR:
-       case ACKX_NONE:
-       case ACKX_SEND_ERROR:
-       case ACKX_ABORTED:
-       case ACKX_TIMEOUT:
-               /* error while sending */
-               return -EAGAIN;
-
-       default:
-               HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
-                        packet->ack_code, packet->node_id, packet->tcode);
-               return -EAGAIN;
-       }
-}
-
-struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, size_t length)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       packet->host = host;
-       packet->node_id = node;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       if (length == 4)
-               fill_async_readquad(packet, addr);
-       else
-               fill_async_readblock(packet, addr, length);
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node,
-                                         u64 addr, quadlet_t * buffer,
-                                         size_t length)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       if (length % 4) {       /* zero padding bytes */
-               packet->data[length >> 2] = 0;
-       }
-       packet->host = host;
-       packet->node_id = node;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       if (length == 4) {
-               fill_async_writequad(packet, addr, buffer ? *buffer : 0);
-       } else {
-               fill_async_writeblock(packet, addr, length);
-               if (buffer)
-                       memcpy(packet->data, buffer, length);
-       }
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
-                                          int length, int channel, int tag,
-                                          int sync)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       if (length % 4) {       /* zero padding bytes */
-               packet->data[length >> 2] = 0;
-       }
-       packet->host = host;
-
-       /* Because it is too difficult to determine all PHY speeds and link
-        * speeds here, we use S100... */
-       packet->speed_code = IEEE1394_SPEED_100;
-
-       /* ...and prevent hpsb_send_packet() from overriding it. */
-       packet->node_id = LOCAL_BUS | ALL_NODES;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       fill_async_stream_packet(packet, length, channel, tag, sync);
-       if (buffer)
-               memcpy(packet->data, buffer, length);
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, int extcode,
-                                        quadlet_t * data, quadlet_t arg)
-{
-       struct hpsb_packet *p;
-       u32 length;
-
-       p = hpsb_alloc_packet(8);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       p->node_id = node;
-       if (hpsb_get_tlabel(p)) {
-               hpsb_free_packet(p);
-               return NULL;
-       }
-
-       switch (extcode) {
-       case EXTCODE_FETCH_ADD:
-       case EXTCODE_LITTLE_ADD:
-               length = 4;
-               if (data)
-                       p->data[0] = *data;
-               break;
-       default:
-               length = 8;
-               if (data) {
-                       p->data[0] = arg;
-                       p->data[1] = *data;
-               }
-               break;
-       }
-       fill_async_lock(p, addr, extcode, length);
-
-       return p;
-}
-
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
-                                          nodeid_t node, u64 addr, int extcode,
-                                          octlet_t * data, octlet_t arg)
-{
-       struct hpsb_packet *p;
-       u32 length;
-
-       p = hpsb_alloc_packet(16);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       p->node_id = node;
-       if (hpsb_get_tlabel(p)) {
-               hpsb_free_packet(p);
-               return NULL;
-       }
-
-       switch (extcode) {
-       case EXTCODE_FETCH_ADD:
-       case EXTCODE_LITTLE_ADD:
-               length = 8;
-               if (data) {
-                       p->data[0] = *data >> 32;
-                       p->data[1] = *data & 0xffffffff;
-               }
-               break;
-       default:
-               length = 16;
-               if (data) {
-                       p->data[0] = arg >> 32;
-                       p->data[1] = arg & 0xffffffff;
-                       p->data[2] = *data >> 32;
-                       p->data[3] = *data & 0xffffffff;
-               }
-               break;
-       }
-       fill_async_lock(p, addr, extcode, length);
-
-       return p;
-}
-
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(0);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       fill_phy_packet(p, data);
-
-       return p;
-}
-
-/*
- * FIXME - these functions should probably read from / write to user space to
- * avoid in kernel buffers for user space callers
- */
-
-/**
- * hpsb_read - generic read function
- *
- * Recognizes the local node ID and act accordingly.  Automatically uses a
- * quadlet read request if @length == 4 and and a block read request otherwise.
- * It does not yet support lengths that are not a multiple of 4.
- *
- * You must explicitly specifiy the @generation for which the node ID is valid,
- * to avoid sending packets to the wrong nodes when we race with a bus reset.
- */
-int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, quadlet_t * buffer, size_t length)
-{
-       struct hpsb_packet *packet;
-       int retval = 0;
-
-       if (length == 0)
-               return -EINVAL;
-
-       packet = hpsb_make_readpacket(host, node, addr, length);
-
-       if (!packet) {
-               return -ENOMEM;
-       }
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_read_fail;
-
-       retval = hpsb_packet_success(packet);
-
-       if (retval == 0) {
-               if (length == 4) {
-                       *buffer = packet->header[3];
-               } else {
-                       memcpy(buffer, packet->data, length);
-               }
-       }
-
-      hpsb_read_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-/**
- * hpsb_write - generic write function
- *
- * Recognizes the local node ID and act accordingly.  Automatically uses a
- * quadlet write request if @length == 4 and and a block write request
- * otherwise.  It does not yet support lengths that are not a multiple of 4.
- *
- * You must explicitly specifiy the @generation for which the node ID is valid,
- * to avoid sending packets to the wrong nodes when we race with a bus reset.
- */
-int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-              u64 addr, quadlet_t * buffer, size_t length)
-{
-       struct hpsb_packet *packet;
-       int retval;
-
-       if (length == 0)
-               return -EINVAL;
-
-       packet = hpsb_make_writepacket(host, node, addr, buffer, length);
-
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_write_fail;
-
-       retval = hpsb_packet_success(packet);
-
-      hpsb_write_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
-{
-       struct hpsb_packet *packet;
-       int retval = 0;
-
-       packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_lock_fail;
-
-       retval = hpsb_packet_success(packet);
-
-       if (retval == 0)
-               *data = packet->data[0];
-
-hpsb_lock_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
deleted file mode 100644 (file)
index 20b693b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _IEEE1394_TRANSACTIONS_H
-#define _IEEE1394_TRANSACTIONS_H
-
-#include <linux/types.h>
-
-#include "ieee1394_types.h"
-
-struct hpsb_packet;
-struct hpsb_host;
-
-int hpsb_get_tlabel(struct hpsb_packet *packet);
-void hpsb_free_tlabel(struct hpsb_packet *packet);
-struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, size_t length);
-struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, int extcode, quadlet_t *data,
-                                        quadlet_t arg);
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
-                                          nodeid_t node, u64 addr, int extcode,
-                                          octlet_t *data, octlet_t arg);
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
-                                         nodeid_t node, u64 addr,
-                                         quadlet_t *buffer, size_t length);
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
-                                           int length, int channel, int tag,
-                                          int sync);
-int hpsb_packet_success(struct hpsb_packet *packet);
-int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-              u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
-
-#ifdef HPSB_DEBUG_TLABELS
-extern spinlock_t hpsb_tlabel_lock;
-#endif
-
-#endif /* _IEEE1394_TRANSACTIONS_H */
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
deleted file mode 100644 (file)
index 9803aaa..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef _IEEE1394_TYPES_H
-#define _IEEE1394_TYPES_H
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-typedef u32 quadlet_t;
-typedef u64 octlet_t;
-typedef u16 nodeid_t;
-
-typedef u8  byte_t;
-typedef u64 nodeaddr_t;
-typedef u16 arm_length_t;
-
-#define BUS_MASK  0xffc0
-#define BUS_SHIFT 6
-#define NODE_MASK 0x003f
-#define LOCAL_BUS 0xffc0
-#define ALL_NODES 0x003f
-
-#define NODEID_TO_BUS(nodeid)  ((nodeid & BUS_MASK) >> BUS_SHIFT)
-#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
-
-/* Can be used to consistently print a node/bus ID. */
-#define NODE_BUS_FMT           "%d-%02d:%04d"
-#define NODE_BUS_ARGS(__host, __nodeid)        \
-       __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid)
-
-#define HPSB_PRINT(level, fmt, args...) \
-       printk(level "ieee1394: " fmt "\n" , ## args)
-
-#define HPSB_DEBUG(fmt, args...)       HPSB_PRINT(KERN_DEBUG, fmt , ## args)
-#define HPSB_INFO(fmt, args...)                HPSB_PRINT(KERN_INFO, fmt , ## args)
-#define HPSB_NOTICE(fmt, args...)      HPSB_PRINT(KERN_NOTICE, fmt , ## args)
-#define HPSB_WARN(fmt, args...)                HPSB_PRINT(KERN_WARNING, fmt , ## args)
-#define HPSB_ERR(fmt, args...)         HPSB_PRINT(KERN_ERR, fmt , ## args)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define HPSB_VERBOSE(fmt, args...)     HPSB_PRINT(KERN_DEBUG, fmt , ## args)
-#define HPSB_DEBUG_TLABELS
-#else
-#define HPSB_VERBOSE(fmt, args...)     do {} while (0)
-#endif
-
-#ifdef __BIG_ENDIAN
-
-static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count)
-{
-       void *tmp = dest;
-       u32 *src = (u32 *)__src;
-
-       count /= 4;
-       while (count--)
-               *dest++ = swab32p(src++);
-       return tmp;
-}
-
-#else
-
-static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count)
-{
-       return memcpy(dest, src, count);
-}
-
-#endif /* __BIG_ENDIAN */
-
-#endif /* _IEEE1394_TYPES_H */
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
deleted file mode 100644 (file)
index 1cf6487..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * kernel ISO transmission/reception
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include "hosts.h"
-#include "iso.h"
-
-/**
- * hpsb_iso_stop - stop DMA
- */
-void hpsb_iso_stop(struct hpsb_iso *iso)
-{
-       if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
-               return;
-
-       iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
-                                 XMIT_STOP : RECV_STOP, 0);
-       iso->flags &= ~HPSB_ISO_DRIVER_STARTED;
-}
-
-/**
- * hpsb_iso_shutdown - deallocate buffer and DMA context
- */
-void hpsb_iso_shutdown(struct hpsb_iso *iso)
-{
-       if (iso->flags & HPSB_ISO_DRIVER_INIT) {
-               hpsb_iso_stop(iso);
-               iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
-                                         XMIT_SHUTDOWN : RECV_SHUTDOWN, 0);
-               iso->flags &= ~HPSB_ISO_DRIVER_INIT;
-       }
-
-       dma_region_free(&iso->data_buf);
-       kfree(iso);
-}
-
-static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
-                                            enum hpsb_iso_type type,
-                                            unsigned int data_buf_size,
-                                            unsigned int buf_packets,
-                                            int channel, int dma_mode,
-                                            int irq_interval,
-                                            void (*callback) (struct hpsb_iso
-                                                              *))
-{
-       struct hpsb_iso *iso;
-       int dma_direction;
-
-       /* make sure driver supports the ISO API */
-       if (!host->driver->isoctl) {
-               printk(KERN_INFO
-                      "ieee1394: host driver '%s' does not support the rawiso API\n",
-                      host->driver->name);
-               return NULL;
-       }
-
-       /* sanitize parameters */
-
-       if (buf_packets < 2)
-               buf_packets = 2;
-
-       if ((dma_mode < HPSB_ISO_DMA_DEFAULT)
-           || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
-               dma_mode = HPSB_ISO_DMA_DEFAULT;
-
-       if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
-               irq_interval = buf_packets / 4;
-       if (irq_interval == 0)  /* really interrupt for each packet */
-               irq_interval = 1;
-
-       if (channel < -1 || channel >= 64)
-               return NULL;
-
-       /* channel = -1 is OK for multi-channel recv but not for xmit */
-       if (type == HPSB_ISO_XMIT && channel < 0)
-               return NULL;
-
-       /* allocate and write the struct hpsb_iso */
-
-       iso =
-           kmalloc(sizeof(*iso) +
-                   buf_packets * sizeof(struct hpsb_iso_packet_info),
-                   GFP_KERNEL);
-       if (!iso)
-               return NULL;
-
-       iso->infos = (struct hpsb_iso_packet_info *)(iso + 1);
-
-       iso->type = type;
-       iso->host = host;
-       iso->hostdata = NULL;
-       iso->callback = callback;
-       init_waitqueue_head(&iso->waitq);
-       iso->channel = channel;
-       iso->irq_interval = irq_interval;
-       iso->dma_mode = dma_mode;
-       dma_region_init(&iso->data_buf);
-       iso->buf_size = PAGE_ALIGN(data_buf_size);
-       iso->buf_packets = buf_packets;
-       iso->pkt_dma = 0;
-       iso->first_packet = 0;
-       spin_lock_init(&iso->lock);
-
-       if (iso->type == HPSB_ISO_XMIT) {
-               iso->n_ready_packets = iso->buf_packets;
-               dma_direction = PCI_DMA_TODEVICE;
-       } else {
-               iso->n_ready_packets = 0;
-               dma_direction = PCI_DMA_FROMDEVICE;
-       }
-
-       atomic_set(&iso->overflows, 0);
-       iso->bytes_discarded = 0;
-       iso->flags = 0;
-       iso->prebuffer = 0;
-
-       /* allocate the packet buffer */
-       if (dma_region_alloc
-           (&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
-               goto err;
-
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_n_ready - returns number of packets ready to send or receive
- */
-int hpsb_iso_n_ready(struct hpsb_iso *iso)
-{
-       unsigned long flags;
-       int val;
-
-       spin_lock_irqsave(&iso->lock, flags);
-       val = iso->n_ready_packets;
-       spin_unlock_irqrestore(&iso->lock, flags);
-
-       return val;
-}
-
-/**
- * hpsb_iso_xmit_init - allocate the buffer and DMA context
- */
-struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int speed,
-                                   int irq_interval,
-                                   void (*callback) (struct hpsb_iso *))
-{
-       struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
-                                                   data_buf_size, buf_packets,
-                                                   channel,
-                                                   HPSB_ISO_DMA_DEFAULT,
-                                                   irq_interval, callback);
-       if (!iso)
-               return NULL;
-
-       iso->speed = speed;
-
-       /* tell the driver to start working */
-       if (host->driver->isoctl(iso, XMIT_INIT, 0))
-               goto err;
-
-       iso->flags |= HPSB_ISO_DRIVER_INIT;
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_recv_init - allocate the buffer and DMA context
- *
- * Note, if channel = -1, multi-channel receive is enabled.
- */
-struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int dma_mode,
-                                   int irq_interval,
-                                   void (*callback) (struct hpsb_iso *))
-{
-       struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
-                                                   data_buf_size, buf_packets,
-                                                   channel, dma_mode,
-                                                   irq_interval, callback);
-       if (!iso)
-               return NULL;
-
-       /* tell the driver to start working */
-       if (host->driver->isoctl(iso, RECV_INIT, 0))
-               goto err;
-
-       iso->flags |= HPSB_ISO_DRIVER_INIT;
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_recv_listen_channel
- *
- * multi-channel only
- */
-int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel);
-}
-
-/**
- * hpsb_iso_recv_unlisten_channel
- *
- * multi-channel only
- */
-int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
-}
-
-/**
- * hpsb_iso_recv_set_channel_mask
- *
- * multi-channel only
- */
-int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK,
-                                        (unsigned long)&mask);
-}
-
-/**
- * hpsb_iso_recv_flush - check for arrival of new packets
- *
- * check for arrival of new packets immediately (even if irq_interval
- * has not yet been reached)
- */
-int hpsb_iso_recv_flush(struct hpsb_iso *iso)
-{
-       if (iso->type != HPSB_ISO_RECV)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_FLUSH, 0);
-}
-
-static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
-{
-       int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle);
-       if (retval)
-               return retval;
-
-       iso->flags |= HPSB_ISO_DRIVER_STARTED;
-       return retval;
-}
-
-/**
- * hpsb_iso_xmit_start - start DMA
- */
-int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
-{
-       if (iso->type != HPSB_ISO_XMIT)
-               return -1;
-
-       if (iso->flags & HPSB_ISO_DRIVER_STARTED)
-               return 0;
-
-       if (cycle < -1)
-               cycle = -1;
-       else if (cycle >= 8000)
-               cycle %= 8000;
-
-       iso->xmit_cycle = cycle;
-
-       if (prebuffer < 0)
-               prebuffer = iso->buf_packets - 1;
-       else if (prebuffer == 0)
-               prebuffer = 1;
-
-       if (prebuffer >= iso->buf_packets)
-               prebuffer = iso->buf_packets - 1;
-
-       iso->prebuffer = prebuffer;
-
-       /* remember the starting cycle; DMA will commence from xmit_queue_packets()
-          once enough packets have been buffered */
-       iso->start_cycle = cycle;
-
-       return 0;
-}
-
-/**
- * hpsb_iso_recv_start - start DMA
- */
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
-{
-       int retval = 0;
-       int isoctl_args[3];
-
-       if (iso->type != HPSB_ISO_RECV)
-               return -1;
-
-       if (iso->flags & HPSB_ISO_DRIVER_STARTED)
-               return 0;
-
-       if (cycle < -1)
-               cycle = -1;
-       else if (cycle >= 8000)
-               cycle %= 8000;
-
-       isoctl_args[0] = cycle;
-
-       if (tag_mask < 0)
-               /* match all tags */
-               tag_mask = 0xF;
-       isoctl_args[1] = tag_mask;
-
-       isoctl_args[2] = sync;
-
-       retval =
-           iso->host->driver->isoctl(iso, RECV_START,
-                                     (unsigned long)&isoctl_args[0]);
-       if (retval)
-               return retval;
-
-       iso->flags |= HPSB_ISO_DRIVER_STARTED;
-       return retval;
-}
-
-/* check to make sure the user has not supplied bogus values of offset/len
- * that would cause the kernel to access memory outside the buffer */
-static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
-                                    unsigned int offset, unsigned short len,
-                                    unsigned int *out_offset,
-                                    unsigned short *out_len)
-{
-       if (offset >= iso->buf_size)
-               return -EFAULT;
-
-       /* make sure the packet does not go beyond the end of the buffer */
-       if (offset + len > iso->buf_size)
-               return -EFAULT;
-
-       /* check for wrap-around */
-       if (offset + len < offset)
-               return -EFAULT;
-
-       /* now we can trust 'offset' and 'length' */
-       *out_offset = offset;
-       *out_len = len;
-
-       return 0;
-}
-
-/**
- * hpsb_iso_xmit_queue_packet - queue a packet for transmission.
- *
- * @offset is relative to the beginning of the DMA buffer, where the packet's
- * data payload should already have been placed.
- */
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
-                              u8 tag, u8 sy)
-{
-       struct hpsb_iso_packet_info *info;
-       unsigned long flags;
-       int rv;
-
-       if (iso->type != HPSB_ISO_XMIT)
-               return -EINVAL;
-
-       /* is there space in the buffer? */
-       if (iso->n_ready_packets <= 0) {
-               return -EBUSY;
-       }
-
-       info = &iso->infos[iso->first_packet];
-
-       /* check for bogus offset/length */
-       if (hpsb_iso_check_offset_len
-           (iso, offset, len, &info->offset, &info->len))
-               return -EFAULT;
-
-       info->tag = tag;
-       info->sy = sy;
-
-       spin_lock_irqsave(&iso->lock, flags);
-
-       rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info);
-       if (rv)
-               goto out;
-
-       /* increment cursors */
-       iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
-       iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000;
-       iso->n_ready_packets--;
-
-       if (iso->prebuffer != 0) {
-               iso->prebuffer--;
-               if (iso->prebuffer <= 0) {
-                       iso->prebuffer = 0;
-                       rv = do_iso_xmit_start(iso, iso->start_cycle);
-               }
-       }
-
-      out:
-       spin_unlock_irqrestore(&iso->lock, flags);
-       return rv;
-}
-
-/**
- * hpsb_iso_xmit_sync - wait until all queued packets have been transmitted
- */
-int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
-{
-       if (iso->type != HPSB_ISO_XMIT)
-               return -EINVAL;
-
-       return wait_event_interruptible(iso->waitq,
-                                       hpsb_iso_n_ready(iso) ==
-                                       iso->buf_packets);
-}
-
-/**
- * hpsb_iso_packet_sent
- *
- * Available to low-level drivers.
- *
- * Call after a packet has been transmitted to the bus (interrupt context is
- * OK).  @cycle is the _exact_ cycle the packet was sent on.  @error should be
- * non-zero if some sort of error occurred when sending the packet.
- */
-void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&iso->lock, flags);
-
-       /* predict the cycle of the next packet to be queued */
-
-       /* jump ahead by the number of packets that are already buffered */
-       cycle += iso->buf_packets - iso->n_ready_packets;
-       cycle %= 8000;
-
-       iso->xmit_cycle = cycle;
-       iso->n_ready_packets++;
-       iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
-
-       if (iso->n_ready_packets == iso->buf_packets || error != 0) {
-               /* the buffer has run empty! */
-               atomic_inc(&iso->overflows);
-       }
-
-       spin_unlock_irqrestore(&iso->lock, flags);
-}
-
-/**
- * hpsb_iso_packet_received
- *
- * Available to low-level drivers.
- *
- * Call after a packet has been received (interrupt context is OK).
- */
-void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-                             u16 total_len, u16 cycle, u8 channel, u8 tag,
-                             u8 sy)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&iso->lock, flags);
-
-       if (iso->n_ready_packets == iso->buf_packets) {
-               /* overflow! */
-               atomic_inc(&iso->overflows);
-               /* Record size of this discarded packet */
-               iso->bytes_discarded += total_len;
-       } else {
-               struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma];
-               info->offset = offset;
-               info->len = len;
-               info->total_len = total_len;
-               info->cycle = cycle;
-               info->channel = channel;
-               info->tag = tag;
-               info->sy = sy;
-
-               iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
-               iso->n_ready_packets++;
-       }
-
-       spin_unlock_irqrestore(&iso->lock, flags);
-}
-
-/**
- * hpsb_iso_recv_release_packets - release packets, reuse buffer
- *
- * @n_packets have been read out of the buffer, re-use the buffer space
- */
-int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
-{
-       unsigned long flags;
-       unsigned int i;
-       int rv = 0;
-
-       if (iso->type != HPSB_ISO_RECV)
-               return -1;
-
-       spin_lock_irqsave(&iso->lock, flags);
-       for (i = 0; i < n_packets; i++) {
-               rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
-                                              (unsigned long)&iso->infos[iso->
-                                                                         first_packet]);
-               if (rv)
-                       break;
-
-               iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
-               iso->n_ready_packets--;
-
-               /* release memory from packets discarded when queue was full  */
-               if (iso->n_ready_packets == 0) {        /* Release only after all prior packets handled */
-                       if (iso->bytes_discarded != 0) {
-                               struct hpsb_iso_packet_info inf;
-                               inf.total_len = iso->bytes_discarded;
-                               iso->host->driver->isoctl(iso, RECV_RELEASE,
-                                                         (unsigned long)&inf);
-                               iso->bytes_discarded = 0;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&iso->lock, flags);
-       return rv;
-}
-
-/**
- * hpsb_iso_wake
- *
- * Available to low-level drivers.
- *
- * Call to wake waiting processes after buffer space has opened up.
- */
-void hpsb_iso_wake(struct hpsb_iso *iso)
-{
-       wake_up_interruptible(&iso->waitq);
-
-       if (iso->callback)
-               iso->callback(iso);
-}
diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
deleted file mode 100644 (file)
index c2089c0..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * kernel ISO transmission/reception
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#ifndef IEEE1394_ISO_H
-#define IEEE1394_ISO_H
-
-#include <linux/spinlock_types.h>
-#include <linux/wait.h>
-#include <asm/atomic.h>
-#include <asm/types.h>
-
-#include "dma.h"
-
-struct hpsb_host;
-
-/* high-level ISO interface */
-
-/*
- * This API sends and receives isochronous packets on a large,
- * virtually-contiguous kernel memory buffer. The buffer may be mapped
- * into a user-space process for zero-copy transmission and reception.
- *
- * There are no explicit boundaries between packets in the buffer. A
- * packet may be transmitted or received at any location. However,
- * low-level drivers may impose certain restrictions on alignment or
- * size of packets. (e.g. in OHCI no packet may cross a page boundary,
- * and packets should be quadlet-aligned)
- */
-
-/* Packet descriptor - the API maintains a ring buffer of these packet
- * descriptors in kernel memory (hpsb_iso.infos[]).  */
-struct hpsb_iso_packet_info {
-       /* offset of data payload relative to the first byte of the buffer */
-       __u32 offset;
-
-       /* length of the data payload, in bytes (not including the isochronous
-        * header) */
-       __u16 len;
-
-       /* (recv only) the cycle number (mod 8000) on which the packet was
-        * received */
-       __u16 cycle;
-
-       /* (recv only) channel on which the packet was received */
-       __u8 channel;
-
-       /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */
-       __u8 tag;
-       __u8 sy;
-
-       /* length in bytes of the packet including header/trailer.
-        * MUST be at structure end, since the first part of this structure is
-        * also defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is
-        * copied to userspace and is accessed there through libraw1394. */
-       __u16 total_len;
-};
-
-enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
-
-/* The mode of the dma when receiving iso data. Must be supported by chip */
-enum raw1394_iso_dma_recv_mode {
-       HPSB_ISO_DMA_DEFAULT = -1,
-       HPSB_ISO_DMA_OLD_ABI = 0,
-       HPSB_ISO_DMA_BUFFERFILL = 1,
-       HPSB_ISO_DMA_PACKET_PER_BUFFER = 2
-};
-
-struct hpsb_iso {
-       enum hpsb_iso_type type;
-
-       /* pointer to low-level driver and its private data */
-       struct hpsb_host *host;
-       void *hostdata;
-
-       /* a function to be called (from interrupt context) after
-        * outgoing packets have been sent, or incoming packets have
-        * arrived */
-       void (*callback)(struct hpsb_iso*);
-
-       /* wait for buffer space */
-       wait_queue_head_t waitq;
-
-       int speed; /* IEEE1394_SPEED_100, 200, or 400 */
-       int channel; /* -1 if multichannel */
-       int dma_mode; /* dma receive mode */
-
-
-       /* greatest # of packets between interrupts - controls
-        * the maximum latency of the buffer */
-       int irq_interval;
-
-       /* the buffer for packet data payloads */
-       struct dma_region data_buf;
-
-       /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */
-       unsigned int buf_size;
-
-       /* # of packets in the ringbuffer */
-       unsigned int buf_packets;
-
-       /* protects packet cursors */
-       spinlock_t lock;
-
-       /* the index of the next packet that will be produced
-          or consumed by the user */
-       int first_packet;
-
-       /* the index of the next packet that will be transmitted
-          or received by the 1394 hardware */
-       int pkt_dma;
-
-       /* how many packets, starting at first_packet:
-        * (transmit) are ready to be filled with data
-        * (receive)  contain received data */
-       int n_ready_packets;
-
-       /* how many times the buffer has overflowed or underflowed */
-       atomic_t overflows;
-       /* how many cycles were skipped for a given context */
-       atomic_t skips;
-
-       /* Current number of bytes lost in discarded packets */
-       int bytes_discarded;
-
-       /* private flags to track initialization progress */
-#define HPSB_ISO_DRIVER_INIT     (1<<0)
-#define HPSB_ISO_DRIVER_STARTED  (1<<1)
-       unsigned int flags;
-
-       /* # of packets left to prebuffer (xmit only) */
-       int prebuffer;
-
-       /* starting cycle for DMA (xmit only) */
-       int start_cycle;
-
-       /* cycle at which next packet will be transmitted,
-        * -1 if not known */
-       int xmit_cycle;
-
-       /* ringbuffer of packet descriptors in regular kernel memory
-        * XXX Keep this last, since we use over-allocated memory from
-        * this entry to fill this field. */
-       struct hpsb_iso_packet_info *infos;
-};
-
-/* functions available to high-level drivers (e.g. raw1394) */
-
-struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int speed,
-                                   int irq_interval,
-                                   void (*callback)(struct hpsb_iso*));
-struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int dma_mode,
-                                   int irq_interval,
-                                   void (*callback)(struct hpsb_iso*));
-int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel);
-int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
-int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
-int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle,
-                       int prebuffer);
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle,
-                       int tag_mask, int sync);
-void hpsb_iso_stop(struct hpsb_iso *iso);
-void hpsb_iso_shutdown(struct hpsb_iso *iso);
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
-                              u8 tag, u8 sy);
-int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
-int hpsb_iso_recv_release_packets(struct hpsb_iso *recv,
-                                 unsigned int n_packets);
-int hpsb_iso_recv_flush(struct hpsb_iso *iso);
-int hpsb_iso_n_ready(struct hpsb_iso *iso);
-
-/* the following are callbacks available to low-level drivers */
-
-void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
-void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-                             u16 total_len, u16 cycle, u8 channel, u8 tag,
-                             u8 sy);
-void hpsb_iso_wake(struct hpsb_iso *iso);
-
-#endif /* IEEE1394_ISO_H */
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
deleted file mode 100644 (file)
index 1835021..0000000
+++ /dev/null
@@ -1,1901 +0,0 @@
-/*
- * Node information (ConfigROM) collection and management.
- *
- * Copyright (C) 2000          Andreas E. Bombe
- *               2001-2003     Ben Collins <bcollins@debian.net>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/bitmap.h>
-#include <linux/kernel.h>
-#include <linux/kmemcheck.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/freezer.h>
-#include <asm/atomic.h>
-
-#include "csr.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "ieee1394_transactions.h"
-#include "nodemgr.h"
-
-static int ignore_drivers;
-module_param(ignore_drivers, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers.");
-
-struct nodemgr_csr_info {
-       struct hpsb_host *host;
-       nodeid_t nodeid;
-       unsigned int generation;
-
-       kmemcheck_bitfield_begin(flags);
-       unsigned int speed_unverified:1;
-       kmemcheck_bitfield_end(flags);
-};
-
-
-/*
- * Correct the speed map entry.  This is necessary
- *  - for nodes with link speed < phy speed,
- *  - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX.
- * A possible speed is determined by trial and error, using quadlet reads.
- */
-static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
-                              quadlet_t *buffer)
-{
-       quadlet_t q;
-       u8 i, *speed, old_speed, good_speed;
-       int error;
-
-       speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
-       old_speed = *speed;
-       good_speed = IEEE1394_SPEED_MAX + 1;
-
-       /* Try every speed from S100 to old_speed.
-        * If we did it the other way around, a too low speed could be caught
-        * if the retry succeeded for some other reason, e.g. because the link
-        * just finished its initialization. */
-       for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
-               *speed = i;
-               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 &q, 4);
-               if (error)
-                       break;
-               *buffer = q;
-               good_speed = i;
-       }
-       if (good_speed <= IEEE1394_SPEED_MAX) {
-               HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s",
-                          NODE_BUS_ARGS(ci->host, ci->nodeid),
-                          hpsb_speedto_str[good_speed]);
-               *speed = good_speed;
-               ci->speed_unverified = 0;
-               return 0;
-       }
-       *speed = old_speed;
-       return error;
-}
-
-static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
-                           void *buffer, void *__ci)
-{
-       struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
-       int i, error;
-
-       for (i = 1; ; i++) {
-               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 buffer, 4);
-               if (!error) {
-                       ci->speed_unverified = 0;
-                       break;
-               }
-               /* Give up after 3rd failure. */
-               if (i == 3)
-                       break;
-
-               /* The ieee1394_core guessed the node's speed capability from
-                * the self ID.  Check whether a lower speed works. */
-               if (ci->speed_unverified) {
-                       error = nodemgr_check_speed(ci, addr, buffer);
-                       if (!error)
-                               break;
-               }
-               if (msleep_interruptible(334))
-                       return -EINTR;
-       }
-       return error;
-}
-
-static struct csr1212_bus_ops nodemgr_csr_ops = {
-       .bus_read =     nodemgr_bus_read,
-};
-
-
-/*
- * Basically what we do here is start off retrieving the bus_info block.
- * From there will fill in some info about the node, verify it is of IEEE
- * 1394 type, and that the crc checks out ok. After that we start off with
- * the root directory, and subdirectories. To do this, we retrieve the
- * quadlet header for a directory, find out the length, and retrieve the
- * complete directory entry (be it a leaf or a directory). We then process
- * it and add the info to our structure for that particular node.
- *
- * We verify CRC's along the way for each directory/block/leaf. The entire
- * node structure is generic, and simply stores the information in a way
- * that's easy to parse by the protocol interface.
- */
-
-/*
- * The nodemgr relies heavily on the Driver Model for device callbacks and
- * driver/device mappings. The old nodemgr used to handle all this itself,
- * but now we are much simpler because of the LDM.
- */
-
-struct host_info {
-       struct hpsb_host *host;
-       struct list_head list;
-       struct task_struct *thread;
-};
-
-static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
-
-struct bus_type ieee1394_bus_type = {
-       .name           = "ieee1394",
-       .match          = nodemgr_bus_match,
-};
-
-static void host_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
-}
-
-struct class hpsb_host_class = {
-       .name           = "ieee1394_host",
-       .dev_release    = host_cls_release,
-};
-
-static void ne_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct node_entry, node_dev)->device);
-}
-
-static struct class nodemgr_ne_class = {
-       .name           = "ieee1394_node",
-       .dev_release    = ne_cls_release,
-};
-
-static void ud_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
-}
-
-/* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway.
- */
-static struct class nodemgr_ud_class = {
-       .name           = "ieee1394",
-       .dev_release    = ud_cls_release,
-       .dev_uevent     = nodemgr_uevent,
-};
-
-static struct hpsb_highlevel nodemgr_highlevel;
-
-
-static void nodemgr_release_ud(struct device *dev)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-
-       if (ud->vendor_name_kv)
-               csr1212_release_keyval(ud->vendor_name_kv);
-       if (ud->model_name_kv)
-               csr1212_release_keyval(ud->model_name_kv);
-
-       kfree(ud);
-}
-
-static void nodemgr_release_ne(struct device *dev)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-
-       if (ne->vendor_name_kv)
-               csr1212_release_keyval(ne->vendor_name_kv);
-
-       kfree(ne);
-}
-
-
-static void nodemgr_release_host(struct device *dev)
-{
-       struct hpsb_host *host = container_of(dev, struct hpsb_host, device);
-
-       csr1212_destroy_csr(host->csr.rom);
-
-       kfree(host);
-}
-
-static int nodemgr_ud_platform_data;
-
-static struct device nodemgr_dev_template_ud = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_ud,
-       .platform_data  = &nodemgr_ud_platform_data,
-};
-
-static struct device nodemgr_dev_template_ne = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_ne,
-};
-
-/* This dummy driver prevents the host devices from being scanned. We have no
- * useful drivers for them yet, and there would be a deadlock possible if the
- * driver core scans the host device while the host's low-level driver (i.e.
- * the host's parent device) is being removed. */
-static struct device_driver nodemgr_mid_layer_driver = {
-       .bus            = &ieee1394_bus_type,
-       .name           = "nodemgr",
-       .owner          = THIS_MODULE,
-};
-
-struct device nodemgr_dev_template_host = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_host,
-};
-
-
-#define fw_attr(class, class_type, field, type, format_string)         \
-static ssize_t fw_show_##class##_##field (struct device *dev, struct device_attribute *attr, char *buf)\
-{                                                                      \
-       class_type *class;                                              \
-       class = container_of(dev, class_type, device);                  \
-       return sprintf(buf, format_string, (type)class->field);         \
-}                                                                      \
-static struct device_attribute dev_attr_##class##_##field = {          \
-       .attr = {.name = __stringify(field), .mode = S_IRUGO },         \
-       .show   = fw_show_##class##_##field,                            \
-};
-
-#define fw_attr_td(class, class_type, td_kv)                           \
-static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attribute *attr, char *buf)\
-{                                                                      \
-       int len;                                                        \
-       class_type *class = container_of(dev, class_type, device);      \
-       len = (class->td_kv->value.leaf.len - 2) * sizeof(quadlet_t);   \
-       memcpy(buf,                                                     \
-              CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv),      \
-              len);                                                    \
-       while (buf[len - 1] == '\0')                                    \
-               len--;                                                  \
-       buf[len++] = '\n';                                              \
-       buf[len] = '\0';                                                \
-       return len;                                                     \
-}                                                                      \
-static struct device_attribute dev_attr_##class##_##td_kv = {          \
-       .attr = {.name = __stringify(td_kv), .mode = S_IRUGO },         \
-       .show   = fw_show_##class##_##td_kv,                            \
-};
-
-
-#define fw_drv_attr(field, type, format_string)                        \
-static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \
-{                                                              \
-       struct hpsb_protocol_driver *driver;                    \
-       driver = container_of(drv, struct hpsb_protocol_driver, driver); \
-       return sprintf(buf, format_string, (type)driver->field);\
-}                                                              \
-static struct driver_attribute driver_attr_drv_##field = {     \
-       .attr = {.name = __stringify(field), .mode = S_IRUGO }, \
-       .show   = fw_drv_show_##field,                          \
-};
-
-
-static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-
-       return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) "
-                      "LSPD(%d) MAX_REC(%d) MAX_ROM(%d) CYC_CLK_ACC(%d)\n",
-                      ne->busopt.irmc,
-                      ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
-                      ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
-                      ne->busopt.max_rec,
-                      ne->busopt.max_rom,
-                      ne->busopt.cyc_clk_acc);
-}
-static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
-
-
-#ifdef HPSB_DEBUG_TLABELS
-static ssize_t fw_show_ne_tlabels_free(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-       unsigned long flags;
-       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
-       int tf;
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       tf = 64 - bitmap_weight(tp, 64);
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       return sprintf(buf, "%d\n", tf);
-}
-static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
-
-
-static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-       unsigned long flags;
-       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
-       u64 tm;
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-#if (BITS_PER_LONG <= 32)
-       tm = ((u64)tp[0] << 32) + tp[1];
-#else
-       tm = tp[0];
-#endif
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       return sprintf(buf, "0x%016llx\n", (unsigned long long)tm);
-}
-static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
-#endif /* HPSB_DEBUG_TLABELS */
-
-
-static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-       int state = simple_strtoul(buf, NULL, 10);
-
-       if (state == 1) {
-               ud->ignore_driver = 1;
-               device_release_driver(dev);
-       } else if (state == 0)
-               ud->ignore_driver = 0;
-
-       return count;
-}
-static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-
-       return sprintf(buf, "%d\n", ud->ignore_driver);
-}
-static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
-
-
-static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
-                            size_t count)
-{
-       int error = 0;
-
-       if (simple_strtoul(buf, NULL, 10) == 1)
-               error = bus_rescan_devices(&ieee1394_bus_type);
-       return error ? error : count;
-}
-static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "You can force a rescan of the bus for "
-                       "drivers by writing a 1 to this file\n");
-}
-static BUS_ATTR(rescan, S_IWUSR | S_IRUGO, fw_get_rescan, fw_set_rescan);
-
-
-static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size_t count)
-{
-       int state = simple_strtoul(buf, NULL, 10);
-
-       if (state == 1)
-               ignore_drivers = 1;
-       else if (state == 0)
-               ignore_drivers = 0;
-
-       return count;
-}
-static ssize_t fw_get_ignore_drivers(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "%d\n", ignore_drivers);
-}
-static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set_ignore_drivers);
-
-
-struct bus_attribute *const fw_bus_attrs[] = {
-       &bus_attr_rescan,
-       &bus_attr_ignore_drivers,
-       NULL
-};
-
-
-fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n")
-
-fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n")
-fw_attr_td(ne, struct node_entry, vendor_name_kv)
-
-fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n")
-fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, in_limbo, int, "%d\n");
-
-static struct device_attribute *const fw_ne_attrs[] = {
-       &dev_attr_ne_guid,
-       &dev_attr_ne_guid_vendor_id,
-       &dev_attr_ne_capabilities,
-       &dev_attr_ne_vendor_id,
-       &dev_attr_ne_nodeid,
-       &dev_attr_bus_options,
-#ifdef HPSB_DEBUG_TLABELS
-       &dev_attr_tlabels_free,
-       &dev_attr_tlabels_mask,
-#endif
-};
-
-
-
-fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n")
-fw_attr(ud, struct unit_directory, length, int, "%d\n")
-/* These are all dependent on the value being provided */
-fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n")
-fw_attr_td(ud, struct unit_directory, vendor_name_kv)
-fw_attr_td(ud, struct unit_directory, model_name_kv)
-
-static struct device_attribute *const fw_ud_attrs[] = {
-       &dev_attr_ud_address,
-       &dev_attr_ud_length,
-       &dev_attr_ignore_driver,
-};
-
-
-fw_attr(host, struct hpsb_host, node_count, int, "%d\n")
-fw_attr(host, struct hpsb_host, selfid_count, int, "%d\n")
-fw_attr(host, struct hpsb_host, nodes_active, int, "%d\n")
-fw_attr(host, struct hpsb_host, in_bus_reset, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_root, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_cycmst, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_irm, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_busmgr, int, "%d\n")
-
-static struct device_attribute *const fw_host_attrs[] = {
-       &dev_attr_host_node_count,
-       &dev_attr_host_selfid_count,
-       &dev_attr_host_nodes_active,
-       &dev_attr_host_in_bus_reset,
-       &dev_attr_host_is_root,
-       &dev_attr_host_is_cycmst,
-       &dev_attr_host_is_irm,
-       &dev_attr_host_is_busmgr,
-};
-
-
-static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf)
-{
-       struct hpsb_protocol_driver *driver;
-       const struct ieee1394_device_id *id;
-       int length = 0;
-       char *scratch = buf;
-
-       driver = container_of(drv, struct hpsb_protocol_driver, driver);
-       id = driver->id_table;
-       if (!id)
-               return 0;
-
-       for (; id->match_flags != 0; id++) {
-               int need_coma = 0;
-
-               if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) {
-                       length += sprintf(scratch, "vendor_id=0x%06x", id->vendor_id);
-                       scratch = buf + length;
-                       need_coma++;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_MODEL_ID) {
-                       length += sprintf(scratch, "%smodel_id=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->model_id);
-                       scratch = buf + length;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) {
-                       length += sprintf(scratch, "%sspecifier_id=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->specifier_id);
-                       scratch = buf + length;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_VERSION) {
-                       length += sprintf(scratch, "%sversion=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->version);
-                       scratch = buf + length;
-               }
-
-               if (need_coma) {
-                       *scratch++ = '\n';
-                       length++;
-               }
-       }
-
-       return length;
-}
-static DRIVER_ATTR(device_ids,S_IRUGO,fw_show_drv_device_ids,NULL);
-
-
-fw_drv_attr(name, const char *, "%s\n")
-
-static struct driver_attribute *const fw_drv_attrs[] = {
-       &driver_attr_drv_name,
-       &driver_attr_device_ids,
-};
-
-
-static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
-{
-       struct device_driver *drv = &driver->driver;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
-               if (driver_create_file(drv, fw_drv_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static void nodemgr_remove_drv_files(struct hpsb_protocol_driver *driver)
-{
-       struct device_driver *drv = &driver->driver;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
-               driver_remove_file(drv, fw_drv_attrs[i]);
-}
-
-
-static void nodemgr_create_ne_dev_files(struct node_entry *ne)
-{
-       struct device *dev = &ne->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
-               if (device_create_file(dev, fw_ne_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static void nodemgr_create_host_dev_files(struct hpsb_host *host)
-{
-       struct device *dev = &host->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++)
-               if (device_create_file(dev, fw_host_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
-                                              nodeid_t nodeid);
-
-static void nodemgr_update_host_dev_links(struct hpsb_host *host)
-{
-       struct device *dev = &host->device;
-       struct node_entry *ne;
-
-       sysfs_remove_link(&dev->kobj, "irm_id");
-       sysfs_remove_link(&dev->kobj, "busmgr_id");
-       sysfs_remove_link(&dev->kobj, "host_id");
-
-       if ((ne = find_entry_by_nodeid(host, host->irm_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"))
-               goto fail;
-       if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"))
-               goto fail;
-       if ((ne = find_entry_by_nodeid(host, host->node_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"))
-               goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to update sysfs attributes for host %d", host->id);
-}
-
-static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
-{
-       struct device *dev = &ud->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
-               if (device_create_file(dev, fw_ud_attrs[i]))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
-               if (device_create_file(dev, &dev_attr_ud_specifier_id))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_VERSION)
-               if (device_create_file(dev, &dev_attr_ud_version))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
-               if (device_create_file(dev, &dev_attr_ud_vendor_id))
-                       goto fail;
-               if (ud->vendor_name_kv &&
-                   device_create_file(dev, &dev_attr_ud_vendor_name_kv))
-                       goto fail;
-       }
-       if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
-               if (device_create_file(dev, &dev_attr_ud_model_id))
-                       goto fail;
-               if (ud->model_name_kv &&
-                   device_create_file(dev, &dev_attr_ud_model_name_kv))
-                       goto fail;
-       }
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
-{
-       struct hpsb_protocol_driver *driver;
-       struct unit_directory *ud;
-       const struct ieee1394_device_id *id;
-
-       /* We only match unit directories */
-       if (dev->platform_data != &nodemgr_ud_platform_data)
-               return 0;
-
-       ud = container_of(dev, struct unit_directory, device);
-       if (ud->ne->in_limbo || ud->ignore_driver)
-               return 0;
-
-       /* We only match drivers of type hpsb_protocol_driver */
-       if (drv == &nodemgr_mid_layer_driver)
-               return 0;
-
-       driver = container_of(drv, struct hpsb_protocol_driver, driver);
-       id = driver->id_table;
-       if (!id)
-               return 0;
-
-       for (; id->match_flags != 0; id++) {
-               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
-                   id->vendor_id != ud->vendor_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
-                   id->model_id != ud->model_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
-                   id->specifier_id != ud->specifier_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
-                   id->version != ud->version)
-                       continue;
-
-               return 1;
-       }
-
-       return 0;
-}
-
-
-static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
-
-static int match_ne(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct node_entry *ne = data;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       return ud->ne == ne;
-}
-
-static void nodemgr_remove_uds(struct node_entry *ne)
-{
-       struct device *dev;
-       struct unit_directory *ud;
-
-       /* Use class_find device to iterate the devices. Since this code
-        * may be called from other contexts besides the knodemgrds,
-        * protect it by nodemgr_serialize_remove_uds.
-        */
-       mutex_lock(&nodemgr_serialize_remove_uds);
-       for (;;) {
-               dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne);
-               if (!dev)
-                       break;
-               ud = container_of(dev, struct unit_directory, unit_dev);
-               put_device(dev);
-               device_unregister(&ud->unit_dev);
-               device_unregister(&ud->device);
-       }
-       mutex_unlock(&nodemgr_serialize_remove_uds);
-}
-
-
-static void nodemgr_remove_ne(struct node_entry *ne)
-{
-       struct device *dev;
-
-       dev = get_device(&ne->device);
-       if (!dev)
-               return;
-
-       HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-       nodemgr_remove_uds(ne);
-
-       device_unregister(&ne->node_dev);
-       device_unregister(dev);
-
-       put_device(dev);
-}
-
-static int remove_host_dev(struct device *dev, void *data)
-{
-       if (dev->bus == &ieee1394_bus_type)
-               nodemgr_remove_ne(container_of(dev, struct node_entry,
-                                 device));
-       return 0;
-}
-
-static void nodemgr_remove_host_dev(struct device *dev)
-{
-       device_for_each_child(dev, NULL, remove_host_dev);
-       sysfs_remove_link(&dev->kobj, "irm_id");
-       sysfs_remove_link(&dev->kobj, "busmgr_id");
-       sysfs_remove_link(&dev->kobj, "host_id");
-}
-
-
-static void nodemgr_update_bus_options(struct node_entry *ne)
-{
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-       static const u16 mr[] = { 4, 64, 1024, 0};
-#endif
-       quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]);
-
-       ne->busopt.irmc         = (busoptions >> 31) & 1;
-       ne->busopt.cmc          = (busoptions >> 30) & 1;
-       ne->busopt.isc          = (busoptions >> 29) & 1;
-       ne->busopt.bmc          = (busoptions >> 28) & 1;
-       ne->busopt.pmc          = (busoptions >> 27) & 1;
-       ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
-       ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
-       ne->busopt.max_rom      = (busoptions >> 8) & 0x3;
-       ne->busopt.generation   = (busoptions >> 4) & 0xf;
-       ne->busopt.lnkspd       = busoptions & 0x7;
-
-       HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
-                    "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d",
-                    busoptions, ne->busopt.irmc, ne->busopt.cmc,
-                    ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
-                    ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
-                    mr[ne->busopt.max_rom],
-                    ne->busopt.generation, ne->busopt.lnkspd);
-}
-
-
-static struct node_entry *nodemgr_create_node(octlet_t guid,
-                               struct csr1212_csr *csr, struct hpsb_host *host,
-                               nodeid_t nodeid, unsigned int generation)
-{
-       struct node_entry *ne;
-
-       ne = kzalloc(sizeof(*ne), GFP_KERNEL);
-       if (!ne)
-               goto fail_alloc;
-
-       ne->host = host;
-       ne->nodeid = nodeid;
-       ne->generation = generation;
-       ne->needs_probe = true;
-
-       ne->guid = guid;
-       ne->guid_vendor_id = (guid >> 40) & 0xffffff;
-       ne->csr = csr;
-
-       memcpy(&ne->device, &nodemgr_dev_template_ne,
-              sizeof(ne->device));
-       ne->device.parent = &host->device;
-       dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid));
-
-       ne->node_dev.parent = &ne->device;
-       ne->node_dev.class = &nodemgr_ne_class;
-       dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid));
-
-       if (device_register(&ne->device))
-               goto fail_devreg;
-       if (device_register(&ne->node_dev))
-               goto fail_classdevreg;
-       get_device(&ne->device);
-
-       nodemgr_create_ne_dev_files(ne);
-
-       nodemgr_update_bus_options(ne);
-
-       HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  (host->node_id == nodeid) ? "Host" : "Node",
-                  NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
-
-       return ne;
-
-fail_classdevreg:
-       device_unregister(&ne->device);
-fail_devreg:
-       kfree(ne);
-fail_alloc:
-       HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
-
-       return NULL;
-}
-
-static int match_ne_guid(struct device *dev, void *data)
-{
-       struct node_entry *ne;
-       u64 *guid = data;
-
-       ne = container_of(dev, struct node_entry, node_dev);
-       return ne->guid == *guid;
-}
-
-static struct node_entry *find_entry_by_guid(u64 guid)
-{
-       struct device *dev;
-       struct node_entry *ne;
-
-       dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid);
-       if (!dev)
-               return NULL;
-       ne = container_of(dev, struct node_entry, node_dev);
-       put_device(dev);
-
-       return ne;
-}
-
-struct match_nodeid_parameter {
-       struct hpsb_host *host;
-       nodeid_t nodeid;
-};
-
-static int match_ne_nodeid(struct device *dev, void *data)
-{
-       int found = 0;
-       struct node_entry *ne;
-       struct match_nodeid_parameter *p = data;
-
-       if (!dev)
-               goto ret;
-       ne = container_of(dev, struct node_entry, node_dev);
-       if (ne->host == p->host && ne->nodeid == p->nodeid)
-               found = 1;
-ret:
-       return found;
-}
-
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
-                                              nodeid_t nodeid)
-{
-       struct device *dev;
-       struct node_entry *ne;
-       struct match_nodeid_parameter p;
-
-       p.host = host;
-       p.nodeid = nodeid;
-
-       dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid);
-       if (!dev)
-               return NULL;
-       ne = container_of(dev, struct node_entry, node_dev);
-       put_device(dev);
-
-       return ne;
-}
-
-
-static void nodemgr_register_device(struct node_entry *ne, 
-       struct unit_directory *ud, struct device *parent)
-{
-       memcpy(&ud->device, &nodemgr_dev_template_ud,
-              sizeof(ud->device));
-
-       ud->device.parent = parent;
-
-       dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id);
-
-       ud->unit_dev.parent = &ud->device;
-       ud->unit_dev.class = &nodemgr_ud_class;
-       dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id);
-
-       if (device_register(&ud->device))
-               goto fail_devreg;
-       if (device_register(&ud->unit_dev))
-               goto fail_classdevreg;
-       get_device(&ud->device);
-
-       nodemgr_create_ud_dev_files(ud);
-
-       return;
-
-fail_classdevreg:
-       device_unregister(&ud->device);
-fail_devreg:
-       HPSB_ERR("Failed to create unit %s", dev_name(&ud->device));
-}      
-
-
-/* This implementation currently only scans the config rom and its
- * immediate unit directories looking for software_id and
- * software_version entries, in order to get driver autoloading working. */
-static struct unit_directory *nodemgr_process_unit_directory
-       (struct node_entry *ne, struct csr1212_keyval *ud_kv,
-        unsigned int *id, struct unit_directory *parent)
-{
-       struct unit_directory *ud;
-       struct unit_directory *ud_child = NULL;
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *kv;
-       u8 last_key_id = 0;
-
-       ud = kzalloc(sizeof(*ud), GFP_KERNEL);
-       if (!ud)
-               goto unit_directory_error;
-
-       ud->ne = ne;
-       ud->ignore_driver = ignore_drivers;
-       ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE;
-       ud->directory_id = ud->address & 0xffffff;
-       ud->ud_kv = ud_kv;
-       ud->id = (*id)++;
-
-       /* inherit vendor_id from root directory if none exists in unit dir */
-       ud->vendor_id = ne->vendor_id;
-
-       csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_VENDOR:
-                       if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-                               ud->vendor_id = kv->value.immediate;
-                               ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
-                       }
-                       break;
-
-               case CSR1212_KV_ID_MODEL:
-                       ud->model_id = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_MODEL_ID;
-                       break;
-
-               case CSR1212_KV_ID_SPECIFIER_ID:
-                       ud->specifier_id = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
-                       break;
-
-               case CSR1212_KV_ID_VERSION:
-                       ud->version = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_VERSION;
-                       break;
-
-               case CSR1212_KV_ID_DESCRIPTOR:
-                       if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
-                           CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
-                           CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
-                               switch (last_key_id) {
-                               case CSR1212_KV_ID_VENDOR:
-                                       csr1212_keep_keyval(kv);
-                                       ud->vendor_name_kv = kv;
-                                       break;
-
-                               case CSR1212_KV_ID_MODEL:
-                                       csr1212_keep_keyval(kv);
-                                       ud->model_name_kv = kv;
-                                       break;
-
-                               }
-                       } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
-                       break;
-
-               case CSR1212_KV_ID_DEPENDENT_INFO:
-                       /* Logical Unit Number */
-                       if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-                               if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
-                                       ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL);
-                                       if (!ud_child)
-                                               goto unit_directory_error;
-                                       nodemgr_register_device(ne, ud_child, &ne->device);
-                                       ud_child = NULL;
-                                       
-                                       ud->id = (*id)++;
-                               }
-                               ud->lun = kv->value.immediate;
-                               ud->flags |= UNIT_DIRECTORY_HAS_LUN;
-
-                       /* Logical Unit Directory */
-                       } else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
-                               /* This should really be done in SBP2 as this is
-                                * doing SBP2 specific parsing.
-                                */
-                               
-                               /* first register the parent unit */
-                               ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
-                               if (ud->device.bus != &ieee1394_bus_type)
-                                       nodemgr_register_device(ne, ud, &ne->device);
-                               
-                               /* process the child unit */
-                               ud_child = nodemgr_process_unit_directory(ne, kv, id, ud);
-
-                               if (ud_child == NULL)
-                                       break;
-                               
-                               /* inherit unspecified values, the driver core picks it up */
-                               if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_MODEL_ID;
-                                       ud_child->model_id = ud->model_id;
-                               }
-                               if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
-                                       ud_child->specifier_id = ud->specifier_id;
-                               }
-                               if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_VERSION))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_VERSION;
-                                       ud_child->version = ud->version;
-                               }
-                               
-                               /* register the child unit */
-                               ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
-                               nodemgr_register_device(ne, ud_child, &ud->device);
-                       }
-
-                       break;
-
-               case CSR1212_KV_ID_DIRECTORY_ID:
-                       ud->directory_id = kv->value.immediate;
-                       break;
-
-               default:
-                       break;
-               }
-               last_key_id = kv->key.id;
-       }
-       
-       /* do not process child units here and only if not already registered */
-       if (!parent && ud->device.bus != &ieee1394_bus_type)
-               nodemgr_register_device(ne, ud, &ne->device);
-
-       return ud;
-
-unit_directory_error:
-       kfree(ud);
-       return NULL;
-}
-
-
-static void nodemgr_process_root_directory(struct node_entry *ne)
-{
-       unsigned int ud_id = 0;
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *kv, *vendor_name_kv = NULL;
-       u8 last_key_id = 0;
-
-       ne->needs_probe = false;
-
-       csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_VENDOR:
-                       ne->vendor_id = kv->value.immediate;
-                       break;
-
-               case CSR1212_KV_ID_NODE_CAPABILITIES:
-                       ne->capabilities = kv->value.immediate;
-                       break;
-
-               case CSR1212_KV_ID_UNIT:
-                       nodemgr_process_unit_directory(ne, kv, &ud_id, NULL);
-                       break;
-
-               case CSR1212_KV_ID_DESCRIPTOR:
-                       if (last_key_id == CSR1212_KV_ID_VENDOR) {
-                               if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
-                                   CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
-                                   CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
-                                       csr1212_keep_keyval(kv);
-                                       vendor_name_kv = kv;
-                               }
-                       }
-                       break;
-               }
-               last_key_id = kv->key.id;
-       }
-
-       if (ne->vendor_name_kv) {
-               kv = ne->vendor_name_kv;
-               ne->vendor_name_kv = vendor_name_kv;
-               csr1212_release_keyval(kv);
-       } else if (vendor_name_kv) {
-               ne->vendor_name_kv = vendor_name_kv;
-               if (device_create_file(&ne->device,
-                                      &dev_attr_ne_vendor_name_kv) != 0)
-                       HPSB_ERR("Failed to add sysfs attribute");
-       }
-}
-
-#ifdef CONFIG_HOTPLUG
-
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct unit_directory *ud;
-       int retval = 0;
-       /* ieee1394:venNmoNspNverN */
-       char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
-
-       if (!dev)
-               return -ENODEV;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-
-       if (ud->ne->in_limbo || ud->ignore_driver)
-               return -ENODEV;
-
-#define PUT_ENVP(fmt,val)                                      \
-do {                                                           \
-       retval = add_uevent_var(env, fmt, val);         \
-       if (retval)                                             \
-               return retval;                                  \
-} while (0)
-
-       PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id);
-       PUT_ENVP("MODEL_ID=%06x", ud->model_id);
-       PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);
-       PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);
-       PUT_ENVP("VERSION=%06x", ud->version);
-       snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
-                       ud->vendor_id,
-                       ud->model_id,
-                       ud->specifier_id,
-                       ud->version);
-       PUT_ENVP("MODALIAS=%s", buf);
-
-#undef PUT_ENVP
-
-       return 0;
-}
-
-#else
-
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       return -ENODEV;
-}
-
-#endif /* CONFIG_HOTPLUG */
-
-
-int __hpsb_register_protocol(struct hpsb_protocol_driver *drv,
-                            struct module *owner)
-{
-       int error;
-
-       drv->driver.bus = &ieee1394_bus_type;
-       drv->driver.owner = owner;
-       drv->driver.name = drv->name;
-
-       /* This will cause a probe for devices */
-       error = driver_register(&drv->driver);
-       if (!error)
-               nodemgr_create_drv_files(drv);
-       return error;
-}
-
-void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
-{
-       nodemgr_remove_drv_files(driver);
-       /* This will subsequently disconnect all devices that our driver
-        * is attached to. */
-       driver_unregister(&driver->driver);
-}
-
-
-/*
- * This function updates nodes that were present on the bus before the
- * reset and still are after the reset.  The nodeid and the config rom
- * may have changed, and the drivers managing this device must be
- * informed that this device just went through a bus reset, to allow
- * the to take whatever actions required.
- */
-static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
-                               nodeid_t nodeid, unsigned int generation)
-{
-       if (ne->nodeid != nodeid) {
-               HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
-                          NODE_BUS_ARGS(ne->host, ne->nodeid),
-                          NODE_BUS_ARGS(ne->host, nodeid));
-               ne->nodeid = nodeid;
-       }
-
-       if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) {
-               kfree(ne->csr->private);
-               csr1212_destroy_csr(ne->csr);
-               ne->csr = csr;
-
-               /* If the node's configrom generation has changed, we
-                * unregister all the unit directories. */
-               nodemgr_remove_uds(ne);
-
-               nodemgr_update_bus_options(ne);
-
-               /* Mark the node as new, so it gets re-probed */
-               ne->needs_probe = true;
-       } else {
-               /* old cache is valid, so update its generation */
-               struct nodemgr_csr_info *ci = ne->csr->private;
-               ci->generation = generation;
-               /* free the partially filled now unneeded new cache */
-               kfree(csr->private);
-               csr1212_destroy_csr(csr);
-       }
-
-       /* Finally, mark the node current */
-       smp_wmb();
-       ne->generation = generation;
-
-       if (ne->in_limbo) {
-               device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-               ne->in_limbo = false;
-
-               HPSB_DEBUG("Node reactivated: "
-                          "ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                          NODE_BUS_ARGS(ne->host, ne->nodeid),
-                          (unsigned long long)ne->guid);
-       }
-}
-
-static void nodemgr_node_scan_one(struct hpsb_host *host,
-                                 nodeid_t nodeid, int generation)
-{
-       struct node_entry *ne;
-       octlet_t guid;
-       struct csr1212_csr *csr;
-       struct nodemgr_csr_info *ci;
-       u8 *speed;
-
-       ci = kmalloc(sizeof(*ci), GFP_KERNEL);
-       kmemcheck_annotate_bitfield(ci, flags);
-       if (!ci)
-               return;
-
-       ci->host = host;
-       ci->nodeid = nodeid;
-       ci->generation = generation;
-
-       /* Prepare for speed probe which occurs when reading the ROM */
-       speed = &(host->speed[NODEID_TO_NODE(nodeid)]);
-       if (*speed > host->csr.lnk_spd)
-               *speed = host->csr.lnk_spd;
-       ci->speed_unverified = *speed > IEEE1394_SPEED_100;
-
-       /* We need to detect when the ConfigROM's generation has changed,
-        * so we only update the node's info when it needs to be.  */
-
-       csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci);
-       if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) {
-               HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT,
-                        NODE_BUS_ARGS(host, nodeid));
-               if (csr)
-                       csr1212_destroy_csr(csr);
-               kfree(ci);
-               return;
-       }
-
-       if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) {
-               /* This isn't a 1394 device, but we let it slide. There
-                * was a report of a device with broken firmware which
-                * reported '2394' instead of '1394', which is obviously a
-                * mistake. One would hope that a non-1394 device never
-                * gets connected to Firewire bus. If someone does, we
-                * shouldn't be held responsible, so we'll allow it with a
-                * warning.  */
-               HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",
-                         NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]);
-       }
-
-       guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]);
-       ne = find_entry_by_guid(guid);
-
-       if (ne && ne->host != host && ne->in_limbo) {
-               /* Must have moved this device from one host to another */
-               nodemgr_remove_ne(ne);
-               ne = NULL;
-       }
-
-       if (!ne)
-               nodemgr_create_node(guid, csr, host, nodeid, generation);
-       else
-               nodemgr_update_node(ne, csr, nodeid, generation);
-}
-
-
-static void nodemgr_node_scan(struct hpsb_host *host, int generation)
-{
-       int count;
-       struct selfid *sid = (struct selfid *)host->topology_map;
-       nodeid_t nodeid = LOCAL_BUS;
-
-       /* Scan each node on the bus */
-       for (count = host->selfid_count; count; count--, sid++) {
-               if (sid->extended)
-                       continue;
-
-               if (!sid->link_active) {
-                       nodeid++;
-                       continue;
-               }
-               nodemgr_node_scan_one(host, nodeid++, generation);
-       }
-}
-
-static void nodemgr_pause_ne(struct node_entry *ne)
-{
-       HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid),
-                  (unsigned long long)ne->guid);
-
-       ne->in_limbo = true;
-       WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
-}
-
-static int update_pdrv(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct hpsb_protocol_driver *pdrv;
-       struct node_entry *ne = data;
-       int error;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       error = 0;
-                       pdrv = container_of(drv, struct hpsb_protocol_driver,
-                                           driver);
-                       if (pdrv->update) {
-                               device_lock(&ud->device);
-                               error = pdrv->update(ud);
-                               device_unlock(&ud->device);
-                       }
-                       if (error)
-                               device_release_driver(&ud->device);
-                       put_driver(drv);
-               }
-       }
-
-       return 0;
-}
-
-static void nodemgr_update_pdrv(struct node_entry *ne)
-{
-       class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
-}
-
-/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
- * seems like an optional service but in the end it is practically mandatory
- * as a consequence of these clauses.
- *
- * Note that we cannot do a broadcast write to all nodes at once because some
- * pre-1394a devices would hang. */
-static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
-{
-       const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
-       quadlet_t bc_remote, bc_local;
-       int error;
-
-       if (!ne->host->is_irm || ne->generation != generation ||
-           ne->nodeid == ne->host->node_id)
-               return;
-
-       bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
-
-       /* Check if the register is implemented and 1394a compliant. */
-       error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
-                         sizeof(bc_remote));
-       if (!error && bc_remote & cpu_to_be32(0x80000000) &&
-           bc_remote != bc_local)
-               hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
-}
-
-
-static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne,
-                            int generation)
-{
-       struct device *dev;
-
-       if (ne->host != host || ne->in_limbo)
-               return;
-
-       dev = get_device(&ne->device);
-       if (!dev)
-               return;
-
-       nodemgr_irm_write_bc(ne, generation);
-
-       /* If "needs_probe", then this is either a new or changed node we
-        * rescan totally. If the generation matches for an existing node
-        * (one that existed prior to the bus reset) we send update calls
-        * down to the drivers. Otherwise, this is a dead node and we
-        * suspend it. */
-       if (ne->needs_probe)
-               nodemgr_process_root_directory(ne);
-       else if (ne->generation == generation)
-               nodemgr_update_pdrv(ne);
-       else
-               nodemgr_pause_ne(ne);
-
-       put_device(dev);
-}
-
-struct node_probe_parameter {
-       struct hpsb_host *host;
-       int generation;
-       bool probe_now;
-};
-
-static int node_probe(struct device *dev, void *data)
-{
-       struct node_probe_parameter *p = data;
-       struct node_entry *ne;
-
-       if (p->generation != get_hpsb_generation(p->host))
-               return -EAGAIN;
-
-       ne = container_of(dev, struct node_entry, node_dev);
-       if (ne->needs_probe == p->probe_now)
-               nodemgr_probe_ne(p->host, ne, p->generation);
-       return 0;
-}
-
-static int nodemgr_node_probe(struct hpsb_host *host, int generation)
-{
-       struct node_probe_parameter p;
-
-       p.host = host;
-       p.generation = generation;
-       /*
-        * Do some processing of the nodes we've probed. This pulls them
-        * into the sysfs layer if needed, and can result in processing of
-        * unit-directories, or just updating the node and it's
-        * unit-directories.
-        *
-        * Run updates before probes. Usually, updates are time-critical
-        * while probes are time-consuming.
-        *
-        * Meanwhile, another bus reset may have happened. In this case we
-        * skip everything here and let the next bus scan handle it.
-        * Otherwise we may prematurely remove nodes which are still there.
-        */
-       p.probe_now = false;
-       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return 0;
-
-       p.probe_now = true;
-       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return 0;
-       /*
-        * Now let's tell the bus to rescan our devices. This may seem
-        * like overhead, but the driver-model core will only scan a
-        * device for a driver when either the device is added, or when a
-        * new driver is added. A bus reset is a good reason to rescan
-        * devices that were there before.  For example, an sbp2 device
-        * may become available for login, if the host that held it was
-        * just removed.
-        */
-       if (bus_rescan_devices(&ieee1394_bus_type) != 0)
-               HPSB_DEBUG("bus_rescan_devices had an error");
-
-       return 1;
-}
-
-static int remove_nodes_in_limbo(struct device *dev, void *data)
-{
-       struct node_entry *ne;
-
-       if (dev->bus != &ieee1394_bus_type)
-               return 0;
-
-       ne = container_of(dev, struct node_entry, device);
-       if (ne->in_limbo)
-               nodemgr_remove_ne(ne);
-
-       return 0;
-}
-
-static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
-{
-       device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
-}
-
-static int nodemgr_send_resume_packet(struct hpsb_host *host)
-{
-       struct hpsb_packet *packet;
-       int error = -ENOMEM;
-
-       packet = hpsb_make_phypacket(host,
-                       EXTPHYPACKET_TYPE_RESUME |
-                       NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT);
-       if (packet) {
-               packet->no_waiter = 1;
-               packet->generation = get_hpsb_generation(host);
-               error = hpsb_send_packet(packet);
-       }
-       if (error)
-               HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
-                         host->id);
-       return error;
-}
-
-/* Perform a few high-level IRM responsibilities. */
-static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
-{
-       quadlet_t bc;
-
-       /* if irm_id == -1 then there is no IRM on this bus */
-       if (!host->is_irm || host->irm_id == (nodeid_t)-1)
-               return 1;
-
-       /* We are a 1394a-2000 compliant IRM. Set the validity bit. */
-       host->csr.broadcast_channel |= 0x40000000;
-
-       /* If there is no bus manager then we should set the root node's
-        * force_root bit to promote bus stability per the 1394
-        * spec. (8.4.2.6) */
-       if (host->busmgr_id == 0xffff && host->node_count > 1)
-       {
-               u16 root_node = host->node_count - 1;
-
-               /* get cycle master capability flag from root node */
-               if (host->is_cycmst ||
-                   (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host),
-                               (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)),
-                               &bc, sizeof(quadlet_t)) &&
-                    be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT))
-                       hpsb_send_phy_config(host, root_node, -1);
-               else {
-                       HPSB_DEBUG("The root node is not cycle master capable; "
-                                  "selecting a new root node and resetting...");
-
-                       if (cycles >= 5) {
-                               /* Oh screw it! Just leave the bus as it is */
-                               HPSB_DEBUG("Stopping reset loop for IRM sanity");
-                               return 1;
-                       }
-
-                       hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
-                       hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
-
-                       return 0;
-               }
-       }
-
-       /* Some devices suspend their ports while being connected to an inactive
-        * host adapter, i.e. if connected before the low-level driver is
-        * loaded.  They become visible either when physically unplugged and
-        * replugged, or when receiving a resume packet.  Send one once. */
-       if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host))
-               host->resume_packet_sent = 1;
-
-       return 1;
-}
-
-/* We need to ensure that if we are not the IRM, that the IRM node is capable of
- * everything we can do, otherwise issue a bus reset and try to become the IRM
- * ourselves. */
-static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
-{
-       quadlet_t bc;
-       int status;
-
-       if (hpsb_disable_irm || host->is_irm)
-               return 1;
-
-       status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
-                          get_hpsb_generation(host),
-                          (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
-                          &bc, sizeof(quadlet_t));
-
-       if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
-               /* The current irm node does not have a valid BROADCAST_CHANNEL
-                * register and we do, so reset the bus with force_root set */
-               HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting...");
-
-               if (cycles >= 5) {
-                       /* Oh screw it! Just leave the bus as it is */
-                       HPSB_DEBUG("Stopping reset loop for IRM sanity");
-                       return 1;
-               }
-
-               hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
-               hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
-
-               return 0;
-       }
-
-       return 1;
-}
-
-static int nodemgr_host_thread(void *data)
-{
-       struct hpsb_host *host = data;
-       unsigned int g, generation = 0;
-       int i, reset_cycles = 0;
-
-       set_freezable();
-       /* Setup our device-model entries */
-       nodemgr_create_host_dev_files(host);
-
-       for (;;) {
-               /* Sleep until next bus reset */
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (get_hpsb_generation(host) == generation &&
-                   !kthread_should_stop())
-                       schedule();
-               __set_current_state(TASK_RUNNING);
-
-               /* Thread may have been woken up to freeze or to exit */
-               if (try_to_freeze())
-                       continue;
-               if (kthread_should_stop())
-                       goto exit;
-
-               /* Pause for 1/4 second in 1/16 second intervals,
-                * to make sure things settle down. */
-               g = get_hpsb_generation(host);
-               for (i = 0; i < 4 ; i++) {
-                       msleep_interruptible(63);
-                       try_to_freeze();
-                       if (kthread_should_stop())
-                               goto exit;
-
-                       /* Now get the generation in which the node ID's we collect
-                        * are valid.  During the bus scan we will use this generation
-                        * for the read transactions, so that if another reset occurs
-                        * during the scan the transactions will fail instead of
-                        * returning bogus data. */
-                       generation = get_hpsb_generation(host);
-
-                       /* If we get a reset before we are done waiting, then
-                        * start the waiting over again */
-                       if (generation != g)
-                               g = generation, i = 0;
-               }
-
-               if (!nodemgr_check_irm_capability(host, reset_cycles) ||
-                   !nodemgr_do_irm_duties(host, reset_cycles)) {
-                       reset_cycles++;
-                       continue;
-               }
-               reset_cycles = 0;
-
-               /* Scan our nodes to get the bus options and create node
-                * entries. This does not do the sysfs stuff, since that
-                * would trigger uevents and such, which is a bad idea at
-                * this point. */
-               nodemgr_node_scan(host, generation);
-
-               /* This actually does the full probe, with sysfs
-                * registration. */
-               if (!nodemgr_node_probe(host, generation))
-                       continue;
-
-               /* Update some of our sysfs symlinks */
-               nodemgr_update_host_dev_links(host);
-
-               /* Sleep 3 seconds */
-               for (i = 3000/200; i; i--) {
-                       msleep_interruptible(200);
-                       try_to_freeze();
-                       if (kthread_should_stop())
-                               goto exit;
-
-                       if (generation != get_hpsb_generation(host))
-                               break;
-               }
-               /* Remove nodes which are gone, unless a bus reset happened */
-               if (!i)
-                       nodemgr_remove_nodes_in_limbo(host);
-       }
-exit:
-       HPSB_VERBOSE("NodeMgr: Exiting thread");
-       return 0;
-}
-
-struct per_host_parameter {
-       void *data;
-       int (*cb)(struct hpsb_host *, void *);
-};
-
-static int per_host(struct device *dev, void *data)
-{
-       struct hpsb_host *host;
-       struct per_host_parameter *p = data;
-
-       host = container_of(dev, struct hpsb_host, host_dev);
-       return p->cb(host, p->data);
-}
-
-/**
- * nodemgr_for_each_host - call a function for each IEEE 1394 host
- * @data: an address to supply to the callback
- * @cb: function to call for each host
- *
- * Iterate the hosts, calling a given function with supplied data for each host.
- * If the callback fails on a host, i.e. if it returns a non-zero value, the
- * iteration is stopped.
- *
- * Return value: 0 on success, non-zero on failure (same as returned by last run
- * of the callback).
- */
-int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
-{
-       struct per_host_parameter p;
-
-       p.cb = cb;
-       p.data = data;
-       return class_for_each_device(&hpsb_host_class, NULL, &p, per_host);
-}
-
-/* The following two convenience functions use a struct node_entry
- * for addressing a node on the bus.  They are intended for use by any
- * process context, not just the nodemgr thread, so we need to be a
- * little careful when reading out the node ID and generation.  The
- * thing that can go wrong is that we get the node ID, then a bus
- * reset occurs, and then we read the generation.  The node ID is
- * possibly invalid, but the generation is current, and we end up
- * sending a packet to a the wrong node.
- *
- * The solution is to make sure we read the generation first, so that
- * if a reset occurs in the process, we end up with a stale generation
- * and the transactions will fail instead of silently using wrong node
- * ID's.
- */
-
-/**
- * hpsb_node_fill_packet - fill some destination information into a packet
- * @ne: destination node
- * @packet: packet to fill in
- *
- * This will fill in the given, pre-initialised hpsb_packet with the current
- * information from the node entry (host, node ID, bus generation number).
- */
-void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
-{
-       packet->host = ne->host;
-       packet->generation = ne->generation;
-       smp_rmb();
-       packet->node_id = ne->nodeid;
-}
-
-int hpsb_node_write(struct node_entry *ne, u64 addr,
-                   quadlet_t *buffer, size_t length)
-{
-       unsigned int generation = ne->generation;
-
-       smp_rmb();
-       return hpsb_write(ne->host, ne->nodeid, generation,
-                         addr, buffer, length);
-}
-
-static void nodemgr_add_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-
-       hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi));
-       if (!hi) {
-               HPSB_ERR("NodeMgr: out of memory in add host");
-               return;
-       }
-       hi->host = host;
-       hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d",
-                                host->id);
-       if (IS_ERR(hi->thread)) {
-               HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
-               hpsb_destroy_hostinfo(&nodemgr_highlevel, host);
-       }
-}
-
-static void nodemgr_host_reset(struct hpsb_host *host)
-{
-       struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
-
-       if (hi) {
-               HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id);
-               wake_up_process(hi->thread);
-       }
-}
-
-static void nodemgr_remove_host(struct hpsb_host *host)
-{
-       struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
-
-       if (hi) {
-               kthread_stop(hi->thread);
-               nodemgr_remove_host_dev(&host->device);
-       }
-}
-
-static struct hpsb_highlevel nodemgr_highlevel = {
-       .name =         "Node manager",
-       .add_host =     nodemgr_add_host,
-       .host_reset =   nodemgr_host_reset,
-       .remove_host =  nodemgr_remove_host,
-};
-
-int init_ieee1394_nodemgr(void)
-{
-       int error;
-
-       error = class_register(&nodemgr_ne_class);
-       if (error)
-               goto fail_ne;
-       error = class_register(&nodemgr_ud_class);
-       if (error)
-               goto fail_ud;
-       error = driver_register(&nodemgr_mid_layer_driver);
-       if (error)
-               goto fail_ml;
-       /* This driver is not used if nodemgr is off (disable_nodemgr=1). */
-       nodemgr_dev_template_host.driver = &nodemgr_mid_layer_driver;
-
-       hpsb_register_highlevel(&nodemgr_highlevel);
-       return 0;
-
-fail_ml:
-       class_unregister(&nodemgr_ud_class);
-fail_ud:
-       class_unregister(&nodemgr_ne_class);
-fail_ne:
-       return error;
-}
-
-void cleanup_ieee1394_nodemgr(void)
-{
-       hpsb_unregister_highlevel(&nodemgr_highlevel);
-       driver_unregister(&nodemgr_mid_layer_driver);
-       class_unregister(&nodemgr_ud_class);
-       class_unregister(&nodemgr_ne_class);
-}
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
deleted file mode 100644 (file)
index 749b271..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2000  Andreas E. Bombe
- *               2001  Ben Collins <bcollins@debian.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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _IEEE1394_NODEMGR_H
-#define _IEEE1394_NODEMGR_H
-
-#include <linux/device.h>
-#include <asm/system.h>
-#include <asm/types.h>
-
-#include "ieee1394_core.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-
-struct csr1212_csr;
-struct csr1212_keyval;
-struct hpsb_host;
-struct ieee1394_device_id;
-
-/* This is the start of a Node entry structure. It should be a stable API
- * for which to gather info from the Node Manager about devices attached
- * to the bus.  */
-struct bus_options {
-       u8      irmc;           /* Iso Resource Manager Capable */
-       u8      cmc;            /* Cycle Master Capable */
-       u8      isc;            /* Iso Capable */
-       u8      bmc;            /* Bus Master Capable */
-       u8      pmc;            /* Power Manager Capable (PNP spec) */
-       u8      cyc_clk_acc;    /* Cycle clock accuracy */
-       u8      max_rom;        /* Maximum block read supported in the CSR */
-       u8      generation;     /* Incremented when configrom changes */
-       u8      lnkspd;         /* Link speed */
-       u16     max_rec;        /* Maximum packet size node can receive */
-};
-
-#define UNIT_DIRECTORY_VENDOR_ID               0x01
-#define UNIT_DIRECTORY_MODEL_ID                        0x02
-#define UNIT_DIRECTORY_SPECIFIER_ID            0x04
-#define UNIT_DIRECTORY_VERSION                 0x08
-#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY       0x10
-#define UNIT_DIRECTORY_LUN_DIRECTORY           0x20
-#define UNIT_DIRECTORY_HAS_LUN                 0x40
-
-/*
- * A unit directory corresponds to a protocol supported by the
- * node. If a node supports eg. IP/1394 and AV/C, its config rom has a
- * unit directory for each of these protocols.
- */
-struct unit_directory {
-       struct node_entry *ne;  /* The node which this directory belongs to */
-       octlet_t address;       /* Address of the unit directory on the node */
-       u8 flags;               /* Indicates which entries were read */
-
-       quadlet_t vendor_id;
-       struct csr1212_keyval *vendor_name_kv;
-
-       quadlet_t model_id;
-       struct csr1212_keyval *model_name_kv;
-       quadlet_t specifier_id;
-       quadlet_t version;
-       quadlet_t directory_id;
-
-       unsigned int id;
-
-       int ignore_driver;
-
-       int length;             /* Number of quadlets */
-
-       struct device device;
-       struct device unit_dev;
-
-       struct csr1212_keyval *ud_kv;
-       u32 lun;                /* logical unit number immediate value */
-};
-
-struct node_entry {
-       u64 guid;                       /* GUID of this node */
-       u32 guid_vendor_id;             /* Top 24bits of guid */
-
-       struct hpsb_host *host;         /* Host this node is attached to */
-       nodeid_t nodeid;                /* NodeID */
-       struct bus_options busopt;      /* Bus Options */
-       bool needs_probe;
-       unsigned int generation;        /* Synced with hpsb generation */
-
-       /* The following is read from the config rom */
-       u32 vendor_id;
-       struct csr1212_keyval *vendor_name_kv;
-
-       u32 capabilities;
-
-       struct device device;
-       struct device node_dev;
-
-       /* Means this node is not attached anymore */
-       bool in_limbo;
-
-       struct csr1212_csr *csr;
-};
-
-struct hpsb_protocol_driver {
-       /* The name of the driver, e.g. SBP2 or IP1394 */
-       const char *name;
-
-       /*
-        * The device id table describing the protocols and/or devices
-        * supported by this driver.  This is used by the nodemgr to
-        * decide if a driver could support a given node, but the
-        * probe function below can implement further protocol
-        * dependent or vendor dependent checking.
-        */
-       const struct ieee1394_device_id *id_table;
-
-       /*
-        * The update function is called when the node has just
-        * survived a bus reset, i.e. it is still present on the bus.
-        * However, it may be necessary to reestablish the connection
-        * or login into the node again, depending on the protocol. If the
-        * probe fails (returns non-zero), we unbind the driver from this
-        * device.
-        */
-       int (*update)(struct unit_directory *ud);
-
-       /* Our LDM structure */
-       struct device_driver driver;
-};
-
-int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *);
-static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
-{
-       return __hpsb_register_protocol(driver, THIS_MODULE);
-}
-
-void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
-
-static inline int hpsb_node_entry_valid(struct node_entry *ne)
-{
-       return ne->generation == get_hpsb_generation(ne->host);
-}
-void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
-int hpsb_node_write(struct node_entry *ne, u64 addr,
-                   quadlet_t *buffer, size_t length);
-static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
-                                quadlet_t *buffer, size_t length)
-{
-       unsigned int g = ne->generation;
-
-       smp_rmb();
-       return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
-}
-static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
-                                quadlet_t *buffer, quadlet_t arg)
-{
-       unsigned int g = ne->generation;
-
-       smp_rmb();
-       return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
-}
-int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
-
-int init_ieee1394_nodemgr(void);
-void cleanup_ieee1394_nodemgr(void);
-
-/* The template for a host device */
-extern struct device nodemgr_dev_template_host;
-
-/* Bus attributes we export */
-extern struct bus_attribute *const fw_bus_attrs[];
-
-#endif /* _IEEE1394_NODEMGR_H */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
deleted file mode 100644 (file)
index 5081502..0000000
+++ /dev/null
@@ -1,3590 +0,0 @@
-/*
- * ohci1394.c - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Gord Peters <GordPeters@smarttech.com>
- *              2001      Ben Collins <bcollins@debian.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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Things known to be working:
- * . Async Request Transmit
- * . Async Response Receive
- * . Async Request Receive
- * . Async Response Transmit
- * . Iso Receive
- * . DMA mmap for iso receive
- * . Config ROM generation
- *
- * Things implemented, but still in test phase:
- * . Iso Transmit
- * . Async Stream Packets Transmit (Receive done via Iso interface)
- *
- * Things not implemented:
- * . DMA error recovery
- *
- * Known bugs:
- * . devctl BUS_RESET arg confusion (reset type or root holdoff?)
- *   added LONG_RESET_ROOT and SHORT_RESET_ROOT for root holdoff --kk
- */
-
-/*
- * Acknowledgments:
- *
- * Adam J Richter <adam@yggdrasil.com>
- *  . Use of pci_class to find device
- *
- * Emilie Chung        <emilie.chung@axis.com>
- *  . Tip on Async Request Filter
- *
- * Pascal Drolet <pascal.drolet@informission.ca>
- *  . Various tips for optimization and functionnalities
- *
- * Robert Ficklin <rficklin@westengineering.com>
- *  . Loop in irq_handler
- *
- * James Goodwin <jamesg@Filanet.com>
- *  . Various tips on initialization, self-id reception, etc.
- *
- * Albrecht Dress <ad@mpifr-bonn.mpg.de>
- *  . Apple PowerBook detection
- *
- * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
- *  . Reset the board properly before leaving + misc cleanups
- *
- * Leon van Stuivenberg <leonvs@iae.nl>
- *  . Bug fixes
- *
- * Ben Collins <bcollins@debian.org>
- *  . Working big-endian support
- *  . Updated to 2.4.x module scheme (PCI aswell)
- *  . Config ROM generation
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *  . Reworked code for initiating bus resets
- *    (long, short, with or without hold-off)
- *
- * Nandu Santhi <contactnandu@users.sourceforge.net>
- *  . Added support for nVidia nForce2 onboard Firewire chipset
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "dma.h"
-#include "iso.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "ohci1394.h"
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define OHCI1394_DEBUG
-#endif
-
-#ifdef DBGMSG
-#undef DBGMSG
-#endif
-
-#ifdef OHCI1394_DEBUG
-#define DBGMSG(fmt, args...) \
-printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-#else
-#define DBGMSG(fmt, args...) do {} while (0)
-#endif
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) \
-printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
-
-/* print card specific information */
-#define PRINT(level, fmt, args...) \
-printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-
-/* Module Parameters */
-static int phys_dma = 1;
-module_param(phys_dma, int, 0444);
-MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1).");
-
-static void dma_trm_tasklet(unsigned long data);
-static void dma_trm_reset(struct dma_trm_ctx *d);
-
-static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
-                            enum context_type type, int ctx, int num_desc,
-                            int buf_size, int split_buf_size, int context_base);
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
-
-static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
-                            enum context_type type, int ctx, int num_desc,
-                            int context_base);
-
-static void ohci1394_pci_remove(struct pci_dev *pdev);
-
-#ifndef __LITTLE_ENDIAN
-static const size_t hdr_sizes[] = {
-       3,      /* TCODE_WRITEQ */
-       4,      /* TCODE_WRITEB */
-       3,      /* TCODE_WRITE_RESPONSE */
-       0,      /* reserved */
-       3,      /* TCODE_READQ */
-       4,      /* TCODE_READB */
-       3,      /* TCODE_READQ_RESPONSE */
-       4,      /* TCODE_READB_RESPONSE */
-       1,      /* TCODE_CYCLE_START */
-       4,      /* TCODE_LOCK_REQUEST */
-       2,      /* TCODE_ISO_DATA */
-       4,      /* TCODE_LOCK_RESPONSE */
-               /* rest is reserved or link-internal */
-};
-
-static inline void header_le32_to_cpu(quadlet_t *data, unsigned char tcode)
-{
-       size_t size;
-
-       if (unlikely(tcode >= ARRAY_SIZE(hdr_sizes)))
-               return;
-
-       size = hdr_sizes[tcode];
-       while (size--)
-               data[size] = le32_to_cpu(data[size]);
-}
-#else
-#define header_le32_to_cpu(w,x) do {} while (0)
-#endif /* !LITTLE_ENDIAN */
-
-/***********************************
- * IEEE-1394 functionality section *
- ***********************************/
-
-static u8 get_phy_reg(struct ti_ohci *ohci, u8 addr)
-{
-       int i;
-       unsigned long flags;
-       quadlet_t r;
-
-       spin_lock_irqsave (&ohci->phy_reg_lock, flags);
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
-                       break;
-
-               mdelay(1);
-       }
-
-       r = reg_read(ohci, OHCI1394_PhyControl);
-
-       if (i >= OHCI_LOOP_COUNT)
-               PRINT (KERN_ERR, "Get PHY Reg timeout [0x%08x/0x%08x/%d]",
-                      r, r & 0x80000000, i);
-
-       spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
-
-       return (r & 0x00ff0000) >> 16;
-}
-
-static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
-{
-       int i;
-       unsigned long flags;
-       u32 r = 0;
-
-       spin_lock_irqsave (&ohci->phy_reg_lock, flags);
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               r = reg_read(ohci, OHCI1394_PhyControl);
-               if (!(r & 0x00004000))
-                       break;
-
-               mdelay(1);
-       }
-
-       if (i == OHCI_LOOP_COUNT)
-               PRINT (KERN_ERR, "Set PHY Reg timeout [0x%08x/0x%08x/%d]",
-                      r, r & 0x00004000, i);
-
-       spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
-
-       return;
-}
-
-/* Or's our value into the current value */
-static void set_phy_reg_mask(struct ti_ohci *ohci, u8 addr, u8 data)
-{
-       u8 old;
-
-       old = get_phy_reg (ohci, addr);
-       old |= data;
-       set_phy_reg (ohci, addr, old);
-
-       return;
-}
-
-static void handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
-                               int phyid, int isroot)
-{
-       quadlet_t *q = ohci->selfid_buf_cpu;
-       quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount);
-       size_t size;
-       quadlet_t q0, q1;
-
-       /* Check status of self-id reception */
-
-       if (ohci->selfid_swap)
-               q0 = le32_to_cpu(q[0]);
-       else
-               q0 = q[0];
-
-       if ((self_id_count & 0x80000000) ||
-           ((self_id_count & 0x00FF0000) != (q0 & 0x00FF0000))) {
-               PRINT(KERN_ERR,
-                     "Error in reception of SelfID packets [0x%08x/0x%08x] (count: %d)",
-                     self_id_count, q0, ohci->self_id_errors);
-
-               /* Tip by James Goodwin <jamesg@Filanet.com>:
-                * We had an error, generate another bus reset in response.  */
-               if (ohci->self_id_errors<OHCI1394_MAX_SELF_ID_ERRORS) {
-                       set_phy_reg_mask (ohci, 1, 0x40);
-                       ohci->self_id_errors++;
-               } else {
-                       PRINT(KERN_ERR,
-                             "Too many errors on SelfID error reception, giving up!");
-               }
-               return;
-       }
-
-       /* SelfID Ok, reset error counter. */
-       ohci->self_id_errors = 0;
-
-       size = ((self_id_count & 0x00001FFC) >> 2) - 1;
-       q++;
-
-       while (size > 0) {
-               if (ohci->selfid_swap) {
-                       q0 = le32_to_cpu(q[0]);
-                       q1 = le32_to_cpu(q[1]);
-               } else {
-                       q0 = q[0];
-                       q1 = q[1];
-               }
-
-               if (q0 == ~q1) {
-                       DBGMSG ("SelfID packet 0x%x received", q0);
-                       hpsb_selfid_received(host, cpu_to_be32(q0));
-                       if (((q0 & 0x3f000000) >> 24) == phyid)
-                               DBGMSG ("SelfID for this node is 0x%08x", q0);
-               } else {
-                       PRINT(KERN_ERR,
-                             "SelfID is inconsistent [0x%08x/0x%08x]", q0, q1);
-               }
-               q += 2;
-               size -= 2;
-       }
-
-       DBGMSG("SelfID complete");
-
-       return;
-}
-
-static void ohci_soft_reset(struct ti_ohci *ohci) {
-       int i;
-
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (!(reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset))
-                       break;
-               mdelay(1);
-       }
-       DBGMSG ("Soft reset finished");
-}
-
-
-/* Generate the dma receive prgs and start the context */
-static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d, int generate_irq)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       int i;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0; i<d->num_desc; i++) {
-               u32 c;
-
-               c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH;
-               if (generate_irq)
-                       c |= DMA_CTL_IRQ;
-
-               d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size);
-
-               /* End of descriptor list? */
-               if (i + 1 < d->num_desc) {
-                       d->prg_cpu[i]->branchAddress =
-                               cpu_to_le32((d->prg_bus[i+1] & 0xfffffff0) | 0x1);
-               } else {
-                       d->prg_cpu[i]->branchAddress =
-                               cpu_to_le32((d->prg_bus[0] & 0xfffffff0));
-               }
-
-               d->prg_cpu[i]->address = cpu_to_le32(d->buf_bus[i]);
-               d->prg_cpu[i]->status = cpu_to_le32(d->buf_size);
-       }
-
-        d->buf_ind = 0;
-        d->buf_offset = 0;
-
-       if (d->type == DMA_CTX_ISO) {
-               /* Clear contextControl */
-               reg_write(ohci, d->ctrlClear, 0xffffffff);
-
-               /* Set bufferFill, isochHeader, multichannel for IR context */
-               reg_write(ohci, d->ctrlSet, 0xd0000000);
-
-               /* Set the context match register to match on all tags */
-               reg_write(ohci, d->ctxtMatch, 0xf0000000);
-
-               /* Clear the multi channel mask high and low registers */
-               reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
-
-               /* Set up isoRecvIntMask to generate interrupts */
-               reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx);
-       }
-
-       /* Tell the controller where the first AR program is */
-       reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1);
-
-       /* Run context */
-       reg_write(ohci, d->ctrlSet, 0x00008000);
-
-       DBGMSG("Receive DMA ctx=%d initialized", d->ctx);
-}
-
-/* Initialize the dma transmit context */
-static void initialize_dma_trm_ctx(struct dma_trm_ctx *d)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-
-       /* Stop the context */
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-        d->prg_ind = 0;
-       d->sent_ind = 0;
-       d->free_prgs = d->num_desc;
-        d->branchAddrPtr = NULL;
-       INIT_LIST_HEAD(&d->fifo_list);
-       INIT_LIST_HEAD(&d->pending_list);
-
-       if (d->type == DMA_CTX_ISO) {
-               /* enable interrupts */
-               reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx);
-       }
-
-       DBGMSG("Transmit DMA ctx=%d initialized", d->ctx);
-}
-
-/* Count the number of available iso contexts */
-static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
-{
-       u32 tmp;
-
-       reg_write(ohci, reg, 0xffffffff);
-       tmp = reg_read(ohci, reg);
-
-       DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp);
-
-       /* Count the number of contexts */
-       return hweight32(tmp);
-}
-
-/* Global initialization */
-static void ohci_initialize(struct ti_ohci *ohci)
-{
-       quadlet_t buf;
-       int num_ports, i;
-
-       spin_lock_init(&ohci->phy_reg_lock);
-
-       /* Put some defaults to these undefined bus options */
-       buf = reg_read(ohci, OHCI1394_BusOptions);
-       buf |=  0x60000000; /* Enable CMC and ISC */
-       if (hpsb_disable_irm)
-               buf &= ~0x80000000;
-       else
-               buf |=  0x80000000; /* Enable IRMC */
-       buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
-       buf &= ~0x18000000; /* Disable PMC and BMC */
-       reg_write(ohci, OHCI1394_BusOptions, buf);
-
-       /* Set the bus number */
-       reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
-
-       /* Enable posted writes */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable);
-
-       /* Clear link control register */
-       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-
-       /* Enable cycle timer and cycle master and set the IRM
-        * contender bit in our self ID packets if appropriate. */
-       reg_write(ohci, OHCI1394_LinkControlSet,
-                 OHCI1394_LinkControl_CycleTimerEnable |
-                 OHCI1394_LinkControl_CycleMaster);
-       i = get_phy_reg(ohci, 4) | PHY_04_LCTRL;
-       if (hpsb_disable_irm)
-               i &= ~PHY_04_CONTENDER;
-       else
-               i |= PHY_04_CONTENDER;
-       set_phy_reg(ohci, 4, i);
-
-       /* Set up self-id dma buffer */
-       reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
-
-       /* enable self-id */
-       reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID);
-
-       /* Set the Config ROM mapping register */
-       reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
-
-       /* Now get our max packet size */
-       ohci->max_packet_size =
-               1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-               
-       /* Clear the interrupt mask */
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-
-       /* Clear the interrupt mask */
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-
-       /* Initialize AR dma */
-       initialize_dma_rcv_ctx(&ohci->ar_req_context, 0);
-       initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0);
-
-       /* Initialize AT dma */
-       initialize_dma_trm_ctx(&ohci->at_req_context);
-       initialize_dma_trm_ctx(&ohci->at_resp_context);
-       
-       /* Accept AR requests from all nodes */
-       reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
-
-       /* Set the address range of the physical response unit.
-        * Most controllers do not implement it as a writable register though.
-        * They will keep a hardwired offset of 0x00010000 and show 0x0 as
-        * register content.
-        * To actually enable physical responses is the job of our interrupt
-        * handler which programs the physical request filter. */
-       reg_write(ohci, OHCI1394_PhyUpperBound,
-                 OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16);
-
-       DBGMSG("physUpperBoundOffset=%08x",
-              reg_read(ohci, OHCI1394_PhyUpperBound));
-
-       /* Specify AT retries */
-       reg_write(ohci, OHCI1394_ATRetries,
-                 OHCI1394_MAX_AT_REQ_RETRIES |
-                 (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
-                 (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
-
-       /* We don't want hardware swapping */
-       reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
-
-       /* Enable interrupts */
-       reg_write(ohci, OHCI1394_IntMaskSet,
-                 OHCI1394_unrecoverableError |
-                 OHCI1394_masterIntEnable |
-                 OHCI1394_busReset |
-                 OHCI1394_selfIDComplete |
-                 OHCI1394_RSPkt |
-                 OHCI1394_RQPkt |
-                 OHCI1394_respTxComplete |
-                 OHCI1394_reqTxComplete |
-                 OHCI1394_isochRx |
-                 OHCI1394_isochTx |
-                 OHCI1394_postedWriteErr |
-                 OHCI1394_cycleTooLong |
-                 OHCI1394_cycleInconsistent);
-
-       /* Enable link */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
-
-       buf = reg_read(ohci, OHCI1394_Version);
-       PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d]  "
-             "MMIO=[%llx-%llx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
-             ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
-             ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
-             (unsigned long long)pci_resource_start(ohci->dev, 0),
-             (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
-             ohci->max_packet_size,
-             ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
-
-       /* Check all of our ports to make sure that if anything is
-        * connected, we enable that port. */
-       num_ports = get_phy_reg(ohci, 2) & 0xf;
-       for (i = 0; i < num_ports; i++) {
-               unsigned int status;
-
-               set_phy_reg(ohci, 7, i);
-               status = get_phy_reg(ohci, 8);
-
-               if (status & 0x20)
-                       set_phy_reg(ohci, 8, status & ~1);
-       }
-
-        /* Serial EEPROM Sanity check. */
-        if ((ohci->max_packet_size < 512) ||
-           (ohci->max_packet_size > 4096)) {
-               /* Serial EEPROM contents are suspect, set a sane max packet
-                * size and print the raw contents for bug reports if verbose
-                * debug is enabled. */
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-               int i;
-#endif
-
-               PRINT(KERN_DEBUG, "Serial EEPROM has suspicious values, "
-                      "attempting to set max_packet_size to 512 bytes");
-               reg_write(ohci, OHCI1394_BusOptions,
-                         (reg_read(ohci, OHCI1394_BusOptions) & 0xf007) | 0x8002);
-               ohci->max_packet_size = 512;
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-               PRINT(KERN_DEBUG, "    EEPROM Present: %d",
-                     (reg_read(ohci, OHCI1394_Version) >> 24) & 0x1);
-               reg_write(ohci, OHCI1394_GUID_ROM, 0x80000000);
-
-               for (i = 0;
-                    ((i < 1000) &&
-                     (reg_read(ohci, OHCI1394_GUID_ROM) & 0x80000000)); i++)
-                       udelay(10);
-
-               for (i = 0; i < 0x20; i++) {
-                       reg_write(ohci, OHCI1394_GUID_ROM, 0x02000000);
-                       PRINT(KERN_DEBUG, "    EEPROM %02x: %02x", i,
-                             (reg_read(ohci, OHCI1394_GUID_ROM) >> 16) & 0xff);
-               }
-#endif
-       }
-}
-
-/*
- * Insert a packet in the DMA fifo and generate the DMA prg
- * FIXME: rewrite the program in order to accept packets crossing
- *        page boundaries.
- *        check also that a single dma descriptor doesn't cross a
- *        page boundary.
- */
-static void insert_packet(struct ti_ohci *ohci,
-                         struct dma_trm_ctx *d, struct hpsb_packet *packet)
-{
-       u32 cycleTimer;
-       int idx = d->prg_ind;
-
-       DBGMSG("Inserting packet for node " NODE_BUS_FMT
-              ", tlabel=%d, tcode=0x%x, speed=%d",
-              NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel,
-              packet->tcode, packet->speed_code);
-
-       d->prg_cpu[idx]->begin.address = 0;
-       d->prg_cpu[idx]->begin.branchAddress = 0;
-
-       if (d->type == DMA_CTX_ASYNC_RESP) {
-               /*
-                * For response packets, we need to put a timeout value in
-                * the 16 lower bits of the status... let's try 1 sec timeout
-                */
-               cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-               d->prg_cpu[idx]->begin.status = cpu_to_le32(
-                       (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) |
-                       ((cycleTimer&0x01fff000)>>12));
-
-               DBGMSG("cycleTimer: %08x timeStamp: %08x",
-                      cycleTimer, d->prg_cpu[idx]->begin.status);
-       } else 
-               d->prg_cpu[idx]->begin.status = 0;
-
-        if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) {
-
-                if (packet->type == hpsb_raw) {
-                       d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);
-                        d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]);
-                        d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]);
-                } else {
-                        d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
-                                (packet->header[0] & 0xFFFF);
-
-                       if (packet->tcode == TCODE_ISO_DATA) {
-                               /* Sending an async stream packet */
-                               d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-                       } else {
-                               /* Sending a normal async request or response */
-                               d->prg_cpu[idx]->data[1] =
-                                       (packet->header[1] & 0xFFFF) |
-                                       (packet->header[0] & 0xFFFF0000);
-                               d->prg_cpu[idx]->data[2] = packet->header[2];
-                               d->prg_cpu[idx]->data[3] = packet->header[3];
-                       }
-                       header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
-                }
-
-                if (packet->data_size) { /* block transmit */
-                       if (packet->tcode == TCODE_STREAM_DATA){
-                               d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                                   DMA_CTL_IMMEDIATE | 0x8);
-                       } else {
-                               d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                                   DMA_CTL_IMMEDIATE | 0x10);
-                       }
-                        d->prg_cpu[idx]->end.control =
-                                cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                           DMA_CTL_IRQ |
-                                           DMA_CTL_BRANCH |
-                                           packet->data_size);
-                        /*
-                         * Check that the packet data buffer
-                         * does not cross a page boundary.
-                        *
-                        * XXX Fix this some day. eth1394 seems to trigger
-                        * it, but ignoring it doesn't seem to cause a
-                        * problem.
-                         */
-#if 0
-                        if (cross_bound((unsigned long)packet->data,
-                                        packet->data_size)>0) {
-                                /* FIXME: do something about it */
-                                PRINT(KERN_ERR,
-                                      "%s: packet data addr: %p size %Zd bytes "
-                                     "cross page boundary", __func__,
-                                      packet->data, packet->data_size);
-                        }
-#endif
-                        d->prg_cpu[idx]->end.address = cpu_to_le32(
-                                pci_map_single(ohci->dev, packet->data,
-                                               packet->data_size,
-                                               PCI_DMA_TODEVICE));
-
-                        d->prg_cpu[idx]->end.branchAddress = 0;
-                        d->prg_cpu[idx]->end.status = 0;
-                        if (d->branchAddrPtr)
-                                *(d->branchAddrPtr) =
-                                       cpu_to_le32(d->prg_bus[idx] | 0x3);
-                        d->branchAddrPtr =
-                                &(d->prg_cpu[idx]->end.branchAddress);
-                } else { /* quadlet transmit */
-                        if (packet->type == hpsb_raw)
-                                d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                                   DMA_CTL_IMMEDIATE |
-                                                   DMA_CTL_IRQ |
-                                                   DMA_CTL_BRANCH |
-                                                   (packet->header_size + 4));
-                        else
-                                d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                                   DMA_CTL_IMMEDIATE |
-                                                   DMA_CTL_IRQ |
-                                                   DMA_CTL_BRANCH |
-                                                   packet->header_size);
-
-                        if (d->branchAddrPtr)
-                                *(d->branchAddrPtr) =
-                                       cpu_to_le32(d->prg_bus[idx] | 0x2);
-                        d->branchAddrPtr =
-                                &(d->prg_cpu[idx]->begin.branchAddress);
-                }
-
-        } else { /* iso packet */
-                d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
-                        (packet->header[0] & 0xFFFF);
-                d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-               header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
-
-                d->prg_cpu[idx]->begin.control =
-                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                   DMA_CTL_IMMEDIATE | 0x8);
-                d->prg_cpu[idx]->end.control =
-                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                   DMA_CTL_UPDATE |
-                                   DMA_CTL_IRQ |
-                                   DMA_CTL_BRANCH |
-                                   packet->data_size);
-                d->prg_cpu[idx]->end.address = cpu_to_le32(
-                               pci_map_single(ohci->dev, packet->data,
-                               packet->data_size, PCI_DMA_TODEVICE));
-
-                d->prg_cpu[idx]->end.branchAddress = 0;
-                d->prg_cpu[idx]->end.status = 0;
-                DBGMSG("Iso xmit context info: header[%08x %08x]\n"
-                       "                       begin=%08x %08x %08x %08x\n"
-                       "                             %08x %08x %08x %08x\n"
-                       "                       end  =%08x %08x %08x %08x",
-                       d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1],
-                       d->prg_cpu[idx]->begin.control,
-                       d->prg_cpu[idx]->begin.address,
-                       d->prg_cpu[idx]->begin.branchAddress,
-                       d->prg_cpu[idx]->begin.status,
-                       d->prg_cpu[idx]->data[0],
-                       d->prg_cpu[idx]->data[1],
-                       d->prg_cpu[idx]->data[2],
-                       d->prg_cpu[idx]->data[3],
-                       d->prg_cpu[idx]->end.control,
-                       d->prg_cpu[idx]->end.address,
-                       d->prg_cpu[idx]->end.branchAddress,
-                       d->prg_cpu[idx]->end.status);
-                if (d->branchAddrPtr)
-                       *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3);
-                d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress);
-        }
-       d->free_prgs--;
-
-       /* queue the packet in the appropriate context queue */
-       list_add_tail(&packet->driver_list, &d->fifo_list);
-       d->prg_ind = (d->prg_ind + 1) % d->num_desc;
-}
-
-/*
- * This function fills the FIFO with the (eventual) pending packets
- * and runs or wakes up the DMA prg if necessary.
- *
- * The function MUST be called with the d->lock held.
- */
-static void dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d)
-{
-       struct hpsb_packet *packet, *ptmp;
-       int idx = d->prg_ind;
-       int z = 0;
-
-       /* insert the packets into the dma fifo */
-       list_for_each_entry_safe(packet, ptmp, &d->pending_list, driver_list) {
-               if (!d->free_prgs)
-                       break;
-
-               /* For the first packet only */
-               if (!z)
-                       z = (packet->data_size) ? 3 : 2;
-
-               /* Insert the packet */
-               list_del_init(&packet->driver_list);
-               insert_packet(ohci, d, packet);
-       }
-
-       /* Nothing must have been done, either no free_prgs or no packets */
-       if (z == 0)
-               return;
-
-       /* Is the context running ? (should be unless it is
-          the first packet to be sent in this context) */
-       if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) {
-               u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
-
-               DBGMSG("Starting transmit DMA ctx=%d",d->ctx);
-               reg_write(ohci, d->cmdPtr, d->prg_bus[idx] | z);
-
-               /* Check that the node id is valid, and not 63 */
-               if (!(nodeId & 0x80000000) || (nodeId & 0x3f) == 63)
-                       PRINT(KERN_ERR, "Running dma failed because Node ID is not valid");
-               else
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-       } else {
-               /* Wake up the dma context if necessary */
-               if (!(reg_read(ohci, d->ctrlSet) & 0x400))
-                       DBGMSG("Waking transmit DMA ctx=%d",d->ctx);
-
-               /* do this always, to avoid race condition */
-               reg_write(ohci, d->ctrlSet, 0x1000);
-       }
-
-       return;
-}
-
-/* Transmission of an async or iso packet */
-static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       struct dma_trm_ctx *d;
-       unsigned long flags;
-
-       if (packet->data_size > ohci->max_packet_size) {
-               PRINT(KERN_ERR,
-                     "Transmit packet size %Zd is too big",
-                     packet->data_size);
-               return -EOVERFLOW;
-       }
-
-       if (packet->type == hpsb_raw)
-               d = &ohci->at_req_context;
-       else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
-               d = &ohci->at_resp_context;
-       else
-               d = &ohci->at_req_context;
-
-       spin_lock_irqsave(&d->lock,flags);
-
-       list_add_tail(&packet->driver_list, &d->pending_list);
-
-       dma_trm_flush(ohci, d);
-
-       spin_unlock_irqrestore(&d->lock,flags);
-
-       return 0;
-}
-
-static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       int retval = 0, phy_reg;
-
-       switch (cmd) {
-       case RESET_BUS:
-               switch (arg) {
-               case SHORT_RESET:
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 1, phy_reg); /* set IBR */
-                       break;
-               case SHORT_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       if (phy_reg & 0x80) {
-                               phy_reg &= ~0x80;
-                               set_phy_reg(ohci, 1, phy_reg); /* clear RHB */
-                       }
-
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg &= ~0x80;
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       if (!(phy_reg & 0x80)) {
-                               phy_reg |= 0x80;
-                               set_phy_reg(ohci, 1, phy_reg); /* set RHB */
-                       }
-
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg |= 0xc0;
-                       set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */
-                       break;
-               default:
-                       retval = -1;
-               }
-               break;
-
-       case GET_CYCLE_COUNTER:
-               retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-               break;
-
-       case SET_CYCLE_COUNTER:
-               reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg);
-               break;
-
-       case SET_BUS_ID:
-               PRINT(KERN_ERR, "devctl command SET_BUS_ID err");
-               break;
-
-       case ACT_CYCLE_MASTER:
-               if (arg) {
-                       /* check if we are root and other nodes are present */
-                       u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
-                       if ((nodeId & (1<<30)) && (nodeId & 0x3f)) {
-                               /*
-                                * enable cycleTimer, cycleMaster
-                                */
-                               DBGMSG("Cycle master enabled");
-                               reg_write(ohci, OHCI1394_LinkControlSet,
-                                         OHCI1394_LinkControl_CycleTimerEnable |
-                                         OHCI1394_LinkControl_CycleMaster);
-                       }
-               } else {
-                       /* disable cycleTimer, cycleMaster, cycleSource */
-                       reg_write(ohci, OHCI1394_LinkControlClear,
-                                 OHCI1394_LinkControl_CycleTimerEnable |
-                                 OHCI1394_LinkControl_CycleMaster |
-                                 OHCI1394_LinkControl_CycleSource);
-               }
-               break;
-
-       case CANCEL_REQUESTS:
-               DBGMSG("Cancel request received");
-               dma_trm_reset(&ohci->at_req_context);
-               dma_trm_reset(&ohci->at_resp_context);
-               break;
-
-       default:
-               PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
-                       cmd);
-               break;
-       }
-       return retval;
-}
-
-/***********************************
- * rawiso ISO reception            *
- ***********************************/
-
-/*
-  We use either buffer-fill or packet-per-buffer DMA mode. The DMA
-  buffer is split into "blocks" (regions described by one DMA
-  descriptor). Each block must be one page or less in size, and
-  must not cross a page boundary.
-
-  There is one little wrinkle with buffer-fill mode: a packet that
-  starts in the final block may wrap around into the first block. But
-  the user API expects all packets to be contiguous. Our solution is
-  to keep the very last page of the DMA buffer in reserve - if a
-  packet spans the gap, we copy its tail into this page.
-*/
-
-struct ohci_iso_recv {
-       struct ti_ohci *ohci;
-
-       struct ohci1394_iso_tasklet task;
-       int task_active;
-
-       enum { BUFFER_FILL_MODE = 0,
-              PACKET_PER_BUFFER_MODE = 1 } dma_mode;
-
-       /* memory and PCI mapping for the DMA descriptors */
-       struct dma_prog_region prog;
-       struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */
-
-       /* how many DMA blocks fit in the buffer */
-       unsigned int nblocks;
-
-       /* stride of DMA blocks */
-       unsigned int buf_stride;
-
-       /* number of blocks to batch between interrupts */
-       int block_irq_interval;
-
-       /* block that DMA will finish next */
-       int block_dma;
-
-       /* (buffer-fill only) block that the reader will release next */
-       int block_reader;
-
-       /* (buffer-fill only) bytes of buffer the reader has released,
-          less than one block */
-       int released_bytes;
-
-       /* (buffer-fill only) buffer offset at which the next packet will appear */
-       int dma_offset;
-
-       /* OHCI DMA context control registers */
-       u32 ContextControlSet;
-       u32 ContextControlClear;
-       u32 CommandPtr;
-       u32 ContextMatch;
-};
-
-static void ohci_iso_recv_task(unsigned long data);
-static void ohci_iso_recv_stop(struct hpsb_iso *iso);
-static void ohci_iso_recv_shutdown(struct hpsb_iso *iso);
-static int  ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync);
-static void ohci_iso_recv_program(struct hpsb_iso *iso);
-
-static int ohci_iso_recv_init(struct hpsb_iso *iso)
-{
-       struct ti_ohci *ohci = iso->host->hostdata;
-       struct ohci_iso_recv *recv;
-       int ctx;
-       int ret = -ENOMEM;
-
-       recv = kmalloc(sizeof(*recv), GFP_KERNEL);
-       if (!recv)
-               return -ENOMEM;
-
-       iso->hostdata = recv;
-       recv->ohci = ohci;
-       recv->task_active = 0;
-       dma_prog_region_init(&recv->prog);
-       recv->block = NULL;
-
-       /* use buffer-fill mode, unless irq_interval is 1
-          (note: multichannel requires buffer-fill) */
-
-       if (((iso->irq_interval == 1 && iso->dma_mode == HPSB_ISO_DMA_OLD_ABI) ||
-            iso->dma_mode == HPSB_ISO_DMA_PACKET_PER_BUFFER) && iso->channel != -1) {
-               recv->dma_mode = PACKET_PER_BUFFER_MODE;
-       } else {
-               recv->dma_mode = BUFFER_FILL_MODE;
-       }
-
-       /* set nblocks, buf_stride, block_irq_interval */
-
-       if (recv->dma_mode == BUFFER_FILL_MODE) {
-               recv->buf_stride = PAGE_SIZE;
-
-               /* one block per page of data in the DMA buffer, minus the final guard page */
-               recv->nblocks = iso->buf_size/PAGE_SIZE - 1;
-               if (recv->nblocks < 3) {
-                       DBGMSG("ohci_iso_recv_init: DMA buffer too small");
-                       goto err;
-               }
-
-               /* iso->irq_interval is in packets - translate that to blocks */
-               if (iso->irq_interval == 1)
-                       recv->block_irq_interval = 1;
-               else
-                       recv->block_irq_interval = iso->irq_interval *
-                                                       ((recv->nblocks+1)/iso->buf_packets);
-               if (recv->block_irq_interval*4 > recv->nblocks)
-                       recv->block_irq_interval = recv->nblocks/4;
-               if (recv->block_irq_interval < 1)
-                       recv->block_irq_interval = 1;
-
-       } else {
-               int max_packet_size;
-
-               recv->nblocks = iso->buf_packets;
-               recv->block_irq_interval = iso->irq_interval;
-               if (recv->block_irq_interval * 4 > iso->buf_packets)
-                       recv->block_irq_interval = iso->buf_packets / 4;
-               if (recv->block_irq_interval < 1)
-                       recv->block_irq_interval = 1;
-
-               /* choose a buffer stride */
-               /* must be a power of 2, and <= PAGE_SIZE */
-
-               max_packet_size = iso->buf_size / iso->buf_packets;
-
-               for (recv->buf_stride = 8; recv->buf_stride < max_packet_size;
-                   recv->buf_stride *= 2);
-
-               if (recv->buf_stride*iso->buf_packets > iso->buf_size ||
-                  recv->buf_stride > PAGE_SIZE) {
-                       /* this shouldn't happen, but anyway... */
-                       DBGMSG("ohci_iso_recv_init: problem choosing a buffer stride");
-                       goto err;
-               }
-       }
-
-       recv->block_reader = 0;
-       recv->released_bytes = 0;
-       recv->block_dma = 0;
-       recv->dma_offset = 0;
-
-       /* size of DMA program = one descriptor per block */
-       if (dma_prog_region_alloc(&recv->prog,
-                                sizeof(struct dma_cmd) * recv->nblocks,
-                                recv->ohci->dev))
-               goto err;
-
-       recv->block = (struct dma_cmd*) recv->prog.kvirt;
-
-       ohci1394_init_iso_tasklet(&recv->task,
-                                 iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE :
-                                                      OHCI_ISO_RECEIVE,
-                                 ohci_iso_recv_task, (unsigned long) iso);
-
-       if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) {
-               ret = -EBUSY;
-               goto err;
-       }
-
-       recv->task_active = 1;
-
-       /* recv context registers are spaced 32 bytes apart */
-       ctx = recv->task.context;
-       recv->ContextControlSet = OHCI1394_IsoRcvContextControlSet + 32 * ctx;
-       recv->ContextControlClear = OHCI1394_IsoRcvContextControlClear + 32 * ctx;
-       recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx;
-       recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx;
-
-       if (iso->channel == -1) {
-               /* clear multi-channel selection mask */
-               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF);
-               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF);
-       }
-
-       /* write the DMA program */
-       ohci_iso_recv_program(iso);
-
-       DBGMSG("ohci_iso_recv_init: %s mode, DMA buffer is %lu pages"
-              " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d",
-              recv->dma_mode == BUFFER_FILL_MODE ?
-              "buffer-fill" : "packet-per-buffer",
-              iso->buf_size/PAGE_SIZE, iso->buf_size,
-              recv->nblocks, recv->buf_stride, recv->block_irq_interval);
-
-       return 0;
-
-err:
-       ohci_iso_recv_shutdown(iso);
-       return ret;
-}
-
-static void ohci_iso_recv_stop(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       /* disable interrupts */
-       reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context);
-
-       /* halt DMA */
-       ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL);
-}
-
-static void ohci_iso_recv_shutdown(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       if (recv->task_active) {
-               ohci_iso_recv_stop(iso);
-               ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task);
-               recv->task_active = 0;
-       }
-
-       dma_prog_region_free(&recv->prog);
-       kfree(recv);
-       iso->hostdata = NULL;
-}
-
-/* set up a "gapped" ring buffer DMA program */
-static void ohci_iso_recv_program(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int blk;
-
-       /* address of 'branch' field in previous DMA descriptor */
-       u32 *prev_branch = NULL;
-
-       for (blk = 0; blk < recv->nblocks; blk++) {
-               u32 control;
-
-               /* the DMA descriptor */
-               struct dma_cmd *cmd = &recv->block[blk];
-
-               /* offset of the DMA descriptor relative to the DMA prog buffer */
-               unsigned long prog_offset = blk * sizeof(struct dma_cmd);
-
-               /* offset of this packet's data within the DMA buffer */
-               unsigned long buf_offset = blk * recv->buf_stride;
-
-               if (recv->dma_mode == BUFFER_FILL_MODE) {
-                       control = 2 << 28; /* INPUT_MORE */
-               } else {
-                       control = 3 << 28; /* INPUT_LAST */
-               }
-
-               control |= 8 << 24; /* s = 1, update xferStatus and resCount */
-
-               /* interrupt on last block, and at intervals */
-               if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
-                       control |= 3 << 20; /* want interrupt */
-               }
-
-               control |= 3 << 18; /* enable branch to address */
-               control |= recv->buf_stride;
-
-               cmd->control = cpu_to_le32(control);
-               cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
-               cmd->branchAddress = 0; /* filled in on next loop */
-               cmd->status = cpu_to_le32(recv->buf_stride);
-
-               /* link the previous descriptor to this one */
-               if (prev_branch) {
-                       *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
-               }
-
-               prev_branch = &cmd->branchAddress;
-       }
-
-       /* the final descriptor's branch address and Z should be left at 0 */
-}
-
-/* listen or unlisten to a specific channel (multi-channel mode only) */
-static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int reg, i;
-
-       if (channel < 32) {
-               reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear;
-               i = channel;
-       } else {
-               reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear;
-               i = channel - 32;
-       }
-
-       reg_write(recv->ohci, reg, (1 << i));
-
-       /* issue a dummy read to force all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int i;
-
-       for (i = 0; i < 64; i++) {
-               if (mask & (1ULL << i)) {
-                       if (i < 32)
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i));
-                       else
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32)));
-               } else {
-                       if (i < 32)
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i));
-                       else
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32)));
-               }
-       }
-
-       /* issue a dummy read to force all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       struct ti_ohci *ohci = recv->ohci;
-       u32 command, contextMatch;
-
-       reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF);
-       wmb();
-
-       /* always keep ISO headers */
-       command = (1 << 30);
-
-       if (recv->dma_mode == BUFFER_FILL_MODE)
-               command |= (1 << 31);
-
-       reg_write(recv->ohci, recv->ContextControlSet, command);
-
-       /* match on specified tags */
-       contextMatch = tag_mask << 28;
-
-       if (iso->channel == -1) {
-               /* enable multichannel reception */
-               reg_write(recv->ohci, recv->ContextControlSet, (1 << 28));
-       } else {
-               /* listen on channel */
-               contextMatch |= iso->channel;
-       }
-
-       if (cycle != -1) {
-               u32 seconds;
-
-               /* enable cycleMatch */
-               reg_write(recv->ohci, recv->ContextControlSet, (1 << 29));
-
-               /* set starting cycle */
-               cycle &= 0x1FFF;
-
-               /* 'cycle' is only mod 8000, but we also need two 'seconds' bits -
-                  just snarf them from the current time */
-               seconds = reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer) >> 25;
-
-               /* advance one second to give some extra time for DMA to start */
-               seconds += 1;
-
-               cycle |= (seconds & 3) << 13;
-
-               contextMatch |= cycle << 12;
-       }
-
-       if (sync != -1) {
-               /* set sync flag on first DMA descriptor */
-               struct dma_cmd *cmd = &recv->block[recv->block_dma];
-               cmd->control |= cpu_to_le32(DMA_CTL_WAIT);
-
-               /* match sync field */
-               contextMatch |= (sync&0xf)<<8;
-       }
-
-       reg_write(recv->ohci, recv->ContextMatch, contextMatch);
-
-       /* address of first descriptor block */
-       command = dma_prog_region_offset_to_bus(&recv->prog,
-                                               recv->block_dma * sizeof(struct dma_cmd));
-       command |= 1; /* Z=1 */
-
-       reg_write(recv->ohci, recv->CommandPtr, command);
-
-       /* enable interrupts */
-       reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context);
-
-       wmb();
-
-       /* run */
-       reg_write(recv->ohci, recv->ContextControlSet, 0x8000);
-
-       /* issue a dummy read of the cycle timer register to force
-          all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-
-       /* check RUN */
-       if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) {
-               PRINT(KERN_ERR,
-                     "Error starting IR DMA (ContextControl 0x%08x)\n",
-                     reg_read(recv->ohci, recv->ContextControlSet));
-               return -1;
-       }
-
-       return 0;
-}
-
-static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
-{
-       /* re-use the DMA descriptor for the block */
-       /* by linking the previous descriptor to it */
-
-       int next_i = block;
-       int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1);
-
-       struct dma_cmd *next = &recv->block[next_i];
-       struct dma_cmd *prev = &recv->block[prev_i];
-       
-       /* ignore out-of-range requests */
-       if ((block < 0) || (block > recv->nblocks))
-               return;
-
-       /* 'next' becomes the new end of the DMA chain,
-          so disable branch and enable interrupt */
-       next->branchAddress = 0;
-       next->control |= cpu_to_le32(3 << 20);
-       next->status = cpu_to_le32(recv->buf_stride);
-
-       /* link prev to next */
-       prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
-                                                                       sizeof(struct dma_cmd) * next_i)
-                                         | 1); /* Z=1 */
-
-       /* disable interrupt on previous DMA descriptor, except at intervals */
-       if ((prev_i % recv->block_irq_interval) == 0) {
-               prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
-       } else {
-               prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
-       }
-       wmb();
-
-       /* wake up DMA in case it fell asleep */
-       reg_write(recv->ohci, recv->ContextControlSet, (1 << 12));
-}
-
-static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv,
-                                            struct hpsb_iso_packet_info *info)
-{
-       /* release the memory where the packet was */
-       recv->released_bytes += info->total_len;
-
-       /* have we released enough memory for one block? */
-       while (recv->released_bytes > recv->buf_stride) {
-               ohci_iso_recv_release_block(recv, recv->block_reader);
-               recv->block_reader = (recv->block_reader + 1) % recv->nblocks;
-               recv->released_bytes -= recv->buf_stride;
-       }
-}
-
-static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       if (recv->dma_mode == BUFFER_FILL_MODE) {
-               ohci_iso_recv_bufferfill_release(recv, info);
-       } else {
-               ohci_iso_recv_release_block(recv, info - iso->infos);
-       }
-}
-
-/* parse all packets from blocks that have been fully received */
-static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int wake = 0;
-       int runaway = 0;
-       struct ti_ohci *ohci = recv->ohci;
-
-       while (1) {
-               /* we expect the next parsable packet to begin at recv->dma_offset */
-               /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */
-
-               unsigned int offset;
-               unsigned short len, cycle, total_len;
-               unsigned char channel, tag, sy;
-
-               unsigned char *p = iso->data_buf.kvirt;
-
-               unsigned int this_block = recv->dma_offset/recv->buf_stride;
-
-               /* don't loop indefinitely */
-               if (runaway++ > 100000) {
-                       atomic_inc(&iso->overflows);
-                       PRINT(KERN_ERR,
-                             "IR DMA error - Runaway during buffer parsing!\n");
-                       break;
-               }
-
-               /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */
-               if (this_block == recv->block_dma)
-                       break;
-
-               wake = 1;
-
-               /* parse data length, tag, channel, and sy */
-
-               /* note: we keep our own local copies of 'len' and 'offset'
-                  so the user can't mess with them by poking in the mmap area */
-
-               len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8);
-
-               if (len > 4096) {
-                       PRINT(KERN_ERR,
-                             "IR DMA error - bogus 'len' value %u\n", len);
-               }
-
-               channel = p[recv->dma_offset+1] & 0x3F;
-               tag = p[recv->dma_offset+1] >> 6;
-               sy = p[recv->dma_offset+0] & 0xF;
-
-               /* advance to data payload */
-               recv->dma_offset += 4;
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               /* dma_offset now points to the first byte of the data payload */
-               offset = recv->dma_offset;
-
-               /* advance to xferStatus/timeStamp */
-               recv->dma_offset += len;
-
-               total_len = len + 8; /* 8 bytes header+trailer in OHCI packet */
-               /* payload is padded to 4 bytes */
-               if (len % 4) {
-                       recv->dma_offset += 4 - (len%4);
-                       total_len += 4 - (len%4);
-               }
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       /* uh oh, the packet data wraps from the last
-                           to the first DMA block - make the packet
-                           contiguous by copying its "tail" into the
-                           guard page */
-
-                       int guard_off = recv->buf_stride*recv->nblocks;
-                       int tail_len = len - (guard_off - offset);
-
-                       if (tail_len > 0  && tail_len < recv->buf_stride) {
-                               memcpy(iso->data_buf.kvirt + guard_off,
-                                      iso->data_buf.kvirt,
-                                      tail_len);
-                       }
-
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               /* parse timestamp */
-               cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8);
-               cycle &= 0x1FFF;
-
-               /* advance to next packet */
-               recv->dma_offset += 4;
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               hpsb_iso_packet_received(iso, offset, len, total_len, cycle, channel, tag, sy);
-       }
-
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int loop;
-       struct ti_ohci *ohci = recv->ohci;
-
-       /* loop over all blocks */
-       for (loop = 0; loop < recv->nblocks; loop++) {
-
-               /* check block_dma to see if it's done */
-               struct dma_cmd *im = &recv->block[recv->block_dma];
-
-               /* check the DMA descriptor for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(im->status) >> 16;
-
-               /* rescount is the number of bytes *remaining to be written* in the block */
-               u16 rescount = le32_to_cpu(im->status) & 0xFFFF;
-
-               unsigned char event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* nothing has happened to this block yet */
-                       break;
-               }
-
-               if (event != 0x11) {
-                       atomic_inc(&iso->overflows);
-                       PRINT(KERN_ERR,
-                             "IR DMA error - OHCI error code 0x%02x\n", event);
-               }
-
-               if (rescount != 0) {
-                       /* the card is still writing to this block;
-                          we can't touch it until it's done */
-                       break;
-               }
-
-               /* OK, the block is finished... */
-
-               /* sync our view of the block */
-               dma_region_sync_for_cpu(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride);
-
-               /* reset the DMA descriptor */
-               im->status = recv->buf_stride;
-
-               /* advance block_dma */
-               recv->block_dma = (recv->block_dma + 1) % recv->nblocks;
-
-               if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) {
-                       atomic_inc(&iso->overflows);
-                       DBGMSG("ISO reception overflow - "
-                              "ran out of DMA blocks");
-               }
-       }
-
-       /* parse any packets that have arrived */
-       ohci_iso_recv_bufferfill_parse(iso, recv);
-}
-
-static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int count;
-       int wake = 0;
-       struct ti_ohci *ohci = recv->ohci;
-
-       /* loop over the entire buffer */
-       for (count = 0; count < recv->nblocks; count++) {
-               u32 packet_len = 0;
-
-               /* pointer to the DMA descriptor */
-               struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
-
-               /* check the DMA descriptor for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(il->status) >> 16;
-               u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
-
-               unsigned char event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* this packet hasn't come in yet; we are done for now */
-                       goto out;
-               }
-
-               if (event == 0x11) {
-                       /* packet received successfully! */
-
-                       /* rescount is the number of bytes *remaining* in the packet buffer,
-                          after the packet was written */
-                       packet_len = recv->buf_stride - rescount;
-
-               } else if (event == 0x02) {
-                       PRINT(KERN_ERR, "IR DMA error - packet too long for buffer\n");
-               } else if (event) {
-                       PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event);
-               }
-
-               /* sync our view of the buffer */
-               dma_region_sync_for_cpu(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride);
-
-               /* record the per-packet info */
-               {
-                       /* iso header is 8 bytes ahead of the data payload */
-                       unsigned char *hdr;
-
-                       unsigned int offset;
-                       unsigned short cycle;
-                       unsigned char channel, tag, sy;
-
-                       offset = iso->pkt_dma * recv->buf_stride;
-                       hdr = iso->data_buf.kvirt + offset;
-
-                       /* skip iso header */
-                       offset += 8;
-                       packet_len -= 8;
-
-                       cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF;
-                       channel = hdr[5] & 0x3F;
-                       tag = hdr[5] >> 6;
-                       sy = hdr[4] & 0xF;
-
-                       hpsb_iso_packet_received(iso, offset, packet_len,
-                                       recv->buf_stride, cycle, channel, tag, sy);
-               }
-
-               /* reset the DMA descriptor */
-               il->status = recv->buf_stride;
-
-               wake = 1;
-               recv->block_dma = iso->pkt_dma;
-       }
-
-out:
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static void ohci_iso_recv_task(unsigned long data)
-{
-       struct hpsb_iso *iso = (struct hpsb_iso*) data;
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       if (recv->dma_mode == BUFFER_FILL_MODE)
-               ohci_iso_recv_bufferfill_task(iso, recv);
-       else
-               ohci_iso_recv_packetperbuf_task(iso, recv);
-}
-
-/***********************************
- * rawiso ISO transmission         *
- ***********************************/
-
-struct ohci_iso_xmit {
-       struct ti_ohci *ohci;
-       struct dma_prog_region prog;
-       struct ohci1394_iso_tasklet task;
-       int task_active;
-       int last_cycle;
-       atomic_t skips;
-
-       u32 ContextControlSet;
-       u32 ContextControlClear;
-       u32 CommandPtr;
-};
-
-/* transmission DMA program:
-   one OUTPUT_MORE_IMMEDIATE for the IT header
-   one OUTPUT_LAST for the buffer data */
-
-struct iso_xmit_cmd {
-       struct dma_cmd output_more_immediate;
-       u8 iso_hdr[8];
-       u32 unused[2];
-       struct dma_cmd output_last;
-};
-
-static int ohci_iso_xmit_init(struct hpsb_iso *iso);
-static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle);
-static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso);
-static void ohci_iso_xmit_task(unsigned long data);
-
-static int ohci_iso_xmit_init(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit;
-       unsigned int prog_size;
-       int ctx;
-       int ret = -ENOMEM;
-
-       xmit = kmalloc(sizeof(*xmit), GFP_KERNEL);
-       if (!xmit)
-               return -ENOMEM;
-
-       iso->hostdata = xmit;
-       xmit->ohci = iso->host->hostdata;
-       xmit->task_active = 0;
-       xmit->last_cycle = -1;
-       atomic_set(&iso->skips, 0);
-
-       dma_prog_region_init(&xmit->prog);
-
-       prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets;
-
-       if (dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev))
-               goto err;
-
-       ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT,
-                                 ohci_iso_xmit_task, (unsigned long) iso);
-
-       if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) {
-               ret = -EBUSY;
-               goto err;
-       }
-
-       xmit->task_active = 1;
-
-       /* xmit context registers are spaced 16 bytes apart */
-       ctx = xmit->task.context;
-       xmit->ContextControlSet = OHCI1394_IsoXmitContextControlSet + 16 * ctx;
-       xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx;
-       xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx;
-
-       return 0;
-
-err:
-       ohci_iso_xmit_shutdown(iso);
-       return ret;
-}
-
-static void ohci_iso_xmit_stop(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       /* disable interrupts */
-       reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context);
-
-       /* halt DMA */
-       if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) {
-               /* XXX the DMA context will lock up if you try to send too much data! */
-               PRINT(KERN_ERR,
-                     "you probably exceeded the OHCI card's bandwidth limit - "
-                     "reload the module and reduce xmit bandwidth");
-       }
-}
-
-static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-
-       if (xmit->task_active) {
-               ohci_iso_xmit_stop(iso);
-               ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task);
-               xmit->task_active = 0;
-       }
-
-       dma_prog_region_free(&xmit->prog);
-       kfree(xmit);
-       iso->hostdata = NULL;
-}
-
-static void ohci_iso_xmit_task(unsigned long data)
-{
-       struct hpsb_iso *iso = (struct hpsb_iso*) data;
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-       int wake = 0;
-       int count;
-
-       /* check the whole buffer if necessary, starting at pkt_dma */
-       for (count = 0; count < iso->buf_packets; count++) {
-               int cycle;
-
-               /* DMA descriptor */
-               struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
-
-               /* check for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
-               u8  event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* packet hasn't been sent yet; we are done for now */
-                       break;
-               }
-
-               if (event != 0x11)
-                       PRINT(KERN_ERR,
-                             "IT DMA error - OHCI error code 0x%02x\n", event);
-
-               /* at least one packet went out, so wake up the writer */
-               wake = 1;
-
-               /* parse cycle */
-               cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
-
-               if (xmit->last_cycle > -1) {
-                       int cycle_diff = cycle - xmit->last_cycle;
-                       int skip;
-
-                       /* unwrap */
-                       if (cycle_diff < 0) {
-                               cycle_diff += 8000;
-                               if (cycle_diff < 0)
-                                       PRINT(KERN_ERR, "bogus cycle diff %d\n",
-                                             cycle_diff);
-                       }
-
-                       skip = cycle_diff - 1;
-                       if (skip > 0) {
-                               DBGMSG("skipped %d cycles without packet loss", skip);
-                               atomic_add(skip, &iso->skips);
-                       }
-               }
-               xmit->last_cycle = cycle;
-
-               /* tell the subsystem the packet has gone out */
-               hpsb_iso_packet_sent(iso, cycle, event != 0x11);
-
-               /* reset the DMA descriptor for next time */
-               cmd->output_last.status = 0;
-       }
-
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       int next_i, prev_i;
-       struct iso_xmit_cmd *next, *prev;
-
-       unsigned int offset;
-       unsigned short len;
-       unsigned char tag, sy;
-
-       /* check that the packet doesn't cross a page boundary
-          (we could allow this if we added OUTPUT_MORE descriptor support) */
-       if (cross_bound(info->offset, info->len)) {
-               PRINT(KERN_ERR,
-                     "rawiso xmit: packet %u crosses a page boundary",
-                     iso->first_packet);
-               return -EINVAL;
-       }
-
-       offset = info->offset;
-       len = info->len;
-       tag = info->tag;
-       sy = info->sy;
-
-       /* sync up the card's view of the buffer */
-       dma_region_sync_for_device(&iso->data_buf, offset, len);
-
-       /* append first_packet to the DMA chain */
-       /* by linking the previous descriptor to it */
-       /* (next will become the new end of the DMA chain) */
-
-       next_i = iso->first_packet;
-       prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1);
-
-       next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i);
-       prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i);
-
-       /* set up the OUTPUT_MORE_IMMEDIATE descriptor */
-       memset(next, 0, sizeof(struct iso_xmit_cmd));
-       next->output_more_immediate.control = cpu_to_le32(0x02000008);
-
-       /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
-
-       /* tcode = 0xA, and sy */
-       next->iso_hdr[0] = 0xA0 | (sy & 0xF);
-
-       /* tag and channel number */
-       next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F);
-
-       /* transmission speed */
-       next->iso_hdr[2] = iso->speed & 0x7;
-
-       /* payload size */
-       next->iso_hdr[6] = len & 0xFF;
-       next->iso_hdr[7] = len >> 8;
-
-       /* set up the OUTPUT_LAST */
-       next->output_last.control = cpu_to_le32(1 << 28);
-       next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
-       next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
-       next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
-       next->output_last.control |= cpu_to_le32(len);
-
-       /* payload bus address */
-       next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset));
-
-       /* leave branchAddress at zero for now */
-
-       /* re-write the previous DMA descriptor to chain to this one */
-
-       /* set prev branch address to point to next (Z=3) */
-       prev->output_last.branchAddress = cpu_to_le32(
-               dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
-
-       /*
-        * Link the skip address to this descriptor itself. This causes a
-        * context to skip a cycle whenever lost cycles or FIFO overruns occur,
-        * without dropping the data at that point the application should then
-        * decide whether this is an error condition or not. Some protocols
-        * can deal with this by dropping some rate-matching padding packets.
-        */
-       next->output_more_immediate.branchAddress =
-                       prev->output_last.branchAddress;
-
-       /* disable interrupt, unless required by the IRQ interval */
-       if (prev_i % iso->irq_interval) {
-               prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
-       } else {
-               prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
-       }
-
-       wmb();
-
-       /* wake DMA in case it is sleeping */
-       reg_write(xmit->ohci, xmit->ContextControlSet, 1 << 12);
-
-       /* issue a dummy read of the cycle timer to force all PCI
-          writes to be posted immediately */
-       mb();
-       reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer);
-
-       return 0;
-}
-
-static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       /* clear out the control register */
-       reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF);
-       wmb();
-
-       /* address and length of first descriptor block (Z=3) */
-       reg_write(xmit->ohci, xmit->CommandPtr,
-                 dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3);
-
-       /* cycle match */
-       if (cycle != -1) {
-               u32 start = cycle & 0x1FFF;
-
-               /* 'cycle' is only mod 8000, but we also need two 'seconds' bits -
-                  just snarf them from the current time */
-               u32 seconds = reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer) >> 25;
-
-               /* advance one second to give some extra time for DMA to start */
-               seconds += 1;
-
-               start |= (seconds & 3) << 13;
-
-               reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16));
-       }
-
-       /* enable interrupts */
-       reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context);
-
-       /* run */
-       reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000);
-       mb();
-
-       /* wait 100 usec to give the card time to go active */
-       udelay(100);
-
-       /* check the RUN bit */
-       if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) {
-               PRINT(KERN_ERR, "Error starting IT DMA (ContextControl 0x%08x)\n",
-                     reg_read(xmit->ohci, xmit->ContextControlSet));
-               return -1;
-       }
-
-       return 0;
-}
-
-static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, unsigned long arg)
-{
-
-       switch(cmd) {
-       case XMIT_INIT:
-               return ohci_iso_xmit_init(iso);
-       case XMIT_START:
-               return ohci_iso_xmit_start(iso, arg);
-       case XMIT_STOP:
-               ohci_iso_xmit_stop(iso);
-               return 0;
-       case XMIT_QUEUE:
-               return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg);
-       case XMIT_SHUTDOWN:
-               ohci_iso_xmit_shutdown(iso);
-               return 0;
-
-       case RECV_INIT:
-               return ohci_iso_recv_init(iso);
-       case RECV_START: {
-               int *args = (int*) arg;
-               return ohci_iso_recv_start(iso, args[0], args[1], args[2]);
-       }
-       case RECV_STOP:
-               ohci_iso_recv_stop(iso);
-               return 0;
-       case RECV_RELEASE:
-               ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg);
-               return 0;
-       case RECV_FLUSH:
-               ohci_iso_recv_task((unsigned long) iso);
-               return 0;
-       case RECV_SHUTDOWN:
-               ohci_iso_recv_shutdown(iso);
-               return 0;
-       case RECV_LISTEN_CHANNEL:
-               ohci_iso_recv_change_channel(iso, arg, 1);
-               return 0;
-       case RECV_UNLISTEN_CHANNEL:
-               ohci_iso_recv_change_channel(iso, arg, 0);
-               return 0;
-       case RECV_SET_CHANNEL_MASK:
-               ohci_iso_recv_set_channel_mask(iso, *((u64*) arg));
-               return 0;
-
-       default:
-               PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet",
-                       cmd);
-               break;
-       }
-       return -EINVAL;
-}
-
-/***************************************
- * IEEE-1394 functionality section END *
- ***************************************/
-
-
-/********************************************************
- * Global stuff (interrupt handler, init/shutdown code) *
- ********************************************************/
-
-static void dma_trm_reset(struct dma_trm_ctx *d)
-{
-       unsigned long flags;
-       LIST_HEAD(packet_list);
-       struct ti_ohci *ohci = d->ohci;
-       struct hpsb_packet *packet, *ptmp;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       /* Lock the context, reset it and release it. Move the packets
-        * that were pending in the context to packet_list and free
-        * them after releasing the lock. */
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       list_splice_init(&d->fifo_list, &packet_list);
-       list_splice_init(&d->pending_list, &packet_list);
-
-       d->branchAddrPtr = NULL;
-       d->sent_ind = d->prg_ind;
-       d->free_prgs = d->num_desc;
-
-       spin_unlock_irqrestore(&d->lock, flags);
-
-       if (list_empty(&packet_list))
-               return;
-
-       PRINT(KERN_INFO, "AT dma reset ctx=%d, aborting transmission", d->ctx);
-
-       /* Now process subsystem callbacks for the packets from this
-        * context. */
-       list_for_each_entry_safe(packet, ptmp, &packet_list, driver_list) {
-               list_del_init(&packet->driver_list);
-               hpsb_packet_sent(ohci->host, packet, ACKX_ABORTED);
-       }
-}
-
-static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
-                                      quadlet_t rx_event,
-                                      quadlet_t tx_event)
-{
-       struct ohci1394_iso_tasklet *t;
-       unsigned long mask;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
-               mask = 1 << t->context;
-
-               if (t->type == OHCI_ISO_TRANSMIT) {
-                       if (tx_event & mask)
-                               tasklet_schedule(&t->tasklet);
-               } else {
-                       /* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */
-                       if (rx_event & mask)
-                               tasklet_schedule(&t->tasklet);
-               }
-       }
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-}
-
-static irqreturn_t ohci_irq_handler(int irq, void *dev_id)
-{
-       quadlet_t event, node_id;
-       struct ti_ohci *ohci = (struct ti_ohci *)dev_id;
-       struct hpsb_host *host = ohci->host;
-       int phyid = -1, isroot = 0;
-       unsigned long flags;
-
-       /* Read and clear the interrupt event register.  Don't clear
-        * the busReset event, though. This is done when we get the
-        * selfIDComplete interrupt. */
-       spin_lock_irqsave(&ohci->event_lock, flags);
-       event = reg_read(ohci, OHCI1394_IntEventClear);
-       reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
-       spin_unlock_irqrestore(&ohci->event_lock, flags);
-
-       if (!event)
-               return IRQ_NONE;
-
-       /* If event is ~(u32)0 cardbus card was ejected.  In this case
-        * we just return, and clean up in the ohci1394_pci_remove
-        * function. */
-       if (event == ~(u32) 0) {
-               DBGMSG("Device removed.");
-               return IRQ_NONE;
-       }
-
-       DBGMSG("IntEvent: %08x", event);
-
-       if (event & OHCI1394_unrecoverableError) {
-               int ctx;
-               PRINT(KERN_ERR, "Unrecoverable error!");
-
-               if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Req Tx Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsReqTrContextControlSet),
-                               reg_read(ohci, OHCI1394_AsReqTrCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Rsp Tx Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsRspTrContextControlSet),
-                               reg_read(ohci, OHCI1394_AsRspTrCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Req Rcv Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsReqRcvContextControlSet),
-                               reg_read(ohci, OHCI1394_AsReqRcvCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Rsp Rcv Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsRspRcvContextControlSet),
-                               reg_read(ohci, OHCI1394_AsRspRcvCommandPtr));
-
-               for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) {
-                       if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800)
-                               PRINT(KERN_ERR, "Iso Xmit %d Context died: "
-                                       "ctrl[%08x] cmdptr[%08x]", ctx,
-                                       reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx)));
-               }
-
-               for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) {
-                       if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800)
-                               PRINT(KERN_ERR, "Iso Recv %d Context died: "
-                                       "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx,
-                                       reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoRcvContextMatch + (32 * ctx)));
-               }
-
-               event &= ~OHCI1394_unrecoverableError;
-       }
-       if (event & OHCI1394_postedWriteErr) {
-               PRINT(KERN_ERR, "physical posted write error");
-               /* no recovery strategy yet, had to involve protocol drivers */
-               event &= ~OHCI1394_postedWriteErr;
-       }
-       if (event & OHCI1394_cycleTooLong) {
-               if(printk_ratelimit())
-                       PRINT(KERN_WARNING, "isochronous cycle too long");
-               else
-                       DBGMSG("OHCI1394_cycleTooLong");
-               reg_write(ohci, OHCI1394_LinkControlSet,
-                         OHCI1394_LinkControl_CycleMaster);
-               event &= ~OHCI1394_cycleTooLong;
-       }
-       if (event & OHCI1394_cycleInconsistent) {
-               /* We subscribe to the cycleInconsistent event only to
-                * clear the corresponding event bit... otherwise,
-                * isochronous cycleMatch DMA won't work. */
-               DBGMSG("OHCI1394_cycleInconsistent");
-               event &= ~OHCI1394_cycleInconsistent;
-       }
-       if (event & OHCI1394_busReset) {
-               /* The busReset event bit can't be cleared during the
-                * selfID phase, so we disable busReset interrupts, to
-                * avoid burying the cpu in interrupt requests. */
-               spin_lock_irqsave(&ohci->event_lock, flags);
-               reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
-
-               if (ohci->check_busreset) {
-                       int loop_count = 0;
-
-                       udelay(10);
-
-                       while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
-                               reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
-
-                               spin_unlock_irqrestore(&ohci->event_lock, flags);
-                               udelay(10);
-                               spin_lock_irqsave(&ohci->event_lock, flags);
-
-                               /* The loop counter check is to prevent the driver
-                                * from remaining in this state forever. For the
-                                * initial bus reset, the loop continues for ever
-                                * and the system hangs, until some device is plugged-in
-                                * or out manually into a port! The forced reset seems
-                                * to solve this problem. This mainly effects nForce2. */
-                               if (loop_count > 10000) {
-                                       ohci_devctl(host, RESET_BUS, LONG_RESET);
-                                       DBGMSG("Detected bus-reset loop. Forced a bus reset!");
-                                       loop_count = 0;
-                               }
-
-                               loop_count++;
-                       }
-               }
-               spin_unlock_irqrestore(&ohci->event_lock, flags);
-               if (!host->in_bus_reset) {
-                       DBGMSG("irq_handler: Bus reset requested");
-
-                       /* Subsystem call */
-                       hpsb_bus_reset(ohci->host);
-               }
-               event &= ~OHCI1394_busReset;
-       }
-       if (event & OHCI1394_reqTxComplete) {
-               struct dma_trm_ctx *d = &ohci->at_req_context;
-               DBGMSG("Got reqTxComplete interrupt "
-                      "status=0x%08X", reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear,
-                                             "reqTxComplete");
-               else
-                       dma_trm_tasklet((unsigned long)d);
-                       //tasklet_schedule(&d->task);
-               event &= ~OHCI1394_reqTxComplete;
-       }
-       if (event & OHCI1394_respTxComplete) {
-               struct dma_trm_ctx *d = &ohci->at_resp_context;
-               DBGMSG("Got respTxComplete interrupt "
-                      "status=0x%08X", reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear,
-                                             "respTxComplete");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_respTxComplete;
-       }
-       if (event & OHCI1394_RQPkt) {
-               struct dma_rcv_ctx *d = &ohci->ar_req_context;
-               DBGMSG("Got RQPkt interrupt status=0x%08X",
-                      reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_RQPkt;
-       }
-       if (event & OHCI1394_RSPkt) {
-               struct dma_rcv_ctx *d = &ohci->ar_resp_context;
-               DBGMSG("Got RSPkt interrupt status=0x%08X",
-                      reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_RSPkt;
-       }
-       if (event & OHCI1394_isochRx) {
-               quadlet_t rx_event;
-
-               rx_event = reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
-               reg_write(ohci, OHCI1394_IsoRecvIntEventClear, rx_event);
-               ohci_schedule_iso_tasklets(ohci, rx_event, 0);
-               event &= ~OHCI1394_isochRx;
-       }
-       if (event & OHCI1394_isochTx) {
-               quadlet_t tx_event;
-
-               tx_event = reg_read(ohci, OHCI1394_IsoXmitIntEventSet);
-               reg_write(ohci, OHCI1394_IsoXmitIntEventClear, tx_event);
-               ohci_schedule_iso_tasklets(ohci, 0, tx_event);
-               event &= ~OHCI1394_isochTx;
-       }
-       if (event & OHCI1394_selfIDComplete) {
-               if (host->in_bus_reset) {
-                       node_id = reg_read(ohci, OHCI1394_NodeID);
-
-                       if (!(node_id & 0x80000000)) {
-                               PRINT(KERN_ERR,
-                                     "SelfID received, but NodeID invalid "
-                                     "(probably new bus reset occurred): %08X",
-                                     node_id);
-                               goto selfid_not_valid;
-                       }
-
-                       phyid =  node_id & 0x0000003f;
-                       isroot = (node_id & 0x40000000) != 0;
-
-                       DBGMSG("SelfID interrupt received "
-                             "(phyid %d, %s)", phyid,
-                             (isroot ? "root" : "not root"));
-
-                       handle_selfid(ohci, host, phyid, isroot);
-
-                       /* Clear the bus reset event and re-enable the
-                        * busReset interrupt.  */
-                       spin_lock_irqsave(&ohci->event_lock, flags);
-                       reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
-                       reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
-                       spin_unlock_irqrestore(&ohci->event_lock, flags);
-
-                       /* Turn on phys dma reception.
-                        *
-                        * TODO: Enable some sort of filtering management.
-                        */
-                       if (phys_dma) {
-                               reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
-                                         0xffffffff);
-                               reg_write(ohci, OHCI1394_PhyReqFilterLoSet,
-                                         0xffffffff);
-                       }
-
-                       DBGMSG("PhyReqFilter=%08x%08x",
-                              reg_read(ohci, OHCI1394_PhyReqFilterHiSet),
-                              reg_read(ohci, OHCI1394_PhyReqFilterLoSet));
-
-                       hpsb_selfid_complete(host, phyid, isroot);
-               } else
-                       PRINT(KERN_ERR,
-                             "SelfID received outside of bus reset sequence");
-
-selfid_not_valid:
-               event &= ~OHCI1394_selfIDComplete;
-       }
-
-       /* Make sure we handle everything, just in case we accidentally
-        * enabled an interrupt that we didn't write a handler for.  */
-       if (event)
-               PRINT(KERN_ERR, "Unhandled interrupt(s) 0x%08x",
-                     event);
-
-       return IRQ_HANDLED;
-}
-
-/* Put the buffer back into the dma context */
-static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       DBGMSG("Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
-
-       d->prg_cpu[idx]->status = cpu_to_le32(d->buf_size);
-       d->prg_cpu[idx]->branchAddress &= le32_to_cpu(0xfffffff0);
-       idx = (idx + d->num_desc - 1 ) % d->num_desc;
-       d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001);
-
-       /* To avoid a race, ensure 1394 interface hardware sees the inserted
-        * context program descriptors before it sees the wakeup bit set. */
-       wmb();
-       
-       /* wake up the dma context if necessary */
-       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-               PRINT(KERN_INFO,
-                     "Waking dma ctx=%d ... processing is probably too slow",
-                     d->ctx);
-       }
-
-       /* do this always, to avoid race condition */
-       reg_write(ohci, d->ctrlSet, 0x1000);
-}
-
-#define cond_le32_to_cpu(data, noswap) \
-       (noswap ? data : le32_to_cpu(data))
-
-static const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0,
-                           -1, 0, -1, 0, -1, -1, 16, -1};
-
-/*
- * Determine the length of a packet in the buffer
- * Optimization suggested by Pascal Drolet <pascal.drolet@informission.ca>
- */
-static inline int packet_length(struct dma_rcv_ctx *d, int idx,
-                               quadlet_t *buf_ptr, int offset,
-                               unsigned char tcode, int noswap)
-{
-       int length = -1;
-
-       if (d->type == DMA_CTX_ASYNC_REQ || d->type == DMA_CTX_ASYNC_RESP) {
-               length = TCODE_SIZE[tcode];
-               if (length == 0) {
-                       if (offset + 12 >= d->buf_size) {
-                               length = (cond_le32_to_cpu(d->buf_cpu[(idx + 1) % d->num_desc]
-                                               [3 - ((d->buf_size - offset) >> 2)], noswap) >> 16);
-                       } else {
-                               length = (cond_le32_to_cpu(buf_ptr[3], noswap) >> 16);
-                       }
-                       length += 20;
-               }
-       } else if (d->type == DMA_CTX_ISO) {
-               /* Assumption: buffer fill mode with header/trailer */
-               length = (cond_le32_to_cpu(buf_ptr[0], noswap) >> 16) + 8;
-       }
-
-       if (length > 0 && length % 4)
-               length += 4 - (length % 4);
-
-       return length;
-}
-
-/* Tasklet that processes dma receive buffers */
-static void dma_rcv_tasklet (unsigned long data)
-{
-       struct dma_rcv_ctx *d = (struct dma_rcv_ctx*)data;
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       unsigned int split_left, idx, offset, rescount;
-       unsigned char tcode;
-       int length, bytes_left, ack;
-       unsigned long flags;
-       quadlet_t *buf_ptr;
-       char *split_ptr;
-       char msg[256];
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       idx = d->buf_ind;
-       offset = d->buf_offset;
-       buf_ptr = d->buf_cpu[idx] + offset/4;
-
-       rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff;
-       bytes_left = d->buf_size - rescount - offset;
-
-       while (bytes_left > 0) {
-               tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming) >> 4) & 0xf;
-
-               /* packet_length() will return < 4 for an error */
-               length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->no_swap_incoming);
-
-               if (length < 4) { /* something is wrong */
-                       sprintf(msg,"Unexpected tcode 0x%x(0x%08x) in AR ctx=%d, length=%d",
-                               tcode, cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming),
-                               d->ctx, length);
-                       ohci1394_stop_context(ohci, d->ctrlClear, msg);
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return;
-               }
-
-               /* The first case is where we have a packet that crosses
-                * over more than one descriptor. The next case is where
-                * it's all in the first descriptor.  */
-               if ((offset + length) > d->buf_size) {
-                       DBGMSG("Split packet rcv'd");
-                       if (length > d->split_buf_size) {
-                               ohci1394_stop_context(ohci, d->ctrlClear,
-                                            "Split packet size exceeded");
-                               d->buf_ind = idx;
-                               d->buf_offset = offset;
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-
-                       if (le32_to_cpu(d->prg_cpu[(idx+1)%d->num_desc]->status)
-                           == d->buf_size) {
-                               /* Other part of packet not written yet.
-                                * this should never happen I think
-                                * anyway we'll get it on the next call.  */
-                               PRINT(KERN_INFO,
-                                     "Got only half a packet!");
-                               d->buf_ind = idx;
-                               d->buf_offset = offset;
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-
-                       split_left = length;
-                       split_ptr = (char *)d->spb;
-                       memcpy(split_ptr,buf_ptr,d->buf_size-offset);
-                       split_left -= d->buf_size-offset;
-                       split_ptr += d->buf_size-offset;
-                       insert_dma_buffer(d, idx);
-                       idx = (idx+1) % d->num_desc;
-                       buf_ptr = d->buf_cpu[idx];
-                       offset=0;
-
-                       while (split_left >= d->buf_size) {
-                               memcpy(split_ptr,buf_ptr,d->buf_size);
-                               split_ptr += d->buf_size;
-                               split_left -= d->buf_size;
-                               insert_dma_buffer(d, idx);
-                               idx = (idx+1) % d->num_desc;
-                               buf_ptr = d->buf_cpu[idx];
-                       }
-
-                       if (split_left > 0) {
-                               memcpy(split_ptr, buf_ptr, split_left);
-                               offset = split_left;
-                               buf_ptr += offset/4;
-                       }
-               } else {
-                       DBGMSG("Single packet rcv'd");
-                       memcpy(d->spb, buf_ptr, length);
-                       offset += length;
-                       buf_ptr += length/4;
-                       if (offset==d->buf_size) {
-                               insert_dma_buffer(d, idx);
-                               idx = (idx+1) % d->num_desc;
-                               buf_ptr = d->buf_cpu[idx];
-                               offset=0;
-                       }
-               }
-
-               /* We get one phy packet to the async descriptor for each
-                * bus reset. We always ignore it.  */
-               if (tcode != OHCI1394_TCODE_PHY) {
-                       if (!ohci->no_swap_incoming)
-                               header_le32_to_cpu(d->spb, tcode);
-                       DBGMSG("Packet received from node"
-                               " %d ack=0x%02X spd=%d tcode=0x%X"
-                               " length=%d ctx=%d tlabel=%d",
-                               (d->spb[1]>>16)&0x3f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
-                               tcode, length, d->ctx,
-                               (d->spb[0]>>10)&0x3f);
-
-                       ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
-                               == 0x11) ? 1 : 0;
-
-                       hpsb_packet_received(ohci->host, d->spb,
-                                            length-4, ack);
-               }
-#ifdef OHCI1394_DEBUG
-               else
-                       PRINT (KERN_DEBUG, "Got phy packet ctx=%d ... discarded",
-                              d->ctx);
-#endif
-
-               rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff;
-
-               bytes_left = d->buf_size - rescount - offset;
-
-       }
-
-       d->buf_ind = idx;
-       d->buf_offset = offset;
-
-       spin_unlock_irqrestore(&d->lock, flags);
-}
-
-/* Bottom half that processes sent packets */
-static void dma_trm_tasklet (unsigned long data)
-{
-       struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       struct hpsb_packet *packet, *ptmp;
-       unsigned long flags;
-       u32 status, ack;
-        size_t datasize;
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       list_for_each_entry_safe(packet, ptmp, &d->fifo_list, driver_list) {
-                datasize = packet->data_size;
-               if (datasize && packet->type != hpsb_raw)
-                       status = le32_to_cpu(
-                               d->prg_cpu[d->sent_ind]->end.status) >> 16;
-               else
-                       status = le32_to_cpu(
-                               d->prg_cpu[d->sent_ind]->begin.status) >> 16;
-
-               if (status == 0)
-                       /* this packet hasn't been sent yet*/
-                       break;
-
-#ifdef OHCI1394_DEBUG
-               if (datasize)
-                       if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa)
-                               DBGMSG("Stream packet sent to channel %d tcode=0x%X "
-                                      "ack=0x%X spd=%d dataLength=%d ctx=%d",
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
-                                      status&0x1f, (status>>5)&0x3,
-                                      le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16,
-                                      d->ctx);
-                       else
-                               DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-                                      "%d ack=0x%X spd=%d dataLength=%d ctx=%d",
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>10)&0x3f,
-                                      status&0x1f, (status>>5)&0x3,
-                                      le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])>>16,
-                                      d->ctx);
-               else
-                       DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-                              "%d ack=0x%X spd=%d data=0x%08X ctx=%d",
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])
-                                        >>16)&0x3f,
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
-                                        >>4)&0xf,
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
-                                        >>10)&0x3f,
-                                status&0x1f, (status>>5)&0x3,
-                                le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]),
-                                d->ctx);
-#endif
-
-               if (status & 0x10) {
-                       ack = status & 0xf;
-               } else {
-                       switch (status & 0x1f) {
-                       case EVT_NO_STATUS: /* that should never happen */
-                       case EVT_RESERVED_A: /* that should never happen */
-                       case EVT_LONG_PACKET: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_MISSING_ACK:
-                               ack = ACKX_TIMEOUT;
-                               break;
-                       case EVT_UNDERRUN:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_OVERRUN: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_DESCRIPTOR_READ:
-                       case EVT_DATA_READ:
-                       case EVT_DATA_WRITE:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_BUS_RESET: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_TIMEOUT:
-                               ack = ACKX_TIMEOUT;
-                               break;
-                       case EVT_TCODE_ERR:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_RESERVED_B: /* that should never happen */
-                       case EVT_RESERVED_C: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_UNKNOWN:
-                       case EVT_FLUSHED:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       default:
-                               PRINT(KERN_ERR, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               BUG();
-                       }
-               }
-
-               list_del_init(&packet->driver_list);
-               hpsb_packet_sent(ohci->host, packet, ack);
-
-               if (datasize)
-                       pci_unmap_single(ohci->dev,
-                                        cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
-                                        datasize, PCI_DMA_TODEVICE);
-
-               d->sent_ind = (d->sent_ind+1)%d->num_desc;
-               d->free_prgs++;
-       }
-
-       dma_trm_flush(ohci, d);
-
-       spin_unlock_irqrestore(&d->lock, flags);
-}
-
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
-       int i;
-       struct ti_ohci *ohci = d->ohci;
-
-       if (ohci == NULL)
-               return;
-
-       DBGMSG("Freeing dma_rcv_ctx %d", d->ctx);
-
-       if (d->buf_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->buf_cpu[i] && d->buf_bus[i])
-                               pci_free_consistent(
-                                       ohci->dev, d->buf_size,
-                                       d->buf_cpu[i], d->buf_bus[i]);
-               kfree(d->buf_cpu);
-               kfree(d->buf_bus);
-       }
-       if (d->prg_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->prg_cpu[i] && d->prg_bus[i])
-                               pci_pool_free(d->prg_pool, d->prg_cpu[i],
-                                             d->prg_bus[i]);
-               pci_pool_destroy(d->prg_pool);
-               kfree(d->prg_cpu);
-               kfree(d->prg_bus);
-       }
-       kfree(d->spb);
-
-       /* Mark this context as freed. */
-       d->ohci = NULL;
-}
-
-static int
-alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
-                 enum context_type type, int ctx, int num_desc,
-                 int buf_size, int split_buf_size, int context_base)
-{
-       int i, len;
-       static int num_allocs;
-       static char pool_name[20];
-
-       d->ohci = ohci;
-       d->type = type;
-       d->ctx = ctx;
-
-       d->num_desc = num_desc;
-       d->buf_size = buf_size;
-       d->split_buf_size = split_buf_size;
-
-       d->ctrlSet = 0;
-       d->ctrlClear = 0;
-       d->cmdPtr = 0;
-
-       d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
-       d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
-
-       if (d->buf_cpu == NULL || d->buf_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-
-       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
-       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
-
-       if (d->prg_cpu == NULL || d->prg_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-
-       d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
-
-       if (d->spb == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "split buffer");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-       
-       len = sprintf(pool_name, "ohci1394_rcv_prg");
-       sprintf(pool_name+len, "%d", num_allocs);
-       d->prg_pool = pci_pool_create(pool_name, ohci->dev,
-                               sizeof(struct dma_cmd), 4, 0);
-       if(d->prg_pool == NULL)
-       {
-               PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-       num_allocs++;
-
-       for (i=0; i<d->num_desc; i++) {
-               d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
-                                                    d->buf_size,
-                                                    d->buf_bus+i);
-
-               if (d->buf_cpu[i] != NULL) {
-                       memset(d->buf_cpu[i], 0, d->buf_size);
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "DMA buffer");
-                       free_dma_rcv_ctx(d);
-                       return -ENOMEM;
-               }
-
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-
-                if (d->prg_cpu[i] != NULL) {
-                        memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "DMA prg");
-                       free_dma_rcv_ctx(d);
-                       return -ENOMEM;
-               }
-       }
-
-        spin_lock_init(&d->lock);
-
-       d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-       d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-       d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-
-       tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
-       return 0;
-}
-
-static void free_dma_trm_ctx(struct dma_trm_ctx *d)
-{
-       int i;
-       struct ti_ohci *ohci = d->ohci;
-
-       if (ohci == NULL)
-               return;
-
-       DBGMSG("Freeing dma_trm_ctx %d", d->ctx);
-
-       if (d->prg_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->prg_cpu[i] && d->prg_bus[i])
-                               pci_pool_free(d->prg_pool, d->prg_cpu[i],
-                                             d->prg_bus[i]);
-               pci_pool_destroy(d->prg_pool);
-               kfree(d->prg_cpu);
-               kfree(d->prg_bus);
-       }
-
-       /* Mark this context as freed. */
-       d->ohci = NULL;
-}
-
-static int
-alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
-                 enum context_type type, int ctx, int num_desc,
-                 int context_base)
-{
-       int i, len;
-       static char pool_name[20];
-       static int num_allocs=0;
-
-       d->ohci = ohci;
-       d->type = type;
-       d->ctx = ctx;
-       d->num_desc = num_desc;
-       d->ctrlSet = 0;
-       d->ctrlClear = 0;
-       d->cmdPtr = 0;
-
-       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
-       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
-
-       if (d->prg_cpu == NULL || d->prg_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg");
-               free_dma_trm_ctx(d);
-               return -ENOMEM;
-       }
-
-       len = sprintf(pool_name, "ohci1394_trm_prg");
-       sprintf(pool_name+len, "%d", num_allocs);
-       d->prg_pool = pci_pool_create(pool_name, ohci->dev,
-                               sizeof(struct at_dma_prg), 4, 0);
-       if (d->prg_pool == NULL) {
-               PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
-               free_dma_trm_ctx(d);
-               return -ENOMEM;
-       }
-       num_allocs++;
-
-       for (i = 0; i < d->num_desc; i++) {
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-
-                if (d->prg_cpu[i] != NULL) {
-                        memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "AT DMA prg");
-                       free_dma_trm_ctx(d);
-                       return -ENOMEM;
-               }
-       }
-
-        spin_lock_init(&d->lock);
-
-       /* initialize tasklet */
-       d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-       d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-       d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-       tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
-       return 0;
-}
-
-static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom)
-{
-       struct ti_ohci *ohci = host->hostdata;
-
-       reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0]));
-       reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2]));
-
-       memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN);
-}
-
-
-static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg,
-                                 quadlet_t data, quadlet_t compare)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       int i;
-
-       reg_write(ohci, OHCI1394_CSRData, data);
-       reg_write(ohci, OHCI1394_CSRCompareData, compare);
-       reg_write(ohci, OHCI1394_CSRControl, reg & 0x3);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
-                       break;
-
-               mdelay(1);
-       }
-
-       return reg_read(ohci, OHCI1394_CSRData);
-}
-
-static struct hpsb_host_driver ohci1394_driver = {
-       .owner =                THIS_MODULE,
-       .name =                 OHCI1394_DRIVER_NAME,
-       .set_hw_config_rom =    ohci_set_hw_config_rom,
-       .transmit_packet =      ohci_transmit,
-       .devctl =               ohci_devctl,
-       .isoctl =               ohci_isoctl,
-       .hw_csr_reg =           ohci_hw_csr_reg,
-};
-
-/***********************************
- * PCI Driver Interface functions  *
- ***********************************/
-
-#ifdef CONFIG_PPC_PMAC
-static void ohci1394_pmac_on(struct pci_dev *dev)
-{
-       if (machine_is(powermac)) {
-               struct device_node *ofn = pci_device_to_OF_node(dev);
-
-               if (ofn) {
-                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
-               }
-       }
-}
-
-static void ohci1394_pmac_off(struct pci_dev *dev)
-{
-       if (machine_is(powermac)) {
-               struct device_node *ofn = pci_device_to_OF_node(dev);
-
-               if (ofn) {
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
-                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
-               }
-       }
-}
-#else
-#define ohci1394_pmac_on(dev)
-#define ohci1394_pmac_off(dev)
-#endif /* CONFIG_PPC_PMAC */
-
-static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
-                                       const struct pci_device_id *ent)
-{
-       struct hpsb_host *host;
-       struct ti_ohci *ohci;   /* shortcut to currently handled device */
-       resource_size_t ohci_base;
-       int err = -ENOMEM;
-
-       ohci1394_pmac_on(dev);
-       if (pci_enable_device(dev)) {
-               PRINT_G(KERN_ERR, "Failed to enable OHCI hardware");
-               err = -ENXIO;
-               goto err;
-       }
-        pci_set_master(dev);
-
-       host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
-       if (!host) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure");
-               goto err;
-       }
-       ohci = host->hostdata;
-       ohci->dev = dev;
-       ohci->host = host;
-       ohci->init_state = OHCI_INIT_ALLOC_HOST;
-       host->pdev = dev;
-       pci_set_drvdata(dev, ohci);
-
-       /* We don't want hardware swapping */
-       pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
-
-       /* Some oddball Apple controllers do not order the selfid
-        * properly, so we make up for it here.  */
-#ifndef __LITTLE_ENDIAN
-       /* XXX: Need a better way to check this. I'm wondering if we can
-        * read the values of the OHCI1394_PCI_HCI_Control and the
-        * noByteSwapData registers to see if they were not cleared to
-        * zero. Should this work? Obviously it's not defined what these
-        * registers will read when they aren't supported. Bleh! */
-       if (dev->vendor == PCI_VENDOR_ID_APPLE &&
-           dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
-               ohci->no_swap_incoming = 1;
-               ohci->selfid_swap = 0;
-       } else
-               ohci->selfid_swap = 1;
-#endif
-
-
-#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e
-#endif
-
-       /* These chipsets require a bit of extra care when checking after
-        * a busreset.  */
-       if ((dev->vendor == PCI_VENDOR_ID_APPLE &&
-            dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) ||
-           (dev->vendor ==  PCI_VENDOR_ID_NVIDIA &&
-            dev->device == PCI_DEVICE_ID_NVIDIA_NFORCE2_FW))
-               ohci->check_busreset = 1;
-
-       /* We hardwire the MMIO length, since some CardBus adaptors
-        * fail to report the right length.  Anyway, the ohci spec
-        * clearly says it's 2kb, so this shouldn't be a problem. */
-       ohci_base = pci_resource_start(dev, 0);
-       if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE)
-               PRINT(KERN_WARNING, "PCI resource length of 0x%llx too small!",
-                     (unsigned long long)pci_resource_len(dev, 0));
-
-       if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
-                               OHCI1394_DRIVER_NAME)) {
-               PRINT_G(KERN_ERR, "MMIO resource (0x%llx - 0x%llx) unavailable",
-                       (unsigned long long)ohci_base,
-                       (unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
-
-       ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
-       if (ohci->registers == NULL) {
-               PRINT_G(KERN_ERR, "Failed to remap registers");
-               err = -ENXIO;
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_IOMAPPING;
-       DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers);
-
-       /* csr_config rom allocation */
-       ohci->csr_config_rom_cpu =
-               pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
-                                    &ohci->csr_config_rom_bus);
-       if (ohci->csr_config_rom_cpu == NULL) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
-
-       /* self-id dma buffer allocation */
-       ohci->selfid_buf_cpu =
-               pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
-                      &ohci->selfid_buf_bus);
-       if (ohci->selfid_buf_cpu == NULL) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
-
-       if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
-               PRINT(KERN_INFO, "SelfID buffer %p is not aligned on "
-                     "8Kb boundary... may cause problems on some CXD3222 chip",
-                     ohci->selfid_buf_cpu);
-
-       /* No self-id errors at startup */
-       ohci->self_id_errors = 0;
-
-       ohci->init_state = OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE;
-       /* AR DMA request context allocation */
-       if (alloc_dma_rcv_ctx(ohci, &ohci->ar_req_context,
-                             DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC,
-                             AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
-                             OHCI1394_AsReqRcvContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context");
-               goto err;
-       }
-       /* AR DMA response context allocation */
-       if (alloc_dma_rcv_ctx(ohci, &ohci->ar_resp_context,
-                             DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC,
-                             AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
-                             OHCI1394_AsRspRcvContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context");
-               goto err;
-       }
-       /* AT DMA request context */
-       if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context,
-                             DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC,
-                             OHCI1394_AsReqTrContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context");
-               goto err;
-       }
-       /* AT DMA response context */
-       if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context,
-                             DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC,
-                             OHCI1394_AsRspTrContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context");
-               goto err;
-       }
-       /* Start off with a soft reset, to clear everything to a sane
-        * state. */
-       ohci_soft_reset(ohci);
-
-       /* Now enable LPS, which we need in order to start accessing
-        * most of the registers.  In fact, on some cards (ALI M5251),
-        * accessing registers in the SClk domain without LPS enabled
-        * will lock up the machine. */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
-
-       /* Disable and clear interrupts */
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-
-       /* Flush MMIO writes and wait to make sure we have full link enabled. */
-       reg_read(ohci, OHCI1394_Version);
-       msleep(50);
-
-       /* Determine the number of available IR and IT contexts. */
-       ohci->nb_iso_rcv_ctx =
-               get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
-       ohci->nb_iso_xmit_ctx =
-               get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
-
-       /* Set the usage bits for non-existent contexts so they can't
-        * be allocated */
-       ohci->ir_ctx_usage = ~0 << ohci->nb_iso_rcv_ctx;
-       ohci->it_ctx_usage = ~0 << ohci->nb_iso_xmit_ctx;
-
-       INIT_LIST_HEAD(&ohci->iso_tasklet_list);
-       spin_lock_init(&ohci->iso_tasklet_list_lock);
-       ohci->ISO_channel_usage = 0;
-        spin_lock_init(&ohci->IR_channel_lock);
-
-       spin_lock_init(&ohci->event_lock);
-
-       /*
-        * interrupts are disabled, all right, but... due to IRQF_SHARED we
-        * might get called anyway.  We'll see no event, of course, but
-        * we need to get to that "no event", so enough should be initialized
-        * by that point.
-        */
-       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
-                         OHCI1394_DRIVER_NAME, ohci);
-       if (err) {
-               PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_IRQ;
-       ohci_initialize(ohci);
-
-       /* Set certain csr values */
-       host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi);
-       host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo);
-       host->csr.cyc_clk_acc = 100;  /* how do we determine clk accuracy? */
-       host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf;
-       host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
-
-       if (phys_dma) {
-               host->low_addr_space =
-                       (u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16;
-               if (!host->low_addr_space)
-                       host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED;
-       }
-       host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
-
-       /* Tell the highlevel this host is ready */
-       if (hpsb_add_host(host)) {
-               PRINT_G(KERN_ERR, "Failed to register host with highlevel");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_DONE;
-
-       return 0;
-err:
-       ohci1394_pci_remove(dev);
-       return err;
-}
-
-static void ohci1394_pci_remove(struct pci_dev *dev)
-{
-       struct ti_ohci *ohci;
-       struct device *device;
-
-       ohci = pci_get_drvdata(dev);
-       if (!ohci)
-               goto out;
-
-       device = get_device(&ohci->host->device);
-
-       switch (ohci->init_state) {
-       case OHCI_INIT_DONE:
-               hpsb_remove_host(ohci->host);
-
-               /* Clear out BUS Options */
-               reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
-               reg_write(ohci, OHCI1394_BusOptions,
-                         (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
-                         0x00ff0000);
-               memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
-
-       case OHCI_INIT_HAVE_IRQ:
-               /* Clear interrupt registers */
-               reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-
-               /* Disable IRM Contender */
-               set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
-
-               /* Clear link control register */
-               reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-
-               /* Let all other nodes know to ignore us */
-               ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-
-               /* Soft reset before we start - this disables
-                * interrupts and clears linkEnable and LPS. */
-               ohci_soft_reset(ohci);
-               free_irq(dev->irq, ohci);
-
-       case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE:
-               /* The ohci_soft_reset() stops all DMA contexts, so we
-                * dont need to do this.  */
-               free_dma_rcv_ctx(&ohci->ar_req_context);
-               free_dma_rcv_ctx(&ohci->ar_resp_context);
-               free_dma_trm_ctx(&ohci->at_req_context);
-               free_dma_trm_ctx(&ohci->at_resp_context);
-
-       case OHCI_INIT_HAVE_SELFID_BUFFER:
-               pci_free_consistent(dev, OHCI1394_SI_DMA_BUF_SIZE,
-                                   ohci->selfid_buf_cpu,
-                                   ohci->selfid_buf_bus);
-
-       case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
-               pci_free_consistent(dev, OHCI_CONFIG_ROM_LEN,
-                                   ohci->csr_config_rom_cpu,
-                                   ohci->csr_config_rom_bus);
-
-       case OHCI_INIT_HAVE_IOMAPPING:
-               iounmap(ohci->registers);
-
-       case OHCI_INIT_HAVE_MEM_REGION:
-               release_mem_region(pci_resource_start(dev, 0),
-                                  OHCI1394_REGISTER_SIZE);
-
-       case OHCI_INIT_ALLOC_HOST:
-               pci_set_drvdata(dev, NULL);
-       }
-
-       if (device)
-               put_device(device);
-out:
-       ohci1394_pmac_off(dev);
-}
-
-#ifdef CONFIG_PM
-static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       int err;
-       struct ti_ohci *ohci = pci_get_drvdata(dev);
-
-       if (!ohci) {
-               printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
-                      OHCI1394_DRIVER_NAME);
-               return -ENXIO;
-       }
-       DBGMSG("suspend called");
-
-       /* Clear the async DMA contexts and stop using the controller */
-       hpsb_bus_reset(ohci->host);
-
-       /* See ohci1394_pci_remove() for comments on this sequence */
-       reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
-       reg_write(ohci, OHCI1394_BusOptions,
-                 (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
-                 0x00ff0000);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-       set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
-       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-       ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-       ohci_soft_reset(ohci);
-
-       free_irq(dev->irq, ohci);
-       err = pci_save_state(dev);
-       if (err) {
-               PRINT(KERN_ERR, "pci_save_state failed with %d", err);
-               return err;
-       }
-       err = pci_set_power_state(dev, pci_choose_state(dev, state));
-       if (err)
-               DBGMSG("pci_set_power_state failed with %d", err);
-       ohci1394_pmac_off(dev);
-
-       return 0;
-}
-
-static int ohci1394_pci_resume(struct pci_dev *dev)
-{
-       int err;
-       struct ti_ohci *ohci = pci_get_drvdata(dev);
-
-       if (!ohci) {
-               printk(KERN_ERR "%s: tried to resume nonexisting host\n",
-                      OHCI1394_DRIVER_NAME);
-               return -ENXIO;
-       }
-       DBGMSG("resume called");
-
-       ohci1394_pmac_on(dev);
-       pci_set_power_state(dev, PCI_D0);
-       pci_restore_state(dev);
-       err = pci_enable_device(dev);
-       if (err) {
-               PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
-               return err;
-       }
-
-       /* See ohci1394_pci_probe() for comments on this sequence */
-       ohci_soft_reset(ohci);
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-       reg_read(ohci, OHCI1394_Version);
-       msleep(50);
-
-       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
-                         OHCI1394_DRIVER_NAME, ohci);
-       if (err) {
-               PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
-               return err;
-       }
-
-       ohci_initialize(ohci);
-
-       hpsb_resume_host(ohci->host);
-       return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct pci_device_id ohci1394_pci_tbl[] = {
-       {
-               .class =        PCI_CLASS_SERIAL_FIREWIRE_OHCI,
-               .class_mask =   PCI_ANY_ID,
-               .vendor =       PCI_ANY_ID,
-               .device =       PCI_ANY_ID,
-               .subvendor =    PCI_ANY_ID,
-               .subdevice =    PCI_ANY_ID,
-       },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl);
-
-static struct pci_driver ohci1394_pci_driver = {
-       .name =         OHCI1394_DRIVER_NAME,
-       .id_table =     ohci1394_pci_tbl,
-       .probe =        ohci1394_pci_probe,
-       .remove =       ohci1394_pci_remove,
-#ifdef CONFIG_PM
-       .resume =       ohci1394_pci_resume,
-       .suspend =      ohci1394_pci_suspend,
-#endif
-};
-
-/***********************************
- * OHCI1394 Video Interface        *
- ***********************************/
-
-/* essentially the only purpose of this code is to allow another
-   module to hook into ohci's interrupt handler */
-
-/* returns zero if successful, one if DMA context is locked up */
-int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
-{
-       int i=0;
-
-       /* stop the channel program if it's still running */
-       reg_write(ohci, reg, 0x8000);
-
-       /* Wait until it effectively stops */
-       while (reg_read(ohci, reg) & 0x400) {
-               i++;
-               if (i>5000) {
-                       PRINT(KERN_ERR,
-                             "Runaway loop while stopping context: %s...", msg ? msg : "");
-                       return 1;
-               }
-
-               mb();
-               udelay(10);
-       }
-       if (msg) PRINT(KERN_ERR, "%s: dma prg stopped", msg);
-       return 0;
-}
-
-void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type,
-                              void (*func)(unsigned long), unsigned long data)
-{
-       tasklet_init(&tasklet->tasklet, func, data);
-       tasklet->type = type;
-       /* We init the tasklet->link field, so we can list_del() it
-        * without worrying whether it was added to the list or not. */
-       INIT_LIST_HEAD(&tasklet->link);
-}
-
-int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
-                                 struct ohci1394_iso_tasklet *tasklet)
-{
-       unsigned long flags, *usage;
-       int n, i, r = -EBUSY;
-
-       if (tasklet->type == OHCI_ISO_TRANSMIT) {
-               n = ohci->nb_iso_xmit_ctx;
-               usage = &ohci->it_ctx_usage;
-       }
-       else {
-               n = ohci->nb_iso_rcv_ctx;
-               usage = &ohci->ir_ctx_usage;
-
-               /* only one receive context can be multichannel (OHCI sec 10.4.1) */
-               if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
-                       if (test_and_set_bit(0, &ohci->ir_multichannel_used)) {
-                               return r;
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       for (i = 0; i < n; i++)
-               if (!test_and_set_bit(i, usage)) {
-                       tasklet->context = i;
-                       list_add_tail(&tasklet->link, &ohci->iso_tasklet_list);
-                       r = 0;
-                       break;
-               }
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-
-       return r;
-}
-
-void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
-                                    struct ohci1394_iso_tasklet *tasklet)
-{
-       unsigned long flags;
-
-       tasklet_kill(&tasklet->tasklet);
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       if (tasklet->type == OHCI_ISO_TRANSMIT)
-               clear_bit(tasklet->context, &ohci->it_ctx_usage);
-       else {
-               clear_bit(tasklet->context, &ohci->ir_ctx_usage);
-
-               if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
-                       clear_bit(0, &ohci->ir_multichannel_used);
-               }
-       }
-
-       list_del(&tasklet->link);
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-}
-
-EXPORT_SYMBOL(ohci1394_stop_context);
-EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
-EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
-EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
-
-/***********************************
- * General module initialization   *
- ***********************************/
-
-MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
-MODULE_DESCRIPTION("Driver for PCI OHCI IEEE-1394 controllers");
-MODULE_LICENSE("GPL");
-
-static void __exit ohci1394_cleanup (void)
-{
-       pci_unregister_driver(&ohci1394_pci_driver);
-}
-
-static int __init ohci1394_init(void)
-{
-       return pci_register_driver(&ohci1394_pci_driver);
-}
-
-module_init(ohci1394_init);
-module_exit(ohci1394_cleanup);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
deleted file mode 100644 (file)
index 7fb8ab9..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * ohci1394.h - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Gord Peters <GordPeters@smarttech.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.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _OHCI1394_H
-#define _OHCI1394_H
-
-#include "ieee1394_types.h"
-#include <asm/io.h>
-
-#define OHCI1394_DRIVER_NAME      "ohci1394"
-
-#define OHCI1394_MAX_AT_REQ_RETRIES    0xf
-#define OHCI1394_MAX_AT_RESP_RETRIES   0x2
-#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
-#define OHCI1394_MAX_SELF_ID_ERRORS    16
-
-#define AR_REQ_NUM_DESC                4               /* number of AR req descriptors */
-#define AR_REQ_BUF_SIZE                PAGE_SIZE       /* size of AR req buffers */
-#define AR_REQ_SPLIT_BUF_SIZE  PAGE_SIZE       /* split packet buffer */
-
-#define AR_RESP_NUM_DESC       4               /* number of AR resp descriptors */
-#define AR_RESP_BUF_SIZE       PAGE_SIZE       /* size of AR resp buffers */
-#define AR_RESP_SPLIT_BUF_SIZE PAGE_SIZE       /* split packet buffer */
-
-#define IR_NUM_DESC            16              /* number of IR descriptors */
-#define IR_BUF_SIZE            PAGE_SIZE       /* 4096 bytes/buffer */
-#define IR_SPLIT_BUF_SIZE      PAGE_SIZE       /* split packet buffer */
-
-#define IT_NUM_DESC            16      /* number of IT descriptors */
-
-#define AT_REQ_NUM_DESC                32      /* number of AT req descriptors */
-#define AT_RESP_NUM_DESC       32      /* number of AT resp descriptors */
-
-#define OHCI_LOOP_COUNT                100     /* Number of loops for reg read waits */
-
-#define OHCI_CONFIG_ROM_LEN    1024    /* Length of the mapped configrom space */
-
-#define OHCI1394_SI_DMA_BUF_SIZE       8192 /* length of the selfid buffer */
-
-/* PCI configuration space addresses */
-#define OHCI1394_PCI_HCI_Control 0x40
-
-struct dma_cmd {
-        u32 control;
-        u32 address;
-        u32 branchAddress;
-        u32 status;
-};
-
-/*
- * FIXME:
- * It is important that a single at_dma_prg does not cross a page boundary
- * The proper way to do it would be to do the check dynamically as the
- * programs are inserted into the AT fifo.
- */
-struct at_dma_prg {
-       struct dma_cmd begin;
-       quadlet_t data[4];
-       struct dma_cmd end;
-       quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
-};
-
-/* identify whether a DMA context is asynchronous or isochronous */
-enum context_type { DMA_CTX_ASYNC_REQ, DMA_CTX_ASYNC_RESP, DMA_CTX_ISO };
-
-/* DMA receive context */
-struct dma_rcv_ctx {
-       struct ti_ohci *ohci;
-       enum context_type type;
-       int ctx;
-       unsigned int num_desc;
-
-       unsigned int buf_size;
-       unsigned int split_buf_size;
-
-       /* dma block descriptors */
-        struct dma_cmd **prg_cpu;
-        dma_addr_t *prg_bus;
-       struct pci_pool *prg_pool;
-
-       /* dma buffers */
-        quadlet_t **buf_cpu;
-        dma_addr_t *buf_bus;
-
-        unsigned int buf_ind;
-        unsigned int buf_offset;
-        quadlet_t *spb;
-        spinlock_t lock;
-        struct tasklet_struct task;
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-       int ctxtMatch;
-};
-
-/* DMA transmit context */
-struct dma_trm_ctx {
-       struct ti_ohci *ohci;
-       enum context_type type;
-       int ctx;
-       unsigned int num_desc;
-
-       /* dma block descriptors */
-        struct at_dma_prg **prg_cpu;
-       dma_addr_t *prg_bus;
-       struct pci_pool *prg_pool;
-
-        unsigned int prg_ind;
-        unsigned int sent_ind;
-       int free_prgs;
-        quadlet_t *branchAddrPtr;
-
-       /* list of packets inserted in the AT FIFO */
-       struct list_head fifo_list;
-
-       /* list of pending packets to be inserted in the AT FIFO */
-       struct list_head pending_list;
-
-        spinlock_t lock;
-        struct tasklet_struct task;
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-};
-
-struct ohci1394_iso_tasklet {
-       struct tasklet_struct tasklet;
-       struct list_head link;
-       int context;
-       enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE,
-              OHCI_ISO_MULTICHANNEL_RECEIVE } type;
-};
-
-struct ti_ohci {
-        struct pci_dev *dev;
-
-       enum {
-               OHCI_INIT_ALLOC_HOST,
-               OHCI_INIT_HAVE_MEM_REGION,
-               OHCI_INIT_HAVE_IOMAPPING,
-               OHCI_INIT_HAVE_CONFIG_ROM_BUFFER,
-               OHCI_INIT_HAVE_SELFID_BUFFER,
-               OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE,
-               OHCI_INIT_HAVE_IRQ,
-               OHCI_INIT_DONE,
-       } init_state;
-
-        /* remapped memory spaces */
-        void __iomem *registers;
-
-       /* dma buffer for self-id packets */
-        quadlet_t *selfid_buf_cpu;
-        dma_addr_t selfid_buf_bus;
-
-       /* buffer for csr config rom */
-        quadlet_t *csr_config_rom_cpu;
-        dma_addr_t csr_config_rom_bus;
-       int csr_config_rom_length;
-
-       unsigned int max_packet_size;
-
-        /* async receive */
-       struct dma_rcv_ctx ar_resp_context;
-       struct dma_rcv_ctx ar_req_context;
-
-       /* async transmit */
-       struct dma_trm_ctx at_resp_context;
-       struct dma_trm_ctx at_req_context;
-
-        /* iso receive */
-       int nb_iso_rcv_ctx;
-       unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */
-       unsigned long ir_multichannel_used; /* ditto */
-        spinlock_t IR_channel_lock;
-
-        /* iso transmit */
-       int nb_iso_xmit_ctx;
-       unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
-
-        u64 ISO_channel_usage;
-
-        /* IEEE-1394 part follows */
-        struct hpsb_host *host;
-
-        int phyid, isroot;
-
-        spinlock_t phy_reg_lock;
-       spinlock_t event_lock;
-
-       int self_id_errors;
-
-       /* Tasklets for iso receive and transmit, used by video1394
-        * and dv1394 */
-       struct list_head iso_tasklet_list;
-       spinlock_t iso_tasklet_list_lock;
-
-       /* Swap the selfid buffer? */
-       unsigned int selfid_swap:1;
-       /* Some Apple chipset seem to swap incoming headers for us */
-       unsigned int no_swap_incoming:1;
-
-       /* Force extra paranoia checking on bus-reset handling */
-       unsigned int check_busreset:1;
-};
-
-static inline int cross_bound(unsigned long addr, unsigned int size)
-{
-       if (size == 0)
-               return 0;
-
-       if (size > PAGE_SIZE)
-               return 1;
-
-       if (addr >> PAGE_SHIFT != (addr + size - 1) >> PAGE_SHIFT)
-               return 1;
-
-       return 0;
-}
-
-/*
- * Register read and write helper functions.
- */
-static inline void reg_write(const struct ti_ohci *ohci, int offset, u32 data)
-{
-        writel(data, ohci->registers + offset);
-}
-
-static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
-{
-        return readl(ohci->registers + offset);
-}
-
-
-/* 2 KiloBytes of register space */
-#define OHCI1394_REGISTER_SIZE                0x800
-
-/* Offsets relative to context bases defined below */
-
-#define OHCI1394_ContextControlSet            0x000
-#define OHCI1394_ContextControlClear          0x004
-#define OHCI1394_ContextCommandPtr            0x00C
-
-/* register map */
-#define OHCI1394_Version                      0x000
-#define OHCI1394_GUID_ROM                     0x004
-#define OHCI1394_ATRetries                    0x008
-#define OHCI1394_CSRData                      0x00C
-#define OHCI1394_CSRCompareData               0x010
-#define OHCI1394_CSRControl                   0x014
-#define OHCI1394_ConfigROMhdr                 0x018
-#define OHCI1394_BusID                        0x01C
-#define OHCI1394_BusOptions                   0x020
-#define OHCI1394_GUIDHi                       0x024
-#define OHCI1394_GUIDLo                       0x028
-#define OHCI1394_ConfigROMmap                 0x034
-#define OHCI1394_PostedWriteAddressLo         0x038
-#define OHCI1394_PostedWriteAddressHi         0x03C
-#define OHCI1394_VendorID                     0x040
-#define OHCI1394_HCControlSet                 0x050
-#define OHCI1394_HCControlClear               0x054
-#define  OHCI1394_HCControl_noByteSwap         0x40000000
-#define  OHCI1394_HCControl_programPhyEnable   0x00800000
-#define  OHCI1394_HCControl_aPhyEnhanceEnable  0x00400000
-#define  OHCI1394_HCControl_LPS                        0x00080000
-#define  OHCI1394_HCControl_postedWriteEnable  0x00040000
-#define  OHCI1394_HCControl_linkEnable         0x00020000
-#define  OHCI1394_HCControl_softReset          0x00010000
-#define OHCI1394_SelfIDBuffer                 0x064
-#define OHCI1394_SelfIDCount                  0x068
-#define OHCI1394_IRMultiChanMaskHiSet         0x070
-#define OHCI1394_IRMultiChanMaskHiClear       0x074
-#define OHCI1394_IRMultiChanMaskLoSet         0x078
-#define OHCI1394_IRMultiChanMaskLoClear       0x07C
-#define OHCI1394_IntEventSet                  0x080
-#define OHCI1394_IntEventClear                0x084
-#define OHCI1394_IntMaskSet                   0x088
-#define OHCI1394_IntMaskClear                 0x08C
-#define OHCI1394_IsoXmitIntEventSet           0x090
-#define OHCI1394_IsoXmitIntEventClear         0x094
-#define OHCI1394_IsoXmitIntMaskSet            0x098
-#define OHCI1394_IsoXmitIntMaskClear          0x09C
-#define OHCI1394_IsoRecvIntEventSet           0x0A0
-#define OHCI1394_IsoRecvIntEventClear         0x0A4
-#define OHCI1394_IsoRecvIntMaskSet            0x0A8
-#define OHCI1394_IsoRecvIntMaskClear          0x0AC
-#define OHCI1394_InitialBandwidthAvailable    0x0B0
-#define OHCI1394_InitialChannelsAvailableHi   0x0B4
-#define OHCI1394_InitialChannelsAvailableLo   0x0B8
-#define OHCI1394_FairnessControl              0x0DC
-#define OHCI1394_LinkControlSet               0x0E0
-#define OHCI1394_LinkControlClear             0x0E4
-#define  OHCI1394_LinkControl_RcvSelfID                0x00000200
-#define  OHCI1394_LinkControl_RcvPhyPkt                0x00000400
-#define  OHCI1394_LinkControl_CycleTimerEnable 0x00100000
-#define  OHCI1394_LinkControl_CycleMaster      0x00200000
-#define  OHCI1394_LinkControl_CycleSource      0x00400000
-#define OHCI1394_NodeID                       0x0E8
-#define OHCI1394_PhyControl                   0x0EC
-#define OHCI1394_IsochronousCycleTimer        0x0F0
-#define OHCI1394_AsReqFilterHiSet             0x100
-#define OHCI1394_AsReqFilterHiClear           0x104
-#define OHCI1394_AsReqFilterLoSet             0x108
-#define OHCI1394_AsReqFilterLoClear           0x10C
-#define OHCI1394_PhyReqFilterHiSet            0x110
-#define OHCI1394_PhyReqFilterHiClear          0x114
-#define OHCI1394_PhyReqFilterLoSet            0x118
-#define OHCI1394_PhyReqFilterLoClear          0x11C
-#define OHCI1394_PhyUpperBound                0x120
-
-#define OHCI1394_AsReqTrContextBase           0x180
-#define OHCI1394_AsReqTrContextControlSet     0x180
-#define OHCI1394_AsReqTrContextControlClear   0x184
-#define OHCI1394_AsReqTrCommandPtr            0x18C
-
-#define OHCI1394_AsRspTrContextBase           0x1A0
-#define OHCI1394_AsRspTrContextControlSet     0x1A0
-#define OHCI1394_AsRspTrContextControlClear   0x1A4
-#define OHCI1394_AsRspTrCommandPtr            0x1AC
-
-#define OHCI1394_AsReqRcvContextBase          0x1C0
-#define OHCI1394_AsReqRcvContextControlSet    0x1C0
-#define OHCI1394_AsReqRcvContextControlClear  0x1C4
-#define OHCI1394_AsReqRcvCommandPtr           0x1CC
-
-#define OHCI1394_AsRspRcvContextBase          0x1E0
-#define OHCI1394_AsRspRcvContextControlSet    0x1E0
-#define OHCI1394_AsRspRcvContextControlClear  0x1E4
-#define OHCI1394_AsRspRcvCommandPtr           0x1EC
-
-/* Isochronous transmit registers */
-/* Add (16 * n) for context n */
-#define OHCI1394_IsoXmitContextBase           0x200
-#define OHCI1394_IsoXmitContextControlSet     0x200
-#define OHCI1394_IsoXmitContextControlClear   0x204
-#define OHCI1394_IsoXmitCommandPtr            0x20C
-
-/* Isochronous receive registers */
-/* Add (32 * n) for context n */
-#define OHCI1394_IsoRcvContextBase            0x400
-#define OHCI1394_IsoRcvContextControlSet      0x400
-#define OHCI1394_IsoRcvContextControlClear    0x404
-#define OHCI1394_IsoRcvCommandPtr             0x40C
-#define OHCI1394_IsoRcvContextMatch           0x410
-
-/* Interrupts Mask/Events */
-
-#define OHCI1394_reqTxComplete           0x00000001
-#define OHCI1394_respTxComplete          0x00000002
-#define OHCI1394_ARRQ                    0x00000004
-#define OHCI1394_ARRS                    0x00000008
-#define OHCI1394_RQPkt                   0x00000010
-#define OHCI1394_RSPkt                   0x00000020
-#define OHCI1394_isochTx                 0x00000040
-#define OHCI1394_isochRx                 0x00000080
-#define OHCI1394_postedWriteErr          0x00000100
-#define OHCI1394_lockRespErr             0x00000200
-#define OHCI1394_selfIDComplete          0x00010000
-#define OHCI1394_busReset                0x00020000
-#define OHCI1394_phy                     0x00080000
-#define OHCI1394_cycleSynch              0x00100000
-#define OHCI1394_cycle64Seconds          0x00200000
-#define OHCI1394_cycleLost               0x00400000
-#define OHCI1394_cycleInconsistent       0x00800000
-#define OHCI1394_unrecoverableError      0x01000000
-#define OHCI1394_cycleTooLong            0x02000000
-#define OHCI1394_phyRegRcvd              0x04000000
-#define OHCI1394_masterIntEnable         0x80000000
-
-/* DMA Control flags */
-#define DMA_CTL_OUTPUT_MORE              0x00000000
-#define DMA_CTL_OUTPUT_LAST              0x10000000
-#define DMA_CTL_INPUT_MORE               0x20000000
-#define DMA_CTL_INPUT_LAST               0x30000000
-#define DMA_CTL_UPDATE                   0x08000000
-#define DMA_CTL_IMMEDIATE                0x02000000
-#define DMA_CTL_IRQ                      0x00300000
-#define DMA_CTL_BRANCH                   0x000c0000
-#define DMA_CTL_WAIT                     0x00030000
-
-/* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
-#define EVT_NO_STATUS          0x0     /* No event status */
-#define EVT_RESERVED_A         0x1     /* Reserved, not used !!! */
-#define EVT_LONG_PACKET                0x2     /* The revc data was longer than the buf */
-#define EVT_MISSING_ACK                0x3     /* A subaction gap was detected before an ack
-                                          arrived, or recv'd ack had a parity error */
-#define EVT_UNDERRUN           0x4     /* Underrun on corresponding FIFO, packet
-                                          truncated */
-#define EVT_OVERRUN            0x5     /* A recv FIFO overflowed on reception of ISO
-                                          packet */
-#define EVT_DESCRIPTOR_READ    0x6     /* An unrecoverable error occurred while host was
-                                          reading a descriptor block */
-#define EVT_DATA_READ          0x7     /* An error occurred while host controller was
-                                          attempting to read from host memory in the data
-                                          stage of descriptor processing */
-#define EVT_DATA_WRITE         0x8     /* An error occurred while host controller was
-                                          attempting to write either during the data stage
-                                          of descriptor processing, or when processing a single
-                                          16-bit host memory write */
-#define EVT_BUS_RESET          0x9     /* Identifies a PHY packet in the recv buffer as
-                                          being a synthesized bus reset packet */
-#define EVT_TIMEOUT            0xa     /* Indicates that the asynchronous transmit response
-                                          packet expired and was not transmitted, or that an
-                                          IT DMA context experienced a skip processing overflow */
-#define EVT_TCODE_ERR          0xb     /* A bad tCode is associated with this packet.
-                                          The packet was flushed */
-#define EVT_RESERVED_B         0xc     /* Reserved, not used !!! */
-#define EVT_RESERVED_C         0xd     /* Reserved, not used !!! */
-#define EVT_UNKNOWN            0xe     /* An error condition has occurred that cannot be
-                                          represented by any other event codes defined herein. */
-#define EVT_FLUSHED            0xf     /* Send by the link side of output FIFO when asynchronous
-                                          packets are being flushed due to a bus reset. */
-
-#define OHCI1394_TCODE_PHY               0xE
-
-/* Node offset map (phys DMA area, posted write area).
- * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must
- * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE.
- * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are
- * constants given by the OHCI spec.
- */
-#define OHCI1394_PHYS_UPPER_BOUND_FIXED                0x000100000000ULL /* 4 GB */
-#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED   0x010000000000ULL /* 1 TB */
-#define OHCI1394_MIDDLE_ADDRESS_SPACE          0xffff00000000ULL
-
-void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet,
-                              int type,
-                              void (*func)(unsigned long),
-                              unsigned long data);
-int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
-                                 struct ohci1394_iso_tasklet *tasklet);
-void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
-                                    struct ohci1394_iso_tasklet *tasklet);
-int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg);
-struct ti_ohci *ohci1394_get_struct(int card_num);
-
-#endif
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
deleted file mode 100644 (file)
index bf47fee..0000000
+++ /dev/null
@@ -1,1554 +0,0 @@
-/*
- * pcilynx.c - Texas Instruments PCILynx driver
- * Copyright (C) 1999,2000 Andreas Bombe <andreas.bombe@munich.netsurf.de>,
- *                         Stephan Linz <linz@mazet.de>
- *                         Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        reading bus info block (containing GUID) from serial
- *            eeprom via i2c and storing it in config ROM
- *        Reworked code for initiating bus resets
- *            (long, short, with or without hold-off)
- *        Enhancements in async and iso send code
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/kdev_t.h>
-#include <linux/dma-mapping.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "pcilynx.h"
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
-/* print card specific information */
-#define PRINT(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define PRINT_GD(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
-#define PRINTD(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
-#else
-#define PRINT_GD(level, fmt, args...) do {} while (0)
-#define PRINTD(level, card, fmt, args...) do {} while (0)
-#endif
-
-
-/* Module Parameters */
-static int skip_eeprom;
-module_param(skip_eeprom, int, 0444);
-MODULE_PARM_DESC(skip_eeprom, "Use generic bus info block instead of serial eeprom (default = 0).");
-
-
-static struct hpsb_host_driver lynx_driver;
-static unsigned int card_id;
-
-
-
-/*
- * I2C stuff
- */
-
-/* the i2c stuff was inspired by i2c-philips-par.c */
-
-static void bit_setscl(void *data, int state)
-{
-       if (state) {
-                 ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000040;
-       } else {
-                 ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000040;
-       }
-       reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state);
-}
-
-static void bit_setsda(void *data, int state)
-{
-       if (state) {
-                 ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000010;
-       } else {
-                 ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000010;
-       }
-       reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state);
-}
-
-static int bit_getscl(void *data)
-{
-       return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000040;
-}
-
-static int bit_getsda(void *data)
-{
-       return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010;
-}
-
-static struct i2c_algo_bit_data bit_data = {
-       .setsda                 = bit_setsda,
-       .setscl                 = bit_setscl,
-       .getsda                 = bit_getsda,
-       .getscl                 = bit_getscl,
-       .udelay                 = 5,
-       .timeout                = 100,
-};
-
-
-/*
- * PCL handling functions.
- */
-
-static pcl_t alloc_pcl(struct ti_lynx *lynx)
-{
-        u8 m;
-        int i, j;
-
-        spin_lock(&lynx->lock);
-        /* FIXME - use ffz() to make this readable */
-        for (i = 0; i < (LOCALRAM_SIZE / 1024); i++) {
-                m = lynx->pcl_bmap[i];
-                for (j = 0; j < 8; j++) {
-                        if (m & 1<<j) {
-                                continue;
-                        }
-                        m |= 1<<j;
-                        lynx->pcl_bmap[i] = m;
-                        spin_unlock(&lynx->lock);
-                        return 8 * i + j;
-                }
-        }
-        spin_unlock(&lynx->lock);
-
-        return -1;
-}
-
-
-#if 0
-static void free_pcl(struct ti_lynx *lynx, pcl_t pclid)
-{
-        int off, bit;
-
-        off = pclid / 8;
-        bit = pclid % 8;
-
-        if (pclid < 0) {
-                return;
-        }
-
-        spin_lock(&lynx->lock);
-        if (lynx->pcl_bmap[off] & 1<<bit) {
-                lynx->pcl_bmap[off] &= ~(1<<bit);
-        } else {
-                PRINT(KERN_ERR, lynx->id,
-                      "attempted to free unallocated PCL %d", pclid);
-        }
-        spin_unlock(&lynx->lock);
-}
-
-/* functions useful for debugging */
-static void pretty_print_pcl(const struct ti_pcl *pcl)
-{
-        int i;
-
-        printk("PCL next %08x, userdata %08x, status %08x, remtrans %08x, nextbuf %08x\n",
-               pcl->next, pcl->user_data, pcl->pcl_status,
-               pcl->remaining_transfer_count, pcl->next_data_buffer);
-
-        printk("PCL");
-        for (i=0; i<13; i++) {
-                printk(" c%x:%08x d%x:%08x",
-                       i, pcl->buffer[i].control, i, pcl->buffer[i].pointer);
-                if (!(i & 0x3) && (i != 12)) printk("\nPCL");
-        }
-        printk("\n");
-}
-
-static void print_pcl(const struct ti_lynx *lynx, pcl_t pclid)
-{
-        struct ti_pcl pcl;
-
-        get_pcl(lynx, pclid, &pcl);
-        pretty_print_pcl(&pcl);
-}
-#endif
-
-
-
-/***********************************
- * IEEE-1394 functionality section *
- ***********************************/
-
-
-static int get_phy_reg(struct ti_lynx *lynx, int addr)
-{
-        int retval;
-        int i = 0;
-
-        unsigned long flags;
-
-        if (addr > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                      "%s: PHY register address %d out of range",
-                     __func__, addr);
-                return -1;
-        }
-
-        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
-
-        reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr));
-        do {
-                retval = reg_read(lynx, LINK_PHY);
-
-                if (i > 10000) {
-                        PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting",
-                             __func__);
-                        retval = -1;
-                        break;
-                }
-                i++;
-        } while ((retval & 0xf00) != LINK_PHY_RADDR(addr));
-
-        reg_write(lynx, LINK_INT_STATUS, LINK_INT_PHY_REG_RCVD);
-        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
-
-        if (retval != -1) {
-                return retval & 0xff;
-        } else {
-                return -1;
-        }
-}
-
-static int set_phy_reg(struct ti_lynx *lynx, int addr, int val)
-{
-        unsigned long flags;
-
-        if (addr > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY register address %d out of range", __func__, addr);
-                return -1;
-        }
-
-        if (val > 0xff) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY register value %d out of range", __func__, val);
-                return -1;
-        }
-
-        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
-
-        reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(addr)
-                  | LINK_PHY_WDATA(val));
-
-        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
-
-        return 0;
-}
-
-static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
-{
-        int reg;
-
-        if (page > 7) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY page %d out of range", __func__, page);
-                return -1;
-        }
-
-        reg = get_phy_reg(lynx, 7);
-        if (reg != -1) {
-                reg &= 0x1f;
-                reg |= (page << 5);
-                set_phy_reg(lynx, 7, reg);
-                return 0;
-        } else {
-                return -1;
-        }
-}
-
-#if 0 /* not needed at this time */
-static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
-{
-        int reg;
-
-        if (port > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY port %d out of range", __func__, port);
-                return -1;
-        }
-
-        reg = get_phy_reg(lynx, 7);
-        if (reg != -1) {
-                reg &= 0xf0;
-                reg |= port;
-                set_phy_reg(lynx, 7, reg);
-                return 0;
-        } else {
-                return -1;
-        }
-}
-#endif
-
-static u32 get_phy_vendorid(struct ti_lynx *lynx)
-{
-        u32 pvid = 0;
-        sel_phy_reg_page(lynx, 1);
-        pvid |= (get_phy_reg(lynx, 10) << 16);
-        pvid |= (get_phy_reg(lynx, 11) << 8);
-        pvid |= get_phy_reg(lynx, 12);
-        PRINT(KERN_INFO, lynx->id, "PHY vendor id 0x%06x", pvid);
-        return pvid;
-}
-
-static u32 get_phy_productid(struct ti_lynx *lynx)
-{
-        u32 id = 0;
-        sel_phy_reg_page(lynx, 1);
-        id |= (get_phy_reg(lynx, 13) << 16);
-        id |= (get_phy_reg(lynx, 14) << 8);
-        id |= get_phy_reg(lynx, 15);
-        PRINT(KERN_INFO, lynx->id, "PHY product id 0x%06x", id);
-        return id;
-}
-
-static quadlet_t generate_own_selfid(struct ti_lynx *lynx,
-                                     struct hpsb_host *host)
-{
-        quadlet_t lsid;
-        char phyreg[7];
-        int i;
-
-        phyreg[0] = lynx->phy_reg0;
-        for (i = 1; i < 7; i++) {
-                phyreg[i] = get_phy_reg(lynx, i);
-        }
-
-        /* FIXME? We assume a TSB21LV03A phy here.  This code doesn't support
-           more than 3 ports on the PHY anyway. */
-
-        lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
-        lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
-        lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
-       if (!hpsb_disable_irm)
-               lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
-        /* lsid |= 1 << 11; *//* set contender (hack) */
-        lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
-
-        for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */
-                if (phyreg[3 + i] & 0x4) {
-                        lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)
-                                << (6 - i*2);
-                } else {
-                        lsid |= 1 << (6 - i*2);
-                }
-        }
-
-        cpu_to_be32s(&lsid);
-        PRINT(KERN_DEBUG, lynx->id, "generated own selfid 0x%x", lsid);
-        return lsid;
-}
-
-static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host)
-{
-        quadlet_t *q = lynx->rcv_page;
-        int phyid, isroot, size;
-        quadlet_t lsid = 0;
-        int i;
-
-        if (lynx->phy_reg0 == -1 || lynx->selfid_size == -1) return;
-
-        size = lynx->selfid_size;
-        phyid = lynx->phy_reg0;
-
-        i = (size > 16 ? 16 : size) / 4 - 1;
-        while (i >= 0) {
-                cpu_to_be32s(&q[i]);
-                i--;
-        }
-
-        if (!lynx->phyic.reg_1394a) {
-                lsid = generate_own_selfid(lynx, host);
-        }
-
-        isroot = (phyid & 2) != 0;
-        phyid >>= 2;
-        PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)",
-              phyid, (isroot ? "root" : "not root"));
-        reg_write(lynx, LINK_ID, (0xffc0 | phyid) << 16);
-
-        if (!lynx->phyic.reg_1394a && !size) {
-                hpsb_selfid_received(host, lsid);
-        }
-
-        while (size > 0) {
-                struct selfid *sid = (struct selfid *)q;
-
-                if (!lynx->phyic.reg_1394a && !sid->extended
-                    && (sid->phy_id == (phyid + 1))) {
-                        hpsb_selfid_received(host, lsid);
-                }
-
-                if (q[0] == ~q[1]) {
-                        PRINT(KERN_DEBUG, lynx->id, "SelfID packet 0x%x rcvd",
-                              q[0]);
-                        hpsb_selfid_received(host, q[0]);
-                } else {
-                        PRINT(KERN_INFO, lynx->id,
-                              "inconsistent selfid 0x%x/0x%x", q[0], q[1]);
-                }
-                q += 2;
-                size -= 8;
-        }
-
-        if (!lynx->phyic.reg_1394a && isroot && phyid != 0) {
-                hpsb_selfid_received(host, lsid);
-        }
-
-        hpsb_selfid_complete(host, phyid, isroot);
-
-        if (host->in_bus_reset) return; /* in bus reset again */
-
-        if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here
-        reg_set_bits(lynx, LINK_CONTROL,
-                     LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN
-                     | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN);
-}
-
-
-
-/* This must be called with the respective queue_lock held. */
-static void send_next(struct ti_lynx *lynx, int what)
-{
-        struct ti_pcl pcl;
-        struct lynx_send_data *d;
-        struct hpsb_packet *packet;
-
-#if 0 /* has been removed from ieee1394 core */
-        d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
-#else
-       d = &lynx->async;
-#endif
-        if (!list_empty(&d->pcl_queue)) {
-                PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
-                BUG();
-        }
-
-        packet = driver_packet(d->queue.next);
-       list_move_tail(&packet->driver_list, &d->pcl_queue);
-
-        d->header_dma = pci_map_single(lynx->dev, packet->header,
-                                       packet->header_size, PCI_DMA_TODEVICE);
-        if (packet->data_size) {
-                d->data_dma = pci_map_single(lynx->dev, packet->data,
-                                             packet->data_size,
-                                             PCI_DMA_TODEVICE);
-        } else {
-                d->data_dma = 0;
-        }
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        pcl.pcl_status = 0;
-        pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
-#ifndef __BIG_ENDIAN
-        pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-        pcl.buffer[0].pointer = d->header_dma;
-        pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;
-        pcl.buffer[1].pointer = d->data_dma;
-
-        switch (packet->type) {
-        case hpsb_async:
-                pcl.buffer[0].control |= PCL_CMD_XMT;
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case hpsb_iso:
-                pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
-                break;
-#endif
-        case hpsb_raw:
-                pcl.buffer[0].control |= PCL_CMD_UNFXMT;
-                break;
-        }
-
-        put_pcl(lynx, d->pcl, &pcl);
-        run_pcl(lynx, d->pcl_start, d->channel);
-}
-
-
-/* called from subsystem core */
-static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
-{
-        struct ti_lynx *lynx = host->hostdata;
-        struct lynx_send_data *d;
-        unsigned long flags;
-
-        if (packet->data_size >= 4096) {
-                PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)",
-                      packet->data_size);
-                return -EOVERFLOW;
-        }
-
-        switch (packet->type) {
-        case hpsb_async:
-        case hpsb_raw:
-                d = &lynx->async;
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case hpsb_iso:
-                d = &lynx->iso_send;
-                break;
-#endif
-        default:
-                PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
-                      packet->type);
-                return -EINVAL;
-        }
-
-        if (packet->tcode == TCODE_WRITEQ
-            || packet->tcode == TCODE_READQ_RESPONSE) {
-                cpu_to_be32s(&packet->header[3]);
-        }
-
-        spin_lock_irqsave(&d->queue_lock, flags);
-
-       list_add_tail(&packet->driver_list, &d->queue);
-       if (list_empty(&d->pcl_queue))
-                send_next(lynx, packet->type);
-
-        spin_unlock_irqrestore(&d->queue_lock, flags);
-
-        return 0;
-}
-
-
-/* called from subsystem core */
-static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
-{
-        struct ti_lynx *lynx = host->hostdata;
-        int retval = 0;
-        struct hpsb_packet *packet;
-       LIST_HEAD(packet_list);
-        unsigned long flags;
-       int phy_reg;
-
-        switch (cmd) {
-        case RESET_BUS:
-                if (reg_read(lynx, LINK_INT_STATUS) & LINK_INT_PHY_BUSRESET) {
-                        retval = 0;
-                        break;
-                }
-
-               switch (arg) {
-               case SHORT_RESET:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg |= 0x40;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_NO_FORCE_ROOT:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 1);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               if (phy_reg & 0x80) {
-                                       phy_reg &= ~0x80;
-                                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB */
-                               }
-
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg &= ~0x80;
-                       phy_reg |= 0x40;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_FORCE_ROOT:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 1);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               if (!(phy_reg & 0x80)) {
-                                       phy_reg |= 0x80;
-                                       set_phy_reg(lynx, 1, phy_reg); /* set RHB */
-                               }
-
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg |= 0xc0;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */
-                       break;
-               default:
-                       PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg);
-                       retval = -1;
-               }
-
-                break;
-
-        case GET_CYCLE_COUNTER:
-                retval = reg_read(lynx, CYCLE_TIMER);
-                break;
-
-        case SET_CYCLE_COUNTER:
-                reg_write(lynx, CYCLE_TIMER, arg);
-                break;
-
-        case SET_BUS_ID:
-                reg_write(lynx, LINK_ID,
-                          (arg << 22) | (reg_read(lynx, LINK_ID) & 0x003f0000));
-                break;
-
-        case ACT_CYCLE_MASTER:
-                if (arg) {
-                        reg_set_bits(lynx, LINK_CONTROL,
-                                     LINK_CONTROL_CYCMASTER);
-                } else {
-                        reg_clear_bits(lynx, LINK_CONTROL,
-                                       LINK_CONTROL_CYCMASTER);
-                }
-                break;
-
-        case CANCEL_REQUESTS:
-                spin_lock_irqsave(&lynx->async.queue_lock, flags);
-
-                reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
-               list_splice_init(&lynx->async.queue, &packet_list);
-
-                if (list_empty(&lynx->async.pcl_queue)) {
-                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
-                        PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-
-                        PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL");
-
-                        get_pcl(lynx, lynx->async.pcl, &pcl);
-
-                        packet = driver_packet(lynx->async.pcl_queue.next);
-                       list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-
-                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
-                                ack = ACKX_ABORTED;
-                        }
-                        hpsb_packet_sent(host, packet, ack);
-                }
-
-               while (!list_empty(&packet_list)) {
-                       packet = driver_packet(packet_list.next);
-                       list_del_init(&packet->driver_list);
-                       hpsb_packet_sent(host, packet, ACKX_ABORTED);
-               }
-
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case ISO_LISTEN_CHANNEL:
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-                if (lynx->iso_rcv.chan_count++ == 0) {
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                                  DMA_WORD1_CMP_ENABLE_MASTER);
-                }
-
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-                break;
-
-        case ISO_UNLISTEN_CHANNEL:
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-                if (--lynx->iso_rcv.chan_count == 0) {
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                                  0);
-                }
-
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-                break;
-#endif
-        default:
-                PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
-                retval = -1;
-        }
-
-        return retval;
-}
-
-
-/***************************************
- * IEEE-1394 functionality section END *
- ***************************************/
-
-
-/********************************************************
- * Global stuff (interrupt handler, init/shutdown code) *
- ********************************************************/
-
-
-static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
-{
-        struct ti_lynx *lynx = (struct ti_lynx *)dev_id;
-        struct hpsb_host *host = lynx->host;
-        u32 intmask;
-        u32 linkint;
-
-        linkint = reg_read(lynx, LINK_INT_STATUS);
-        intmask = reg_read(lynx, PCI_INT_STATUS);
-
-        if (!(intmask & PCI_INT_INT_PEND))
-               return IRQ_NONE;
-
-        PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask,
-               linkint);
-
-        reg_write(lynx, LINK_INT_STATUS, linkint);
-        reg_write(lynx, PCI_INT_STATUS, intmask);
-
-        if (intmask & PCI_INT_1394) {
-                if (linkint & LINK_INT_PHY_TIMEOUT) {
-                        PRINT(KERN_INFO, lynx->id, "PHY timeout occurred");
-                }
-                if (linkint & LINK_INT_PHY_BUSRESET) {
-                        PRINT(KERN_INFO, lynx->id, "bus reset interrupt");
-                        lynx->selfid_size = -1;
-                        lynx->phy_reg0 = -1;
-                        if (!host->in_bus_reset)
-                                hpsb_bus_reset(host);
-                }
-                if (linkint & LINK_INT_PHY_REG_RCVD) {
-                        u32 reg;
-
-                        spin_lock(&lynx->phy_reg_lock);
-                        reg = reg_read(lynx, LINK_PHY);
-                        spin_unlock(&lynx->phy_reg_lock);
-
-                        if (!host->in_bus_reset) {
-                                PRINT(KERN_INFO, lynx->id,
-                                      "phy reg received without reset");
-                        } else if (reg & 0xf00) {
-                                PRINT(KERN_INFO, lynx->id,
-                                      "unsolicited phy reg %d received",
-                                      (reg >> 8) & 0xf);
-                        } else {
-                                lynx->phy_reg0 = reg & 0xff;
-                                handle_selfid(lynx, host);
-                        }
-                }
-                if (linkint & LINK_INT_ISO_STUCK) {
-                        PRINT(KERN_INFO, lynx->id, "isochronous transmitter stuck");
-                }
-                if (linkint & LINK_INT_ASYNC_STUCK) {
-                        PRINT(KERN_INFO, lynx->id, "asynchronous transmitter stuck");
-                }
-                if (linkint & LINK_INT_SENT_REJECT) {
-                        PRINT(KERN_INFO, lynx->id, "sent reject");
-                }
-                if (linkint & LINK_INT_TX_INVALID_TC) {
-                        PRINT(KERN_INFO, lynx->id, "invalid transaction code");
-                }
-                if (linkint & LINK_INT_GRF_OVERFLOW) {
-                        /* flush FIFO if overflow happens during reset */
-                        if (host->in_bus_reset)
-                                reg_write(lynx, FIFO_CONTROL,
-                                          FIFO_CONTROL_GRF_FLUSH);
-                        PRINT(KERN_INFO, lynx->id, "GRF overflow");
-                }
-                if (linkint & LINK_INT_ITF_UNDERFLOW) {
-                        PRINT(KERN_INFO, lynx->id, "ITF underflow");
-                }
-                if (linkint & LINK_INT_ATF_UNDERFLOW) {
-                        PRINT(KERN_INFO, lynx->id, "ATF underflow");
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_RCV)) {
-                PRINTD(KERN_DEBUG, lynx->id, "iso receive");
-
-                spin_lock(&lynx->iso_rcv.lock);
-
-                lynx->iso_rcv.stat[lynx->iso_rcv.next] =
-                        reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ISO_RCV));
-
-                lynx->iso_rcv.used++;
-                lynx->iso_rcv.next = (lynx->iso_rcv.next + 1) % NUM_ISORCV_PCL;
-
-                if ((lynx->iso_rcv.next == lynx->iso_rcv.last)
-                    || !lynx->iso_rcv.chan_count) {
-                        PRINTD(KERN_DEBUG, lynx->id, "stopped");
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
-                }
-
-                run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, lynx->iso_rcv.next,
-                            CHANNEL_ISO_RCV);
-
-                spin_unlock(&lynx->iso_rcv.lock);
-
-               tasklet_schedule(&lynx->iso_rcv.tq);
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) {
-                PRINTD(KERN_DEBUG, lynx->id, "async sent");
-                spin_lock(&lynx->async.queue_lock);
-
-                if (list_empty(&lynx->async.pcl_queue)) {
-                        spin_unlock(&lynx->async.queue_lock);
-                        PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-                        struct hpsb_packet *packet;
-
-                        get_pcl(lynx, lynx->async.pcl, &pcl);
-
-                        packet = driver_packet(lynx->async.pcl_queue.next);
-                        list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-
-                        if (!list_empty(&lynx->async.queue)) {
-                                send_next(lynx, hpsb_async);
-                        }
-
-                        spin_unlock(&lynx->async.queue_lock);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
-                                ack = ACKX_SEND_ERROR;
-                        }
-                        hpsb_packet_sent(host, packet, ack);
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) {
-                PRINTD(KERN_DEBUG, lynx->id, "iso sent");
-                spin_lock(&lynx->iso_send.queue_lock);
-
-                if (list_empty(&lynx->iso_send.pcl_queue)) {
-                        spin_unlock(&lynx->iso_send.queue_lock);
-                        PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-                        struct hpsb_packet *packet;
-
-                        get_pcl(lynx, lynx->iso_send.pcl, &pcl);
-
-                        packet = driver_packet(lynx->iso_send.pcl_queue.next);
-                        list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-#if 0 /* has been removed from ieee1394 core */
-                        if (!list_empty(&lynx->iso_send.queue)) {
-                                send_next(lynx, hpsb_iso);
-                        }
-#endif
-                        spin_unlock(&lynx->iso_send.queue_lock);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "iso send packet was not completed");
-                                ack = ACKX_SEND_ERROR;
-                        }
-
-                        hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) {
-                /* general receive DMA completed */
-                int stat = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_RCV));
-
-                PRINTD(KERN_DEBUG, lynx->id, "received packet size %d",
-                       stat & 0x1fff);
-
-                if (stat & DMA_CHAN_STAT_SELFID) {
-                        lynx->selfid_size = stat & 0x1fff;
-                        handle_selfid(lynx, host);
-                } else {
-                        quadlet_t *q_data = lynx->rcv_page;
-                        if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE
-                            || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) {
-                                cpu_to_be32s(q_data + 3);
-                        }
-                        hpsb_packet_received(host, q_data, stat & 0x1fff, 0);
-                }
-
-                run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
-        }
-
-       return IRQ_HANDLED;
-}
-
-
-static void iso_rcv_bh(struct ti_lynx *lynx)
-{
-        unsigned int idx;
-        quadlet_t *data;
-        unsigned long flags;
-
-        spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-        while (lynx->iso_rcv.used) {
-                idx = lynx->iso_rcv.last;
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-
-                data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE]
-                        + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE;
-
-                if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) {
-                        PRINT(KERN_ERR, lynx->id,
-                              "iso length mismatch 0x%08x/0x%08x", *data,
-                              lynx->iso_rcv.stat[idx]);
-                }
-
-                if (lynx->iso_rcv.stat[idx]
-                    & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) {
-                        PRINT(KERN_INFO, lynx->id,
-                              "iso receive error on %d to 0x%p", idx, data);
-                } else {
-                        hpsb_packet_received(lynx->host, data,
-                                             lynx->iso_rcv.stat[idx] & 0x1fff,
-                                             0);
-                }
-
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-                lynx->iso_rcv.last = (idx + 1) % NUM_ISORCV_PCL;
-                lynx->iso_rcv.used--;
-        }
-
-        if (lynx->iso_rcv.chan_count) {
-                reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                          DMA_WORD1_CMP_ENABLE_MASTER);
-        }
-        spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-}
-
-
-static void remove_card(struct pci_dev *dev)
-{
-        struct ti_lynx *lynx;
-       struct device *lynx_dev;
-        int i;
-
-        lynx = pci_get_drvdata(dev);
-        if (!lynx) return;
-        pci_set_drvdata(dev, NULL);
-
-       lynx_dev = get_device(&lynx->host->device);
-
-        switch (lynx->state) {
-        case is_host:
-                reg_write(lynx, PCI_INT_ENABLE, 0);
-                hpsb_remove_host(lynx->host);
-        case have_intr:
-                reg_write(lynx, PCI_INT_ENABLE, 0);
-                free_irq(lynx->dev->irq, lynx);
-
-               /* Disable IRM Contender and LCtrl */
-               if (lynx->phyic.reg_1394a)
-                       set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4));
-
-               /* Let all other nodes know to ignore us */
-               lynx_devctl(lynx->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-
-        case have_iomappings:
-                reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
-                /* Fix buggy cards with autoboot pin not tied low: */
-                reg_write(lynx, DMA0_CHAN_CTRL, 0);
-                iounmap(lynx->registers);
-                iounmap(lynx->local_rom);
-                iounmap(lynx->local_ram);
-                iounmap(lynx->aux_port);
-        case have_1394_buffers:
-                for (i = 0; i < ISORCV_PAGES; i++) {
-                        if (lynx->iso_rcv.page[i]) {
-                                pci_free_consistent(lynx->dev, PAGE_SIZE,
-                                                    lynx->iso_rcv.page[i],
-                                                    lynx->iso_rcv.page_dma[i]);
-                        }
-                }
-                pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,
-                                    lynx->rcv_page_dma);
-        case have_aux_buf:
-        case have_pcl_mem:
-                pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
-                                    lynx->pcl_mem_dma);
-        case clear:
-                /* do nothing - already freed */
-                ;
-        }
-
-       tasklet_kill(&lynx->iso_rcv.tq);
-
-       if (lynx_dev)
-               put_device(lynx_dev);
-}
-
-
-static int __devinit add_card(struct pci_dev *dev,
-                              const struct pci_device_id *devid_is_unused)
-{
-#define FAIL(fmt, args...) do { \
-        PRINT_G(KERN_ERR, fmt , ## args); \
-        remove_card(dev); \
-        return error; \
-        } while (0)
-
-       char irq_buf[16];
-       struct hpsb_host *host;
-        struct ti_lynx *lynx; /* shortcut to currently handled device */
-        struct ti_pcl pcl;
-        u32 *pcli;
-        int i;
-        int error;
-
-        error = -ENXIO;
-
-        if (pci_set_dma_mask(dev, DMA_BIT_MASK(32)))
-                FAIL("DMA address limits not supported for PCILynx hardware");
-        if (pci_enable_device(dev))
-                FAIL("failed to enable PCILynx hardware");
-        pci_set_master(dev);
-
-        error = -ENOMEM;
-
-       host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev);
-        if (!host) FAIL("failed to allocate control structure memory");
-
-        lynx = host->hostdata;
-       lynx->id = card_id++;
-        lynx->dev = dev;
-        lynx->state = clear;
-       lynx->host = host;
-        host->pdev = dev;
-        pci_set_drvdata(dev, lynx);
-
-        spin_lock_init(&lynx->lock);
-        spin_lock_init(&lynx->phy_reg_lock);
-
-        lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,
-                                             &lynx->pcl_mem_dma);
-
-        if (lynx->pcl_mem != NULL) {
-                lynx->state = have_pcl_mem;
-                PRINT(KERN_INFO, lynx->id,
-                      "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE,
-                      lynx->pcl_mem);
-        } else {
-                FAIL("failed to allocate PCL memory area");
-        }
-
-        lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE,
-                                              &lynx->rcv_page_dma);
-        if (lynx->rcv_page == NULL) {
-                FAIL("failed to allocate receive buffer");
-        }
-        lynx->state = have_1394_buffers;
-
-        for (i = 0; i < ISORCV_PAGES; i++) {
-                lynx->iso_rcv.page[i] =
-                        pci_alloc_consistent(dev, PAGE_SIZE,
-                                             &lynx->iso_rcv.page_dma[i]);
-                if (lynx->iso_rcv.page[i] == NULL) {
-                        FAIL("failed to allocate iso receive buffers");
-                }
-        }
-
-        lynx->registers = ioremap_nocache(pci_resource_start(dev,0),
-                                          PCILYNX_MAX_REGISTER);
-        lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY);
-        lynx->aux_port  = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY);
-        lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE),
-                                  PCILYNX_MAX_MEMORY);
-        lynx->state = have_iomappings;
-
-        if (lynx->registers == NULL) {
-                FAIL("failed to remap registers - card not accessible");
-        }
-
-        reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
-        /* Fix buggy cards with autoboot pin not tied low: */
-        reg_write(lynx, DMA0_CHAN_CTRL, 0);
-
-       sprintf (irq_buf, "%d", dev->irq);
-
-        if (!request_irq(dev->irq, lynx_irq_handler, IRQF_SHARED,
-                         PCILYNX_DRIVER_NAME, lynx)) {
-                PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf);
-                lynx->state = have_intr;
-        } else {
-                FAIL("failed to allocate shared interrupt %s", irq_buf);
-        }
-
-        /* alloc_pcl return values are not checked, it is expected that the
-         * provided PCL space is sufficient for the initial allocations */
-        lynx->rcv_pcl = alloc_pcl(lynx);
-        lynx->rcv_pcl_start = alloc_pcl(lynx);
-        lynx->async.pcl = alloc_pcl(lynx);
-        lynx->async.pcl_start = alloc_pcl(lynx);
-        lynx->iso_send.pcl = alloc_pcl(lynx);
-        lynx->iso_send.pcl_start = alloc_pcl(lynx);
-
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);
-        }
-        lynx->iso_rcv.pcl_start = alloc_pcl(lynx);
-
-        /* all allocations successful - simple init stuff follows */
-
-        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
-
-       tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,
-                    (unsigned long)lynx);
-
-        spin_lock_init(&lynx->iso_rcv.lock);
-
-        spin_lock_init(&lynx->async.queue_lock);
-        lynx->async.channel = CHANNEL_ASYNC_SEND;
-        spin_lock_init(&lynx->iso_send.queue_lock);
-        lynx->iso_send.channel = CHANNEL_ISO_SEND;
-
-        PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, "
-              "ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom,
-              lynx->local_ram, lynx->aux_port);
-
-        /* now, looking for PHY register set */
-        if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {
-                lynx->phyic.reg_1394a = 1;
-                PRINT(KERN_INFO, lynx->id,
-                      "found 1394a conform PHY (using extended register set)");
-                lynx->phyic.vendor = get_phy_vendorid(lynx);
-                lynx->phyic.product = get_phy_productid(lynx);
-        } else {
-                lynx->phyic.reg_1394a = 0;
-                PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
-        }
-
-        lynx->selfid_size = -1;
-        lynx->phy_reg0 = -1;
-
-       INIT_LIST_HEAD(&lynx->async.queue);
-       INIT_LIST_HEAD(&lynx->async.pcl_queue);
-       INIT_LIST_HEAD(&lynx->iso_send.queue);
-       INIT_LIST_HEAD(&lynx->iso_send.pcl_queue);
-
-        pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
-        put_pcl(lynx, lynx->rcv_pcl_start, &pcl);
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-
-        pcl.buffer[0].control = PCL_CMD_RCV | 16;
-#ifndef __BIG_ENDIAN
-       pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-       pcl.buffer[1].control = PCL_LAST_BUFF | 4080;
-
-        pcl.buffer[0].pointer = lynx->rcv_page_dma;
-        pcl.buffer[1].pointer = lynx->rcv_page_dma + 16;
-        put_pcl(lynx, lynx->rcv_pcl, &pcl);
-
-        pcl.next = pcl_bus(lynx, lynx->async.pcl);
-        pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl);
-        put_pcl(lynx, lynx->async.pcl_start, &pcl);
-
-        pcl.next = pcl_bus(lynx, lynx->iso_send.pcl);
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        put_pcl(lynx, lynx->iso_send.pcl_start, &pcl);
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        pcl.buffer[0].control = PCL_CMD_RCV | 4;
-#ifndef __BIG_ENDIAN
-        pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-        pcl.buffer[1].control = PCL_LAST_BUFF | 2044;
-
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                int page = i / ISORCV_PER_PAGE;
-                int sec = i % ISORCV_PER_PAGE;
-
-                pcl.buffer[0].pointer = lynx->iso_rcv.page_dma[page]
-                        + sec * MAX_ISORCV_SIZE;
-                pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4;
-                put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl);
-        }
-
-        pcli = (u32 *)&pcl;
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                pcli[i] = pcl_bus(lynx, lynx->iso_rcv.pcl[i]);
-        }
-        put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl);
-
-        /* FIFO sizes from left to right: ITF=48 ATF=48 GRF=160 */
-        reg_write(lynx, FIFO_SIZES, 0x003030a0);
-        /* 20 byte threshold before triggering PCI transfer */
-        reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24);
-        /* threshold on both send FIFOs before transmitting:
-           FIFO size - cache line size - 1 */
-        i = reg_read(lynx, PCI_LATENCY_CACHELINE) & 0xff;
-        i = 0x30 - i - 1;
-        reg_write(lynx, FIFO_XMIT_THRESHOLD, (i << 8) | i);
-
-        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394);
-
-        reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT
-                  | LINK_INT_PHY_REG_RCVD  | LINK_INT_PHY_BUSRESET
-                  | LINK_INT_ISO_STUCK     | LINK_INT_ASYNC_STUCK
-                  | LINK_INT_SENT_REJECT   | LINK_INT_TX_INVALID_TC
-                  | LINK_INT_GRF_OVERFLOW  | LINK_INT_ITF_UNDERFLOW
-                  | LINK_INT_ATF_UNDERFLOW);
-
-        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
-        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4);
-        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
-        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV),
-                  DMA_WORD1_CMP_MATCH_LOCAL_NODE | DMA_WORD1_CMP_MATCH_BROADCAST
-                  | DMA_WORD1_CMP_MATCH_EXACT    | DMA_WORD1_CMP_MATCH_BUS_BCAST
-                  | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER);
-
-        run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
-
-        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0);
-        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4);
-        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ISO_RCV), 0);
-        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
-
-        run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, 0, CHANNEL_ISO_RCV);
-
-        reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID
-                  | LINK_CONTROL_TX_ISO_EN   | LINK_CONTROL_RX_ISO_EN
-                  | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
-                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX);
-
-       if (!lynx->phyic.reg_1394a) {
-               if (!hpsb_disable_irm) {
-                       /* attempt to enable contender bit -FIXME- would this
-                        * work elsewhere? */
-                       reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
-                       reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
-               }
-       } else {
-               /* set the contender (if appropriate) and LCtrl bit in the
-                * extended PHY register set. (Should check that PHY_02_EXTENDED
-                * is set in register 2?)
-                */
-               i = get_phy_reg(lynx, 4);
-               i |= PHY_04_LCTRL;
-               if (hpsb_disable_irm)
-                       i &= ~PHY_04_CONTENDER;
-               else
-                       i |= PHY_04_CONTENDER;
-               if (i != -1) set_phy_reg(lynx, 4, i);
-       }
-       
-        if (!skip_eeprom)
-        {
-               /* needed for i2c communication with serial eeprom */
-               struct i2c_adapter *i2c_ad;
-               struct i2c_algo_bit_data i2c_adapter_data;
-
-               error = -ENOMEM;
-               i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL);
-               if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
-
-               strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name));
-                i2c_adapter_data = bit_data;
-                i2c_ad->algo_data = &i2c_adapter_data;
-                i2c_adapter_data.data = lynx;
-               i2c_ad->dev.parent = &dev->dev;
-
-               PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
-                      reg_read(lynx, SERIAL_EEPROM_CONTROL));
-
-               /* reset hardware to sane state */
-               lynx->i2c_driven_state = 0x00000070;
-               reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state);
-
-               if (i2c_bit_add_bus(i2c_ad) < 0)
-               {
-                       kfree(i2c_ad);
-                       error = -ENXIO;
-                       FAIL("unable to register i2c");
-               }
-               else
-               {
-                        /* do i2c stuff */
-                        unsigned char i2c_cmd = 0x10;
-                        struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd },
-                                                  { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
-                                                };
-
-                       /* we use i2c_transfer because we have no i2c_client
-                          at hand */
-                        if (i2c_transfer(i2c_ad, msg, 2) < 0) {
-                                PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");
-                               /* FIXME: probably we should rewrite the max_rec, max_ROM(1394a),
-                                * generation(1394a) and link_spd(1394a) field and recalculate
-                                * the CRC */
-
-                                for (i = 0; i < 5 ; i++)
-                                        PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",
-                                              i, be32_to_cpu(lynx->bus_info_block[i]));
-
-                                /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
-                               if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&
-                                   (lynx->bus_info_block[1] == IEEE1394_BUSID_MAGIC))
-                                {
-                                        PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
-                                } else {
-                                       kfree(i2c_ad);
-                                       error = -ENXIO;
-                                       FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
-                                }
-
-                        }
-
-                       i2c_del_adapter(i2c_ad);
-                       kfree(i2c_ad);
-                }
-        }
-
-       host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]);
-       host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]);
-       host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff;
-       host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf;
-       if (!lynx->phyic.reg_1394a)
-               host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6;
-       else
-               host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
-
-       if (hpsb_add_host(host)) {
-               error = -ENOMEM;
-               FAIL("Failed to register host with highlevel");
-       }
-
-       lynx->state = is_host;
-
-       return 0;
-#undef FAIL
-}
-
-
-static struct pci_device_id pci_table[] = {
-       {
-                .vendor =    PCI_VENDOR_ID_TI,
-                .device =    PCI_DEVICE_ID_TI_PCILYNX,
-                .subvendor = PCI_ANY_ID,
-                .subdevice = PCI_ANY_ID,
-       },
-       { }                     /* Terminating entry */
-};
-
-static struct pci_driver lynx_pci_driver = {
-        .name =     PCILYNX_DRIVER_NAME,
-        .id_table = pci_table,
-        .probe =    add_card,
-        .remove =   remove_card,
-};
-
-static struct hpsb_host_driver lynx_driver = {
-       .owner =           THIS_MODULE,
-       .name =            PCILYNX_DRIVER_NAME,
-       .set_hw_config_rom = NULL,
-        .transmit_packet = lynx_transmit,
-        .devctl =          lynx_devctl,
-       .isoctl =          NULL,
-};
-
-MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>");
-MODULE_DESCRIPTION("driver for Texas Instruments PCI Lynx IEEE-1394 controller");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("pcilynx");
-MODULE_DEVICE_TABLE(pci, pci_table);
-
-static int __init pcilynx_init(void)
-{
-        int ret;
-
-        ret = pci_register_driver(&lynx_pci_driver);
-        if (ret < 0) {
-                PRINT_G(KERN_ERR, "PCI module init failed");
-                return ret;
-        }
-
-        return 0;
-}
-
-static void __exit pcilynx_cleanup(void)
-{
-        pci_unregister_driver(&lynx_pci_driver);
-}
-
-
-module_init(pcilynx_init);
-module_exit(pcilynx_cleanup);
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
deleted file mode 100644 (file)
index 693a169..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-#ifndef __PCILYNX_H__
-#define __PCILYNX_H__
-
-
-#define PCILYNX_DRIVER_NAME      "pcilynx"
-#define PCILYNX_MAJOR            177
-
-#define PCILYNX_MINOR_AUX_START  0
-#define PCILYNX_MINOR_ROM_START  16
-#define PCILYNX_MINOR_RAM_START  32
-
-#define PCILYNX_MAX_REGISTER     0xfff
-#define PCILYNX_MAX_MEMORY       0xffff
-
-#define PCI_DEVICE_ID_TI_PCILYNX 0x8000
-#define MAX_PCILYNX_CARDS        4
-#define LOCALRAM_SIZE            4096
-
-#define NUM_ISORCV_PCL           4
-#define MAX_ISORCV_SIZE          2048
-#define ISORCV_PER_PAGE          (PAGE_SIZE / MAX_ISORCV_SIZE)
-#define ISORCV_PAGES             (NUM_ISORCV_PCL / ISORCV_PER_PAGE)
-
-#define CHANNEL_LOCALBUS         0
-#define CHANNEL_ASYNC_RCV        1
-#define CHANNEL_ISO_RCV          2
-#define CHANNEL_ASYNC_SEND       3
-#define CHANNEL_ISO_SEND         4
-
-#define PCILYNX_CONFIG_ROM_LENGTH   1024
-
-typedef int pcl_t;
-
-struct ti_lynx {
-        int id; /* sequential card number */
-
-        spinlock_t lock;
-
-        struct pci_dev *dev;
-
-        struct {
-                unsigned reg_1394a:1;
-                u32 vendor;
-                u32 product;
-        } phyic;
-
-        enum { clear, have_intr, have_aux_buf, have_pcl_mem,
-               have_1394_buffers, have_iomappings, is_host } state;
-
-        /* remapped memory spaces */
-        void __iomem *registers;
-        void __iomem *local_rom;
-        void __iomem *local_ram;
-        void __iomem *aux_port;
-       __be32 bus_info_block[5];
-
-        /*
-         * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for
-         * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes);
-         * the following is an allocation bitmap
-         */
-        u8 pcl_bmap[LOCALRAM_SIZE / 1024];
-
-       /* point to PCLs memory area if needed */
-       void *pcl_mem;
-        dma_addr_t pcl_mem_dma;
-
-        /* PCLs for local mem / aux transfers */
-        pcl_t dmem_pcl;
-
-        /* IEEE-1394 part follows */
-        struct hpsb_host *host;
-
-        int phyid, isroot;
-        int selfid_size;
-        int phy_reg0;
-
-        spinlock_t phy_reg_lock;
-
-        pcl_t rcv_pcl_start, rcv_pcl;
-        void *rcv_page;
-        dma_addr_t rcv_page_dma;
-        int rcv_active;
-
-        struct lynx_send_data {
-                pcl_t pcl_start, pcl;
-                struct list_head queue;
-                struct list_head pcl_queue; /* this queue contains at most one packet */
-                spinlock_t queue_lock;
-                dma_addr_t header_dma, data_dma;
-                int channel;
-        } async, iso_send;
-
-        struct {
-                pcl_t pcl[NUM_ISORCV_PCL];
-                u32 stat[NUM_ISORCV_PCL];
-                void *page[ISORCV_PAGES];
-                dma_addr_t page_dma[ISORCV_PAGES];
-                pcl_t pcl_start;
-                int chan_count;
-                int next, last, used, running;
-                struct tasklet_struct tq;
-                spinlock_t lock;
-        } iso_rcv;
-
-       u32 i2c_driven_state; /* the state we currently drive the Serial EEPROM Control register */
-};
-
-/* the per-file data structure for mem space access */
-struct memdata {
-        struct ti_lynx *lynx;
-        int cid;
-        atomic_t aux_intr_last_seen;
-       /* enum values are the same as LBUS_ADDR_SEL_* values below */
-        enum { rom = 0x10000, aux = 0x20000, ram = 0 } type;
-};
-
-
-
-/*
- * Register read and write helper functions.
- */
-static inline void reg_write(const struct ti_lynx *lynx, int offset, u32 data)
-{
-        writel(data, lynx->registers + offset);
-}
-
-static inline u32 reg_read(const struct ti_lynx *lynx, int offset)
-{
-        return readl(lynx->registers + offset);
-}
-
-static inline void reg_set_bits(const struct ti_lynx *lynx, int offset,
-                                u32 mask)
-{
-        reg_write(lynx, offset, (reg_read(lynx, offset) | mask));
-}
-
-static inline void reg_clear_bits(const struct ti_lynx *lynx, int offset,
-                                  u32 mask)
-{
-        reg_write(lynx, offset, (reg_read(lynx, offset) & ~mask));
-}
-
-
-
-/* chip register definitions follow */
-
-#define PCI_LATENCY_CACHELINE             0x0c
-
-#define MISC_CONTROL                      0x40
-#define MISC_CONTROL_SWRESET              (1<<0)
-
-#define SERIAL_EEPROM_CONTROL             0x44
-
-#define PCI_INT_STATUS                    0x48
-#define PCI_INT_ENABLE                    0x4c
-/* status and enable have identical bit numbers */
-#define PCI_INT_INT_PEND                  (1<<31)
-#define PCI_INT_FORCED_INT                (1<<30)
-#define PCI_INT_SLV_ADR_PERR              (1<<28)
-#define PCI_INT_SLV_DAT_PERR              (1<<27)
-#define PCI_INT_MST_DAT_PERR              (1<<26)
-#define PCI_INT_MST_DEV_TIMEOUT           (1<<25)
-#define PCI_INT_INTERNAL_SLV_TIMEOUT      (1<<23)
-#define PCI_INT_AUX_TIMEOUT               (1<<18)
-#define PCI_INT_AUX_INT                   (1<<17)
-#define PCI_INT_1394                      (1<<16)
-#define PCI_INT_DMA4_PCL                  (1<<9)
-#define PCI_INT_DMA4_HLT                  (1<<8)
-#define PCI_INT_DMA3_PCL                  (1<<7)
-#define PCI_INT_DMA3_HLT                  (1<<6)
-#define PCI_INT_DMA2_PCL                  (1<<5)
-#define PCI_INT_DMA2_HLT                  (1<<4)
-#define PCI_INT_DMA1_PCL                  (1<<3)
-#define PCI_INT_DMA1_HLT                  (1<<2)
-#define PCI_INT_DMA0_PCL                  (1<<1)
-#define PCI_INT_DMA0_HLT                  (1<<0)
-/* all DMA interrupts combined: */
-#define PCI_INT_DMA_ALL                   0x3ff
-
-#define PCI_INT_DMA_HLT(chan)             (1 << (chan * 2))
-#define PCI_INT_DMA_PCL(chan)             (1 << (chan * 2 + 1))
-
-#define LBUS_ADDR                         0xb4
-#define LBUS_ADDR_SEL_RAM                 (0x0<<16)
-#define LBUS_ADDR_SEL_ROM                 (0x1<<16)
-#define LBUS_ADDR_SEL_AUX                 (0x2<<16)
-#define LBUS_ADDR_SEL_ZV                  (0x3<<16)
-
-#define GPIO_CTRL_A                       0xb8
-#define GPIO_CTRL_B                       0xbc
-#define GPIO_DATA_BASE                    0xc0
-
-#define DMA_BREG(base, chan)              (base + chan * 0x20)
-#define DMA_SREG(base, chan)              (base + chan * 0x10)
-
-#define DMA0_PREV_PCL                     0x100
-#define DMA1_PREV_PCL                     0x120
-#define DMA2_PREV_PCL                     0x140
-#define DMA3_PREV_PCL                     0x160
-#define DMA4_PREV_PCL                     0x180
-#define DMA_PREV_PCL(chan)                (DMA_BREG(DMA0_PREV_PCL, chan))
-
-#define DMA0_CURRENT_PCL                  0x104
-#define DMA1_CURRENT_PCL                  0x124
-#define DMA2_CURRENT_PCL                  0x144
-#define DMA3_CURRENT_PCL                  0x164
-#define DMA4_CURRENT_PCL                  0x184
-#define DMA_CURRENT_PCL(chan)             (DMA_BREG(DMA0_CURRENT_PCL, chan))
-
-#define DMA0_CHAN_STAT                    0x10c
-#define DMA1_CHAN_STAT                    0x12c
-#define DMA2_CHAN_STAT                    0x14c
-#define DMA3_CHAN_STAT                    0x16c
-#define DMA4_CHAN_STAT                    0x18c
-#define DMA_CHAN_STAT(chan)               (DMA_BREG(DMA0_CHAN_STAT, chan))
-/* CHAN_STATUS registers share bits */
-#define DMA_CHAN_STAT_SELFID              (1<<31)
-#define DMA_CHAN_STAT_ISOPKT              (1<<30)
-#define DMA_CHAN_STAT_PCIERR              (1<<29)
-#define DMA_CHAN_STAT_PKTERR              (1<<28)
-#define DMA_CHAN_STAT_PKTCMPL             (1<<27)
-#define DMA_CHAN_STAT_SPECIALACK          (1<<14)
-
-
-#define DMA0_CHAN_CTRL                    0x110
-#define DMA1_CHAN_CTRL                    0x130
-#define DMA2_CHAN_CTRL                    0x150
-#define DMA3_CHAN_CTRL                    0x170
-#define DMA4_CHAN_CTRL                    0x190
-#define DMA_CHAN_CTRL(chan)               (DMA_BREG(DMA0_CHAN_CTRL, chan))
-/* CHAN_CTRL registers share bits */
-#define DMA_CHAN_CTRL_ENABLE              (1<<31)
-#define DMA_CHAN_CTRL_BUSY                (1<<30)
-#define DMA_CHAN_CTRL_LINK                (1<<29)
-
-#define DMA0_READY                        0x114
-#define DMA1_READY                        0x134
-#define DMA2_READY                        0x154
-#define DMA3_READY                        0x174
-#define DMA4_READY                        0x194
-#define DMA_READY(chan)                   (DMA_BREG(DMA0_READY, chan))
-
-#define DMA_GLOBAL_REGISTER               0x908
-
-#define FIFO_SIZES                        0xa00
-
-#define FIFO_CONTROL                      0xa10
-#define FIFO_CONTROL_GRF_FLUSH            (1<<4)
-#define FIFO_CONTROL_ITF_FLUSH            (1<<3)
-#define FIFO_CONTROL_ATF_FLUSH            (1<<2)
-
-#define FIFO_XMIT_THRESHOLD               0xa14
-
-#define DMA0_WORD0_CMP_VALUE              0xb00
-#define DMA1_WORD0_CMP_VALUE              0xb10
-#define DMA2_WORD0_CMP_VALUE              0xb20
-#define DMA3_WORD0_CMP_VALUE              0xb30
-#define DMA4_WORD0_CMP_VALUE              0xb40
-#define DMA_WORD0_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD0_CMP_VALUE, chan))
-
-#define DMA0_WORD0_CMP_ENABLE             0xb04
-#define DMA1_WORD0_CMP_ENABLE             0xb14
-#define DMA2_WORD0_CMP_ENABLE             0xb24
-#define DMA3_WORD0_CMP_ENABLE             0xb34
-#define DMA4_WORD0_CMP_ENABLE             0xb44
-#define DMA_WORD0_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD0_CMP_ENABLE,chan))
-
-#define DMA0_WORD1_CMP_VALUE              0xb08
-#define DMA1_WORD1_CMP_VALUE              0xb18
-#define DMA2_WORD1_CMP_VALUE              0xb28
-#define DMA3_WORD1_CMP_VALUE              0xb38
-#define DMA4_WORD1_CMP_VALUE              0xb48
-#define DMA_WORD1_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD1_CMP_VALUE, chan))
-
-#define DMA0_WORD1_CMP_ENABLE             0xb0c
-#define DMA1_WORD1_CMP_ENABLE             0xb1c
-#define DMA2_WORD1_CMP_ENABLE             0xb2c
-#define DMA3_WORD1_CMP_ENABLE             0xb3c
-#define DMA4_WORD1_CMP_ENABLE             0xb4c
-#define DMA_WORD1_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD1_CMP_ENABLE,chan))
-/* word 1 compare enable flags */
-#define DMA_WORD1_CMP_MATCH_OTHERBUS      (1<<15)
-#define DMA_WORD1_CMP_MATCH_BROADCAST     (1<<14)
-#define DMA_WORD1_CMP_MATCH_BUS_BCAST     (1<<13)
-#define DMA_WORD1_CMP_MATCH_LOCAL_NODE    (1<<12)
-#define DMA_WORD1_CMP_MATCH_EXACT         (1<<11)
-#define DMA_WORD1_CMP_ENABLE_SELF_ID      (1<<10)
-#define DMA_WORD1_CMP_ENABLE_MASTER       (1<<8)
-
-#define LINK_ID                           0xf00
-#define LINK_ID_BUS(id)                   (id<<22)
-#define LINK_ID_NODE(id)                  (id<<16)
-
-#define LINK_CONTROL                      0xf04
-#define LINK_CONTROL_BUSY                 (1<<29)
-#define LINK_CONTROL_TX_ISO_EN            (1<<26)
-#define LINK_CONTROL_RX_ISO_EN            (1<<25)
-#define LINK_CONTROL_TX_ASYNC_EN          (1<<24)
-#define LINK_CONTROL_RX_ASYNC_EN          (1<<23)
-#define LINK_CONTROL_RESET_TX             (1<<21)
-#define LINK_CONTROL_RESET_RX             (1<<20)
-#define LINK_CONTROL_CYCMASTER            (1<<11)
-#define LINK_CONTROL_CYCSOURCE            (1<<10)
-#define LINK_CONTROL_CYCTIMEREN           (1<<9)
-#define LINK_CONTROL_RCV_CMP_VALID        (1<<7)
-#define LINK_CONTROL_SNOOP_ENABLE         (1<<6)
-
-#define CYCLE_TIMER                       0xf08
-
-#define LINK_PHY                          0xf0c
-#define LINK_PHY_READ                     (1<<31)
-#define LINK_PHY_WRITE                    (1<<30)
-#define LINK_PHY_ADDR(addr)               (addr<<24)
-#define LINK_PHY_WDATA(data)              (data<<16)
-#define LINK_PHY_RADDR(addr)              (addr<<8)
-
-
-#define LINK_INT_STATUS                   0xf14
-#define LINK_INT_ENABLE                   0xf18
-/* status and enable have identical bit numbers */
-#define LINK_INT_LINK_INT                 (1<<31)
-#define LINK_INT_PHY_TIMEOUT              (1<<30)
-#define LINK_INT_PHY_REG_RCVD             (1<<29)
-#define LINK_INT_PHY_BUSRESET             (1<<28)
-#define LINK_INT_TX_RDY                   (1<<26)
-#define LINK_INT_RX_DATA_RDY              (1<<25)
-#define LINK_INT_ISO_STUCK                (1<<20)
-#define LINK_INT_ASYNC_STUCK              (1<<19)
-#define LINK_INT_SENT_REJECT              (1<<17)
-#define LINK_INT_HDR_ERR                  (1<<16)
-#define LINK_INT_TX_INVALID_TC            (1<<15)
-#define LINK_INT_CYC_SECOND               (1<<11)
-#define LINK_INT_CYC_START                (1<<10)
-#define LINK_INT_CYC_DONE                 (1<<9)
-#define LINK_INT_CYC_PENDING              (1<<8)
-#define LINK_INT_CYC_LOST                 (1<<7)
-#define LINK_INT_CYC_ARB_FAILED           (1<<6)
-#define LINK_INT_GRF_OVERFLOW             (1<<5)
-#define LINK_INT_ITF_UNDERFLOW            (1<<4)
-#define LINK_INT_ATF_UNDERFLOW            (1<<3)
-#define LINK_INT_ISOARB_FAILED            (1<<0)
-
-/* PHY specifics */
-#define PHY_VENDORID_TI                 0x800028
-#define PHY_PRODUCTID_TSB41LV03         0x000000
-
-
-/* this is the physical layout of a PCL, its size is 128 bytes */
-struct ti_pcl {
-        u32 next;
-        u32 async_error_next;
-        u32 user_data;
-        u32 pcl_status;
-        u32 remaining_transfer_count;
-        u32 next_data_buffer;
-        struct {
-                u32 control;
-                u32 pointer;
-        } buffer[13] __attribute__ ((packed));
-} __attribute__ ((packed));
-
-#include <linux/stddef.h>
-#define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
-
-
-static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           const struct ti_pcl *pcl)
-{
-        memcpy_le32((u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
-                    (u32 *)pcl, sizeof(struct ti_pcl));
-}
-
-static inline void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           struct ti_pcl *pcl)
-{
-        memcpy_le32((u32 *)pcl,
-                    (u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
-                    sizeof(struct ti_pcl));
-}
-
-static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
-{
-        return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl);
-}
-
-
-#if defined (__BIG_ENDIAN)
-typedef struct ti_pcl pcltmp_t;
-
-static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                                      pcltmp_t *tmp)
-{
-        get_pcl(lynx, pclid, tmp);
-        return tmp;
-}
-
-static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                              pcltmp_t *tmp)
-{
-        put_pcl(lynx, pclid, tmp);
-}
-
-#else
-typedef int pcltmp_t; /* just a dummy */
-
-static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                                      pcltmp_t *tmp)
-{
-        return lynx->pcl_mem + pclid * sizeof(struct ti_pcl);
-}
-
-static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                              pcltmp_t *tmp)
-{
-}
-#endif
-
-
-static inline void run_sub_pcl(const struct ti_lynx *lynx, pcl_t pclid, int idx,
-                               int dmachan)
-{
-        reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20,
-                  pcl_bus(lynx, pclid) + idx * 4);
-        reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20,
-                  DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK);
-}
-
-static inline void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan)
-{
-        run_sub_pcl(lynx, pclid, 0, dmachan);
-}
-
-#define PCL_NEXT_INVALID (1<<0)
-
-/* transfer commands */
-#define PCL_CMD_RCV            (0x1<<24)
-#define PCL_CMD_RCV_AND_UPDATE (0xa<<24)
-#define PCL_CMD_XMT            (0x2<<24)
-#define PCL_CMD_UNFXMT         (0xc<<24)
-#define PCL_CMD_PCI_TO_LBUS    (0x8<<24)
-#define PCL_CMD_LBUS_TO_PCI    (0x9<<24)
-
-/* aux commands */
-#define PCL_CMD_NOP            (0x0<<24)
-#define PCL_CMD_LOAD           (0x3<<24)
-#define PCL_CMD_STOREQ         (0x4<<24)
-#define PCL_CMD_STORED         (0xb<<24)
-#define PCL_CMD_STORE0         (0x5<<24)
-#define PCL_CMD_STORE1         (0x6<<24)
-#define PCL_CMD_COMPARE        (0xe<<24)
-#define PCL_CMD_SWAP_COMPARE   (0xf<<24)
-#define PCL_CMD_ADD            (0xd<<24)
-#define PCL_CMD_BRANCH         (0x7<<24)
-
-/* BRANCH condition codes */
-#define PCL_COND_DMARDY_SET    (0x1<<20)
-#define PCL_COND_DMARDY_CLEAR  (0x2<<20)
-
-#define PCL_GEN_INTR           (1<<19)
-#define PCL_LAST_BUFF          (1<<18)
-#define PCL_LAST_CMD           (PCL_LAST_BUFF)
-#define PCL_WAITSTAT           (1<<17)
-#define PCL_BIGENDIAN          (1<<16)
-#define PCL_ISOMODE            (1<<12)
-
-#endif
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
deleted file mode 100644 (file)
index 7a225a4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef IEEE1394_RAW1394_PRIVATE_H
-#define IEEE1394_RAW1394_PRIVATE_H
-
-/* header for definitions that are private to the raw1394 driver
-   and not visible to user-space */
-
-#define RAW1394_DEVICE_MAJOR      171
-#define RAW1394_DEVICE_NAME       "raw1394"
-
-#define RAW1394_MAX_USER_CSR_DIRS      16
-
-struct iso_block_store {
-        atomic_t refcount;
-        size_t data_size;
-        quadlet_t data[0];
-};
-
-enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
-                        RAW1394_ISO_RECV = 1,
-                        RAW1394_ISO_XMIT = 2 };
-
-struct file_info {
-        struct list_head list;
-
-       struct mutex state_mutex;
-        enum { opened, initialized, connected } state;
-        unsigned int protocol_version;
-
-        struct hpsb_host *host;
-
-        struct list_head req_pending;  /* protected by reqlists_lock */
-        struct list_head req_complete; /* protected by reqlists_lock */
-        spinlock_t reqlists_lock;
-        wait_queue_head_t wait_complete;
-
-        struct list_head addr_list;    /* protected by host_info_lock */
-
-        u8 __user *fcp_buffer;
-
-        u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
-
-       /* new rawiso API */
-       enum raw1394_iso_state iso_state;
-       struct hpsb_iso *iso_handle;
-
-       /* User space's CSR1212 dynamic ConfigROM directories */
-       struct csr1212_keyval *csr1212_dirs[RAW1394_MAX_USER_CSR_DIRS];
-
-       /* Legacy ConfigROM update flag */
-       u8 cfgrom_upd;
-};
-
-struct arm_addr {
-        struct list_head addr_list; /* file_info list */
-        u64    start, end;
-        u64    arm_tag;
-        u8     access_rights;
-        u8     notification_options;
-        u8     client_transactions;
-        u64    recvb;
-        u16    rec_length;
-        u8     *addr_space_buffer; /* accessed by read/write/lock requests */
-};
-
-struct pending_request {
-        struct list_head list;
-        struct file_info *file_info;
-        struct hpsb_packet *packet;
-        struct iso_block_store *ibs;
-        quadlet_t *data;
-        int free_data;
-        struct raw1394_request req;
-};
-
-struct host_info {
-        struct list_head list;
-        struct hpsb_host *host;
-        struct list_head file_info_list;  /* protected by host_info_lock */
-};
-
-#endif  /* IEEE1394_RAW1394_PRIVATE_H */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
deleted file mode 100644 (file)
index f340142..0000000
+++ /dev/null
@@ -1,3096 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Raw interface to the bus
- *
- * Copyright (C) 1999, 2000 Andreas E. Bombe
- *               2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *                     2002 Christian Toegel <christian.toegel@gmx.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        configuration ROM manipulation
- *        address range mapping
- *        adaptation for new (transparent) loopback mechanism
- *        sending of arbitrary async packets
- * Christian Toegel <christian.toegel@gmx.at>
- *        address range mapping
- *        lock64 request
- *        transmit physical packet
- *        busreset notification control (switch on/off)
- *        busreset with selection of type (short/long)
- *        request_reply
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/compat.h>
-
-#include "csr1212.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "iso.h"
-#include "nodemgr.h"
-#include "raw1394.h"
-#include "raw1394-private.h"
-
-#define int2ptr(x) ((void __user *)(unsigned long)x)
-#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define RAW1394_DEBUG
-#endif
-
-#ifdef RAW1394_DEBUG
-#define DBGMSG(fmt, args...) \
-printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
-#else
-#define DBGMSG(fmt, args...) do {} while (0)
-#endif
-
-static LIST_HEAD(host_info_list);
-static int host_count;
-static DEFINE_SPINLOCK(host_info_lock);
-static atomic_t internal_generation = ATOMIC_INIT(0);
-
-static atomic_t iso_buffer_size;
-static const int iso_buffer_max = 4 * 1024 * 1024;     /* 4 MB */
-
-static struct hpsb_highlevel raw1394_highlevel;
-
-static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
-                   u64 addr, size_t length, u16 flags);
-static int arm_write(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t * data, u64 addr, size_t length, u16 flags);
-static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags);
-static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags);
-static const struct hpsb_address_ops arm_ops = {
-       .read = arm_read,
-       .write = arm_write,
-       .lock = arm_lock,
-       .lock64 = arm_lock64,
-};
-
-static void queue_complete_cb(struct pending_request *req);
-
-static struct pending_request *__alloc_pending_request(gfp_t flags)
-{
-       struct pending_request *req;
-
-       req = kzalloc(sizeof(*req), flags);
-       if (req)
-               INIT_LIST_HEAD(&req->list);
-
-       return req;
-}
-
-static inline struct pending_request *alloc_pending_request(void)
-{
-       return __alloc_pending_request(GFP_KERNEL);
-}
-
-static void free_pending_request(struct pending_request *req)
-{
-       if (req->ibs) {
-               if (atomic_dec_and_test(&req->ibs->refcount)) {
-                       atomic_sub(req->ibs->data_size, &iso_buffer_size);
-                       kfree(req->ibs);
-               }
-       } else if (req->free_data) {
-               kfree(req->data);
-       }
-       hpsb_free_packet(req->packet);
-       kfree(req);
-}
-
-/* fi->reqlists_lock must be taken */
-static void __queue_complete_req(struct pending_request *req)
-{
-       struct file_info *fi = req->file_info;
-
-       list_move_tail(&req->list, &fi->req_complete);
-       wake_up(&fi->wait_complete);
-}
-
-static void queue_complete_req(struct pending_request *req)
-{
-       unsigned long flags;
-       struct file_info *fi = req->file_info;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       __queue_complete_req(req);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-}
-
-static void queue_complete_cb(struct pending_request *req)
-{
-       struct hpsb_packet *packet = req->packet;
-       int rcode = (packet->header[1] >> 12) & 0xf;
-
-       switch (packet->ack_code) {
-       case ACKX_NONE:
-       case ACKX_SEND_ERROR:
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               break;
-       case ACKX_ABORTED:
-               req->req.error = RAW1394_ERROR_ABORTED;
-               break;
-       case ACKX_TIMEOUT:
-               req->req.error = RAW1394_ERROR_TIMEOUT;
-               break;
-       default:
-               req->req.error = (packet->ack_code << 16) | rcode;
-               break;
-       }
-
-       if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
-               req->req.length = 0;
-       }
-
-       if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
-           (req->req.type == RAW1394_REQ_ASYNC_WRITE) ||
-           (req->req.type == RAW1394_REQ_ASYNC_STREAM) ||
-           (req->req.type == RAW1394_REQ_LOCK) ||
-           (req->req.type == RAW1394_REQ_LOCK64))
-               hpsb_free_tlabel(packet);
-
-       queue_complete_req(req);
-}
-
-static void add_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-       unsigned long flags;
-
-       hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-
-       if (hi) {
-               INIT_LIST_HEAD(&hi->list);
-               hi->host = host;
-               INIT_LIST_HEAD(&hi->file_info_list);
-
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&hi->list, &host_info_list);
-               host_count++;
-               spin_unlock_irqrestore(&host_info_lock, flags);
-       }
-
-       atomic_inc(&internal_generation);
-}
-
-static struct host_info *find_host_info(struct hpsb_host *host)
-{
-       struct host_info *hi;
-
-       list_for_each_entry(hi, &host_info_list, list)
-           if (hi->host == host)
-               return hi;
-
-       return NULL;
-}
-
-static void remove_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_del(&hi->list);
-               host_count--;
-               /*
-                  FIXME: address ranges should be removed
-                  and fileinfo states should be initialized
-                  (including setting generation to
-                  internal-generation ...)
-                */
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       if (hi == NULL) {
-               printk(KERN_ERR "raw1394: attempt to remove unknown host "
-                      "0x%p\n", host);
-               return;
-       }
-
-       kfree(hi);
-
-       atomic_inc(&internal_generation);
-}
-
-static void host_reset(struct hpsb_host *host)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-       struct pending_request *req;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (fi->notification == RAW1394_NOTIFY_ON) {
-                               req = __alloc_pending_request(GFP_ATOMIC);
-
-                               if (req != NULL) {
-                                       req->file_info = fi;
-                                       req->req.type = RAW1394_REQ_BUS_RESET;
-                                       req->req.generation =
-                                           get_hpsb_generation(host);
-                                       req->req.misc = (host->node_id << 16)
-                                           | host->node_count;
-                                       if (fi->protocol_version > 3) {
-                                               req->req.misc |=
-                                                   (NODEID_TO_NODE
-                                                    (host->irm_id)
-                                                    << 8);
-                                       }
-
-                                       queue_complete_req(req);
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-}
-
-static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                       int cts, u8 * data, size_t length)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-       struct pending_request *req, *req_next;
-       struct iso_block_store *ibs = NULL;
-       LIST_HEAD(reqs);
-
-       if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-               HPSB_INFO("dropped fcp request");
-               return;
-       }
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (!fi->fcp_buffer)
-                               continue;
-
-                       req = __alloc_pending_request(GFP_ATOMIC);
-                       if (!req)
-                               break;
-
-                       if (!ibs) {
-                               ibs = kmalloc(sizeof(*ibs) + length,
-                                             GFP_ATOMIC);
-                               if (!ibs) {
-                                       kfree(req);
-                                       break;
-                               }
-
-                               atomic_add(length, &iso_buffer_size);
-                               atomic_set(&ibs->refcount, 0);
-                               ibs->data_size = length;
-                               memcpy(ibs->data, data, length);
-                       }
-
-                       atomic_inc(&ibs->refcount);
-
-                       req->file_info = fi;
-                       req->ibs = ibs;
-                       req->data = ibs->data;
-                       req->req.type = RAW1394_REQ_FCP_REQUEST;
-                       req->req.generation = get_hpsb_generation(host);
-                       req->req.misc = nodeid | (direction << 16);
-                       req->req.recvb = ptr2int(fi->fcp_buffer);
-                       req->req.length = length;
-
-                       list_add_tail(&req->list, &reqs);
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       list_for_each_entry_safe(req, req_next, &reqs, list)
-           queue_complete_req(req);
-}
-
-#ifdef CONFIG_COMPAT
-struct compat_raw1394_req {
-       __u32 type;
-       __s32 error;
-       __u32 misc;
-
-       __u32 generation;
-       __u32 length;
-
-       __u64 address;
-
-       __u64 tag;
-
-       __u64 sendb;
-       __u64 recvb;
-}
-#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
-__attribute__((packed))
-#endif
-;
-
-static const char __user *raw1394_compat_write(const char __user *buf)
-{
-       struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
-       struct raw1394_request __user *r;
-
-       r = compat_alloc_user_space(sizeof(struct raw1394_request));
-
-#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
-
-       if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
-           C(address) ||
-           C(tag) ||
-           C(sendb) ||
-           C(recvb))
-               return (__force const char __user *)ERR_PTR(-EFAULT);
-
-       return (const char __user *)r;
-}
-#undef C
-
-#define P(x) __put_user(r->x, &cr->x)
-
-static int
-raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
-{
-       struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
-
-       if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
-           P(type) ||
-           P(error) ||
-           P(misc) ||
-           P(generation) ||
-           P(length) ||
-           P(address) ||
-           P(tag) ||
-           P(sendb) ||
-           P(recvb))
-               return -EFAULT;
-
-       return sizeof(struct compat_raw1394_req);
-}
-#undef P
-
-#endif
-
-/* get next completed request  (caller must hold fi->reqlists_lock) */
-static inline struct pending_request *__next_complete_req(struct file_info *fi)
-{
-       struct list_head *lh;
-       struct pending_request *req = NULL;
-
-       if (!list_empty(&fi->req_complete)) {
-               lh = fi->req_complete.next;
-               list_del(lh);
-               req = list_entry(lh, struct pending_request, list);
-       }
-       return req;
-}
-
-/* atomically get next completed request */
-static struct pending_request *next_complete_req(struct file_info *fi)
-{
-       unsigned long flags;
-       struct pending_request *req;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       req = __next_complete_req(fi);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-       return req;
-}
-
-static ssize_t raw1394_read(struct file *file, char __user * buffer,
-                           size_t count, loff_t * offset_is_ignored)
-{
-       struct file_info *fi = file->private_data;
-       struct pending_request *req;
-       ssize_t ret;
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req)) {
-               /* ok */
-       } else
-#endif
-       if (count != sizeof(struct raw1394_request)) {
-               return -EINVAL;
-       }
-
-       if (!access_ok(VERIFY_WRITE, buffer, count)) {
-               return -EFAULT;
-       }
-
-       if (file->f_flags & O_NONBLOCK) {
-               if (!(req = next_complete_req(fi)))
-                       return -EAGAIN;
-       } else {
-               /*
-                * NB: We call the macro wait_event_interruptible() with a
-                * condition argument with side effect.  This is only possible
-                * because the side effect does not occur until the condition
-                * became true, and wait_event_interruptible() won't evaluate
-                * the condition again after that.
-                */
-               if (wait_event_interruptible(fi->wait_complete,
-                                            (req = next_complete_req(fi))))
-                       return -ERESTARTSYS;
-       }
-
-       if (req->req.length) {
-               if (copy_to_user(int2ptr(req->req.recvb), req->data,
-                                req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-               }
-       }
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req) &&
-           sizeof(struct compat_raw1394_req) !=
-                       sizeof(struct raw1394_request)) {
-               ret = raw1394_compat_read(buffer, &req->req);
-       } else
-#endif
-       {
-               if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
-                       ret = -EFAULT;
-                       goto out;
-               }
-               ret = (ssize_t) sizeof(struct raw1394_request);
-       }
-      out:
-       free_pending_request(req);
-       return ret;
-}
-
-static int state_opened(struct file_info *fi, struct pending_request *req)
-{
-       if (req->req.type == RAW1394_REQ_INITIALIZE) {
-               switch (req->req.misc) {
-               case RAW1394_KERNELAPI_VERSION:
-               case 3:
-                       fi->state = initialized;
-                       fi->protocol_version = req->req.misc;
-                       req->req.error = RAW1394_ERROR_NONE;
-                       req->req.generation = atomic_read(&internal_generation);
-                       break;
-
-               default:
-                       req->req.error = RAW1394_ERROR_COMPAT;
-                       req->req.misc = RAW1394_KERNELAPI_VERSION;
-               }
-       } else {
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-       }
-
-       req->req.length = 0;
-       queue_complete_req(req);
-       return 0;
-}
-
-static int state_initialized(struct file_info *fi, struct pending_request *req)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct raw1394_khost_list *khl;
-
-       if (req->req.generation != atomic_read(&internal_generation)) {
-               req->req.error = RAW1394_ERROR_GENERATION;
-               req->req.generation = atomic_read(&internal_generation);
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       switch (req->req.type) {
-       case RAW1394_REQ_LIST_CARDS:
-               spin_lock_irqsave(&host_info_lock, flags);
-               khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC);
-
-               if (khl) {
-                       req->req.misc = host_count;
-                       req->data = (quadlet_t *) khl;
-
-                       list_for_each_entry(hi, &host_info_list, list) {
-                               khl->nodes = hi->host->node_count;
-                               strcpy(khl->name, hi->host->driver->name);
-                               khl++;
-                       }
-               }
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               if (khl) {
-                       req->req.error = RAW1394_ERROR_NONE;
-                       req->req.length = min(req->req.length,
-                                             (u32) (sizeof
-                                                    (struct raw1394_khost_list)
-                                                    * req->req.misc));
-                       req->free_data = 1;
-               } else {
-                       return -ENOMEM;
-               }
-               break;
-
-       case RAW1394_REQ_SET_CARD:
-               spin_lock_irqsave(&host_info_lock, flags);
-               if (req->req.misc >= host_count) {
-                       req->req.error = RAW1394_ERROR_INVALID_ARG;
-                       goto out_set_card;
-               }
-               list_for_each_entry(hi, &host_info_list, list)
-                       if (!req->req.misc--)
-                               break;
-               get_device(&hi->host->device); /* FIXME handle failure case */
-               list_add_tail(&fi->list, &hi->file_info_list);
-
-               /* prevent unloading of the host's low-level driver */
-               if (!try_module_get(hi->host->driver->owner)) {
-                       req->req.error = RAW1394_ERROR_ABORTED;
-                       goto out_set_card;
-               }
-               WARN_ON(fi->host);
-               fi->host = hi->host;
-               fi->state = connected;
-
-               req->req.error = RAW1394_ERROR_NONE;
-               req->req.generation = get_hpsb_generation(fi->host);
-               req->req.misc = (fi->host->node_id << 16)
-                               | fi->host->node_count;
-               if (fi->protocol_version > 3)
-                       req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
-out_set_card:
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               req->req.length = 0;
-               break;
-
-       default:
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-               req->req.length = 0;
-               break;
-       }
-
-       queue_complete_req(req);
-       return 0;
-}
-
-static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
-{
-       if (req->req.misc) {
-               if (fi->fcp_buffer) {
-                       req->req.error = RAW1394_ERROR_ALREADY;
-               } else {
-                       fi->fcp_buffer = int2ptr(req->req.recvb);
-               }
-       } else {
-               if (!fi->fcp_buffer) {
-                       req->req.error = RAW1394_ERROR_ALREADY;
-               } else {
-                       fi->fcp_buffer = NULL;
-               }
-       }
-
-       req->req.length = 0;
-       queue_complete_req(req);
-}
-
-static int handle_async_request(struct file_info *fi,
-                               struct pending_request *req, int node)
-{
-       unsigned long flags;
-       struct hpsb_packet *packet = NULL;
-       u64 addr = req->req.address & 0xffffffffffffULL;
-
-       switch (req->req.type) {
-       case RAW1394_REQ_ASYNC_READ:
-               DBGMSG("read_request called");
-               packet =
-                   hpsb_make_readpacket(fi->host, node, addr, req->req.length);
-
-               if (!packet)
-                       return -ENOMEM;
-
-               if (req->req.length == 4)
-                       req->data = &packet->header[3];
-               else
-                       req->data = packet->data;
-
-               break;
-
-       case RAW1394_REQ_ASYNC_WRITE:
-               DBGMSG("write_request called");
-
-               packet = hpsb_make_writepacket(fi->host, node, addr, NULL,
-                                              req->req.length);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (req->req.length == 4) {
-                       if (copy_from_user
-                           (&packet->header[3], int2ptr(req->req.sendb),
-                            req->req.length))
-                               req->req.error = RAW1394_ERROR_MEMFAULT;
-               } else {
-                       if (copy_from_user
-                           (packet->data, int2ptr(req->req.sendb),
-                            req->req.length))
-                               req->req.error = RAW1394_ERROR_MEMFAULT;
-               }
-
-               req->req.length = 0;
-               break;
-
-       case RAW1394_REQ_ASYNC_STREAM:
-               DBGMSG("stream_request called");
-
-               packet =
-                   hpsb_make_streampacket(fi->host, NULL, req->req.length,
-                                          node & 0x3f /*channel */ ,
-                                          (req->req.misc >> 16) & 0x3,
-                                          req->req.misc & 0xf);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length))
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-
-               req->req.length = 0;
-               break;
-
-       case RAW1394_REQ_LOCK:
-               DBGMSG("lock_request called");
-               if ((req->req.misc == EXTCODE_FETCH_ADD)
-                   || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                       if (req->req.length != 4) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               } else {
-                       if (req->req.length != 8) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               }
-
-               packet = hpsb_make_lockpacket(fi->host, node, addr,
-                                             req->req.misc, NULL, 0);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-                       break;
-               }
-
-               req->data = packet->data;
-               req->req.length = 4;
-               break;
-
-       case RAW1394_REQ_LOCK64:
-               DBGMSG("lock64_request called");
-               if ((req->req.misc == EXTCODE_FETCH_ADD)
-                   || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                       if (req->req.length != 8) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               } else {
-                       if (req->req.length != 16) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               }
-               packet = hpsb_make_lock64packet(fi->host, node, addr,
-                                               req->req.misc, NULL, 0);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-                       break;
-               }
-
-               req->data = packet->data;
-               req->req.length = 8;
-               break;
-
-       default:
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-       }
-
-       req->packet = packet;
-
-       if (req->req.error) {
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       packet->generation = req->req.generation;
-
-       if (hpsb_send_packet(packet) < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               req->req.length = 0;
-               hpsb_free_tlabel(packet);
-               queue_complete_req(req);
-       }
-       return 0;
-}
-
-static int handle_async_send(struct file_info *fi, struct pending_request *req)
-{
-       unsigned long flags;
-       struct hpsb_packet *packet;
-       int header_length = req->req.misc & 0xffff;
-       int expect_response = req->req.misc >> 16;
-       size_t data_size;
-
-       if (header_length > req->req.length || header_length < 12 ||
-           header_length > FIELD_SIZEOF(struct hpsb_packet, header)) {
-               req->req.error = RAW1394_ERROR_INVALID_ARG;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       data_size = req->req.length - header_length;
-       packet = hpsb_alloc_packet(data_size);
-       req->packet = packet;
-       if (!packet)
-               return -ENOMEM;
-
-       if (copy_from_user(packet->header, int2ptr(req->req.sendb),
-                          header_length)) {
-               req->req.error = RAW1394_ERROR_MEMFAULT;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       if (copy_from_user
-           (packet->data, int2ptr(req->req.sendb) + header_length,
-            data_size)) {
-               req->req.error = RAW1394_ERROR_MEMFAULT;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       packet->type = hpsb_async;
-       packet->node_id = packet->header[0] >> 16;
-       packet->tcode = (packet->header[0] >> 4) & 0xf;
-       packet->tlabel = (packet->header[0] >> 10) & 0x3f;
-       packet->host = fi->host;
-       packet->expect_response = expect_response;
-       packet->header_size = header_length;
-       packet->data_size = data_size;
-
-       req->req.length = 0;
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       /* Update the generation of the packet just before sending. */
-       packet->generation = req->req.generation;
-
-       if (hpsb_send_packet(packet) < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               queue_complete_req(req);
-       }
-
-       return 0;
-}
-
-static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
-                   u64 addr, size_t length, u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       DBGMSG("arm_read  called by node: %X "
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >= (addr + length))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_read addr_entry FOUND");
-       }
-       if (arm_addr->rec_length < length) {
-               DBGMSG("arm_read blocklength too big -> rcode_data_error");
-               rcode = RCODE_DATA_ERROR;       /* hardware error, data is unavailable */
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_READ) {
-                       if (!(arm_addr->client_transactions & ARM_READ)) {
-                               memcpy(buffer,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      length);
-                               DBGMSG("arm_read -> (rcode_complete)");
-                               rcode = RCODE_COMPLETE;
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_read -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_READ) {
-               DBGMSG("arm_read -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_read -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       size =
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) +
-                           length * sizeof(byte_t) +
-                           sizeof(struct arm_request_response);
-               } else {
-                       size =
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) +
-                           sizeof(struct arm_request_response);
-               }
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_read -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc =
-                   (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               arm_req->buffer = NULL;
-               arm_resp->buffer = NULL;
-               if (rcode == RCODE_COMPLETE) {
-                       byte_t *buf =
-                           (byte_t *) arm_resp + sizeof(struct arm_response);
-                       memcpy(buf,
-                              (arm_addr->addr_space_buffer) + (addr -
-                                                               (arm_addr->
-                                                                start)),
-                              length);
-                       arm_resp->buffer =
-                           int2ptr((arm_addr->recvb) +
-                                   sizeof(struct arm_request_response) +
-                                   sizeof(struct arm_request) +
-                                   sizeof(struct arm_response));
-               }
-               arm_resp->buffer_length =
-                   (rcode == RCODE_COMPLETE) ? length : 0;
-               arm_resp->response_code = rcode;
-               arm_req->buffer_length = 0;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = 0;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_write(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t * data, u64 addr, size_t length, u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       DBGMSG("arm_write called by node: %X "
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >= (addr + length))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_write addr_entry FOUND");
-       }
-       if (arm_addr->rec_length < length) {
-               DBGMSG("arm_write blocklength too big -> rcode_data_error");
-               rcode = RCODE_DATA_ERROR;       /* hardware error, data is unavailable */
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_WRITE) {
-                       if (!(arm_addr->client_transactions & ARM_WRITE)) {
-                               memcpy((arm_addr->addr_space_buffer) +
-                                      (addr - (arm_addr->start)), data,
-                                      length);
-                               DBGMSG("arm_write -> (rcode_complete)");
-                               rcode = RCODE_COMPLETE;
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_write -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_WRITE) {
-               DBGMSG("arm_write -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_write -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request my be retried */
-               }
-               size =
-                   sizeof(struct arm_request) + sizeof(struct arm_response) +
-                   (length) * sizeof(byte_t) +
-                   sizeof(struct arm_request_response);
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_write -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc =
-                   (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               arm_resp->buffer = NULL;
-               memcpy((byte_t *) arm_resp + sizeof(struct arm_response),
-                      data, length);
-               arm_req->buffer = int2ptr((arm_addr->recvb) +
-                                         sizeof(struct arm_request_response) +
-                                         sizeof(struct arm_request) +
-                                         sizeof(struct arm_response));
-               arm_req->buffer_length = length;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = 0;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = destid;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->buffer_length = 0;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       quadlet_t old, new;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-           ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-               DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
-                      be32_to_cpu(data));
-       } else {
-               DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
-                      be32_to_cpu(data), be32_to_cpu(arg));
-       }
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >=
-                                       (addr + sizeof(*store)))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_lock addr_entry FOUND");
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_LOCK) {
-                       if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                               memcpy(&old,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      sizeof(old));
-                               switch (ext_tcode) {
-                               case (EXTCODE_MASK_SWAP):
-                                       new = data | (old & ~arg);
-                                       break;
-                               case (EXTCODE_COMPARE_SWAP):
-                                       if (old == arg) {
-                                               new = data;
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_FETCH_ADD):
-                                       new =
-                                           cpu_to_be32(be32_to_cpu(data) +
-                                                       be32_to_cpu(old));
-                                       break;
-                               case (EXTCODE_LITTLE_ADD):
-                                       new =
-                                           cpu_to_le32(le32_to_cpu(data) +
-                                                       le32_to_cpu(old));
-                                       break;
-                               case (EXTCODE_BOUNDED_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be32(be32_to_cpu
-                                                               (data) +
-                                                               be32_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_WRAP_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be32(be32_to_cpu
-                                                               (data) +
-                                                               be32_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = data;
-                                       }
-                                       break;
-                               default:
-                                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                                       printk(KERN_ERR
-                                              "raw1394: arm_lock FAILED "
-                                              "ext_tcode not allowed -> rcode_type_error\n");
-                                       break;
-                               }       /*switch */
-                               if (rcode == -1) {
-                                       DBGMSG("arm_lock -> (rcode_complete)");
-                                       rcode = RCODE_COMPLETE;
-                                       memcpy(store, &old, sizeof(*store));
-                                       memcpy((arm_addr->addr_space_buffer) +
-                                              (addr - (arm_addr->start)),
-                                              &new, sizeof(*store));
-                               }
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_lock -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_LOCK) {
-               byte_t *buf1, *buf2;
-               DBGMSG("arm_lock -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_lock -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_lock -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
-               buf2 = buf1 + 2 * sizeof(*store);
-               if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                   (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                       arm_req->buffer_length = sizeof(*store);
-                       memcpy(buf1, &data, sizeof(*store));
-
-               } else {
-                       arm_req->buffer_length = 2 * sizeof(*store);
-                       memcpy(buf1, &arg, sizeof(*store));
-                       memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       arm_resp->buffer_length = sizeof(*store);
-                       memcpy(buf2, &old, sizeof(*store));
-               } else {
-                       arm_resp->buffer_length = 0;
-               }
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                                (ARM_LOCK & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = ext_tcode;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               arm_req->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response));
-               arm_resp->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) + 2 * sizeof(*store));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       octlet_t old, new;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-           ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-               DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
-       } else {
-               DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
-                      "%8.8X %8.8X ",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
-                      (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
-       }
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search addressentry in file_info's for host */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >=
-                                       (addr + sizeof(*store)))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR
-                      "raw1394: arm_lock64 FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_lock64 addr_entry FOUND");
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_LOCK) {
-                       if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                               memcpy(&old,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      sizeof(old));
-                               switch (ext_tcode) {
-                               case (EXTCODE_MASK_SWAP):
-                                       new = data | (old & ~arg);
-                                       break;
-                               case (EXTCODE_COMPARE_SWAP):
-                                       if (old == arg) {
-                                               new = data;
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_FETCH_ADD):
-                                       new =
-                                           cpu_to_be64(be64_to_cpu(data) +
-                                                       be64_to_cpu(old));
-                                       break;
-                               case (EXTCODE_LITTLE_ADD):
-                                       new =
-                                           cpu_to_le64(le64_to_cpu(data) +
-                                                       le64_to_cpu(old));
-                                       break;
-                               case (EXTCODE_BOUNDED_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be64(be64_to_cpu
-                                                               (data) +
-                                                               be64_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_WRAP_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be64(be64_to_cpu
-                                                               (data) +
-                                                               be64_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = data;
-                                       }
-                                       break;
-                               default:
-                                       printk(KERN_ERR
-                                              "raw1394: arm_lock64 FAILED "
-                                              "ext_tcode not allowed -> rcode_type_error\n");
-                                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                                       break;
-                               }       /*switch */
-                               if (rcode == -1) {
-                                       DBGMSG
-                                           ("arm_lock64 -> (rcode_complete)");
-                                       rcode = RCODE_COMPLETE;
-                                       memcpy(store, &old, sizeof(*store));
-                                       memcpy((arm_addr->addr_space_buffer) +
-                                              (addr - (arm_addr->start)),
-                                              &new, sizeof(*store));
-                               }
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG
-                           ("arm_lock64 -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_LOCK) {
-               byte_t *buf1, *buf2;
-               DBGMSG("arm_lock64 -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       DBGMSG("arm_lock64 -> rcode_conflict_error");
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       DBGMSG("arm_lock64 -> rcode_conflict_error");
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
-               buf2 = buf1 + 2 * sizeof(*store);
-               if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                   (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                       arm_req->buffer_length = sizeof(*store);
-                       memcpy(buf1, &data, sizeof(*store));
-
-               } else {
-                       arm_req->buffer_length = 2 * sizeof(*store);
-                       memcpy(buf1, &arg, sizeof(*store));
-                       memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       arm_resp->buffer_length = sizeof(*store);
-                       memcpy(buf2, &old, sizeof(*store));
-               } else {
-                       arm_resp->buffer_length = 0;
-               }
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                                (ARM_LOCK & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = ext_tcode;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               arm_req->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response));
-               arm_resp->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) + 2 * sizeof(*store));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_register(struct file_info *fi, struct pending_request *req)
-{
-       int retval;
-       struct arm_addr *addr;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       int same_host, another_host;
-       unsigned long flags;
-
-       DBGMSG("arm_register called "
-              "addr(Offset): %8.8x %8.8x length: %u "
-              "rights: %2.2X notify: %2.2X "
-              "max_blk_len: %4.4X",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF),
-              req->req.length, ((req->req.misc >> 8) & 0xFF),
-              (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF));
-       /* check addressrange */
-       if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
-           (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) !=
-            0)) {
-               req->req.length = 0;
-               return (-EINVAL);
-       }
-       /* addr-list-entry for fileinfo */
-       addr = kmalloc(sizeof(*addr), GFP_KERNEL);
-       if (!addr) {
-               req->req.length = 0;
-               return (-ENOMEM);
-       }
-       /* allocation of addr_space_buffer */
-       addr->addr_space_buffer = vmalloc(req->req.length);
-       if (!(addr->addr_space_buffer)) {
-               kfree(addr);
-               req->req.length = 0;
-               return (-ENOMEM);
-       }
-       /* initialization of addr_space_buffer */
-       if ((req->req.sendb) == (unsigned long)NULL) {
-               /* init: set 0 */
-               memset(addr->addr_space_buffer, 0, req->req.length);
-       } else {
-               /* init: user -> kernel */
-               if (copy_from_user
-                   (addr->addr_space_buffer, int2ptr(req->req.sendb),
-                    req->req.length)) {
-                       vfree(addr->addr_space_buffer);
-                       kfree(addr);
-                       return (-EFAULT);
-               }
-       }
-       INIT_LIST_HEAD(&addr->addr_list);
-       addr->arm_tag = req->req.tag;
-       addr->start = req->req.address;
-       addr->end = req->req.address + req->req.length;
-       addr->access_rights = (u8) (req->req.misc & 0x0F);
-       addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
-       addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
-       addr->access_rights |= addr->client_transactions;
-       addr->notification_options |= addr->client_transactions;
-       addr->recvb = req->req.recvb;
-       addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(fi->host);
-       same_host = 0;
-       another_host = 0;
-       /* same host with address-entry containing same addressrange ? */
-       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-               entry = fi_hlp->addr_list.next;
-               while (entry != &(fi_hlp->addr_list)) {
-                       arm_addr =
-                           list_entry(entry, struct arm_addr, addr_list);
-                       if ((arm_addr->start == addr->start)
-                           && (arm_addr->end == addr->end)) {
-                               DBGMSG("same host ownes same "
-                                      "addressrange -> EALREADY");
-                               same_host = 1;
-                               break;
-                       }
-                       entry = entry->next;
-               }
-               if (same_host) {
-                       break;
-               }
-       }
-       if (same_host) {
-               /* addressrange occupied by same host */
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               return (-EALREADY);
-       }
-       /* another host with valid address-entry containing same addressrange */
-       list_for_each_entry(hi, &host_info_list, list) {
-               if (hi->host != fi->host) {
-                       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                               entry = fi_hlp->addr_list.next;
-                               while (entry != &(fi_hlp->addr_list)) {
-                                       arm_addr =
-                                           list_entry(entry, struct arm_addr,
-                                                      addr_list);
-                                       if ((arm_addr->start == addr->start)
-                                           && (arm_addr->end == addr->end)) {
-                                               DBGMSG
-                                                   ("another host ownes same "
-                                                    "addressrange");
-                                               another_host = 1;
-                                               break;
-                                       }
-                                       entry = entry->next;
-                               }
-                               if (another_host) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       if (another_host) {
-               DBGMSG("another hosts entry is valid -> SUCCESS");
-               if (copy_to_user(int2ptr(req->req.recvb),
-                                &addr->start, sizeof(u64))) {
-                       printk(KERN_ERR "raw1394: arm_register failed "
-                              " address-range-entry is invalid -> EFAULT !!!\n");
-                       vfree(addr->addr_space_buffer);
-                       kfree(addr);
-                       return (-EFAULT);
-               }
-               free_pending_request(req);      /* immediate success or fail */
-               /* INSERT ENTRY */
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&addr->addr_list, &fi->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return 0;
-       }
-       retval =
-           hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
-                                   req->req.address,
-                                   req->req.address + req->req.length);
-       if (retval) {
-               /* INSERT ENTRY */
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&addr->addr_list, &fi->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-       } else {
-               DBGMSG("arm_register failed errno: %d \n", retval);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               return (-EALREADY);
-       }
-       free_pending_request(req);      /* immediate success or fail */
-       return 0;
-}
-
-static int arm_unregister(struct file_info *fi, struct pending_request *req)
-{
-       int found = 0;
-       int retval = 0;
-       struct list_head *entry;
-       struct arm_addr *addr = NULL;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct arm_addr *arm_addr = NULL;
-       int another_host;
-       unsigned long flags;
-
-       DBGMSG("arm_Unregister called addr(Offset): "
-              "%8.8x %8.8x",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF));
-       spin_lock_irqsave(&host_info_lock, flags);
-       /* get addr */
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               addr = list_entry(entry, struct arm_addr, addr_list);
-               if (addr->start == req->req.address) {
-                       found = 1;
-                       break;
-               }
-               entry = entry->next;
-       }
-       if (!found) {
-               DBGMSG("arm_Unregister addr not found");
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return (-EINVAL);
-       }
-       DBGMSG("arm_Unregister addr found");
-       another_host = 0;
-       /* another host with valid address-entry containing
-          same addressrange */
-       list_for_each_entry(hi, &host_info_list, list) {
-               if (hi->host != fi->host) {
-                       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                               entry = fi_hlp->addr_list.next;
-                               while (entry != &(fi_hlp->addr_list)) {
-                                       arm_addr = list_entry(entry,
-                                                             struct arm_addr,
-                                                             addr_list);
-                                       if (arm_addr->start == addr->start) {
-                                               DBGMSG("another host ownes "
-                                                      "same addressrange");
-                                               another_host = 1;
-                                               break;
-                                       }
-                                       entry = entry->next;
-                               }
-                               if (another_host) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       if (another_host) {
-               DBGMSG("delete entry from list -> success");
-               list_del(&addr->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               free_pending_request(req);      /* immediate success or fail */
-               return 0;
-       }
-       retval =
-           hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
-                                     addr->start);
-       if (!retval) {
-               printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return (-EINVAL);
-       }
-       DBGMSG("delete entry from list -> success");
-       list_del(&addr->addr_list);
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       vfree(addr->addr_space_buffer);
-       kfree(addr);
-       free_pending_request(req);      /* immediate success or fail */
-       return 0;
-}
-
-/* Copy data from ARM buffer(s) to user buffer. */
-static int arm_get_buf(struct file_info *fi, struct pending_request *req)
-{
-       struct arm_addr *arm_addr = NULL;
-       unsigned long flags;
-       unsigned long offset;
-
-       struct list_head *entry;
-
-       DBGMSG("arm_get_buf "
-              "addr(Offset): %04X %08X length: %u",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               arm_addr = list_entry(entry, struct arm_addr, addr_list);
-               if ((arm_addr->start <= req->req.address) &&
-                   (arm_addr->end > req->req.address)) {
-                       if (req->req.address + req->req.length <= arm_addr->end) {
-                               offset = req->req.address - arm_addr->start;
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-
-                               DBGMSG
-                                   ("arm_get_buf copy_to_user( %08X, %p, %u )",
-                                    (u32) req->req.recvb,
-                                    arm_addr->addr_space_buffer + offset,
-                                    (u32) req->req.length);
-                               if (copy_to_user
-                                   (int2ptr(req->req.recvb),
-                                    arm_addr->addr_space_buffer + offset,
-                                    req->req.length))
-                                       return (-EFAULT);
-
-                               /* We have to free the request, because we
-                                * queue no response, and therefore nobody
-                                * will free it. */
-                               free_pending_request(req);
-                               return 0;
-                       } else {
-                               DBGMSG("arm_get_buf request exceeded mapping");
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-                               return (-EINVAL);
-                       }
-               }
-               entry = entry->next;
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       return (-EINVAL);
-}
-
-/* Copy data from user buffer to ARM buffer(s). */
-static int arm_set_buf(struct file_info *fi, struct pending_request *req)
-{
-       struct arm_addr *arm_addr = NULL;
-       unsigned long flags;
-       unsigned long offset;
-
-       struct list_head *entry;
-
-       DBGMSG("arm_set_buf "
-              "addr(Offset): %04X %08X length: %u",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               arm_addr = list_entry(entry, struct arm_addr, addr_list);
-               if ((arm_addr->start <= req->req.address) &&
-                   (arm_addr->end > req->req.address)) {
-                       if (req->req.address + req->req.length <= arm_addr->end) {
-                               offset = req->req.address - arm_addr->start;
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-
-                               DBGMSG
-                                   ("arm_set_buf copy_from_user( %p, %08X, %u )",
-                                    arm_addr->addr_space_buffer + offset,
-                                    (u32) req->req.sendb,
-                                    (u32) req->req.length);
-                               if (copy_from_user
-                                   (arm_addr->addr_space_buffer + offset,
-                                    int2ptr(req->req.sendb),
-                                    req->req.length))
-                                       return (-EFAULT);
-
-                               /* We have to free the request, because we
-                                * queue no response, and therefore nobody
-                                * will free it. */
-                               free_pending_request(req);
-                               return 0;
-                       } else {
-                               DBGMSG("arm_set_buf request exceeded mapping");
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-                               return (-EINVAL);
-                       }
-               }
-               entry = entry->next;
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       return (-EINVAL);
-}
-
-static int reset_notification(struct file_info *fi, struct pending_request *req)
-{
-       DBGMSG("reset_notification called - switch %s ",
-              (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON");
-       if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
-           (req->req.misc == RAW1394_NOTIFY_ON)) {
-               fi->notification = (u8) req->req.misc;
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-               return 0;
-       }
-       /* error EINVAL (22) invalid argument */
-       return (-EINVAL);
-}
-
-static int write_phypacket(struct file_info *fi, struct pending_request *req)
-{
-       struct hpsb_packet *packet = NULL;
-       int retval = 0;
-       quadlet_t data;
-       unsigned long flags;
-
-       data = be32_to_cpu((u32) req->req.sendb);
-       DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
-       packet = hpsb_make_phypacket(fi->host, data);
-       if (!packet)
-               return -ENOMEM;
-       req->req.length = 0;
-       req->packet = packet;
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-       packet->generation = req->req.generation;
-       retval = hpsb_send_packet(packet);
-       DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
-       if (retval < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               req->req.length = 0;
-               queue_complete_req(req);
-       }
-       return 0;
-}
-
-static int get_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       int ret = 0;
-       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
-       int status;
-
-       if (!data)
-               return -ENOMEM;
-
-       status =
-           csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
-                        data, req->req.length);
-       if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length))
-               ret = -EFAULT;
-       if (copy_to_user
-           (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
-            sizeof(fi->host->csr.rom->cache_head->len)))
-               ret = -EFAULT;
-       if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
-                        sizeof(fi->host->csr.generation)))
-               ret = -EFAULT;
-       if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status)))
-               ret = -EFAULT;
-       kfree(data);
-       if (ret >= 0) {
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-       }
-       return ret;
-}
-
-static int update_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       int ret = 0;
-       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
-               ret = -EFAULT;
-       } else {
-               int status = hpsb_update_config_rom(fi->host,
-                                                   data, req->req.length,
-                                                   (unsigned char)req->req.
-                                                   misc);
-               if (copy_to_user
-                   (int2ptr(req->req.recvb), &status, sizeof(status)))
-                       ret = -ENOMEM;
-       }
-       kfree(data);
-       if (ret >= 0) {
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-               fi->cfgrom_upd = 1;
-       }
-       return ret;
-}
-
-static int modify_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       struct csr1212_keyval *kv;
-       struct csr1212_csr_rom_cache *cache;
-       struct csr1212_dentry *dentry;
-       u32 dr;
-       int ret = 0;
-
-       if (req->req.misc == ~0) {
-               if (req->req.length == 0)
-                       return -EINVAL;
-
-               /* Find an unused slot */
-               for (dr = 0;
-                    dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr];
-                    dr++) ;
-
-               if (dr == RAW1394_MAX_USER_CSR_DIRS)
-                       return -ENOMEM;
-
-               fi->csr1212_dirs[dr] =
-                   csr1212_new_directory(CSR1212_KV_ID_VENDOR);
-               if (!fi->csr1212_dirs[dr])
-                       return -ENOMEM;
-       } else {
-               dr = req->req.misc;
-               if (!fi->csr1212_dirs[dr])
-                       return -EINVAL;
-
-               /* Delete old stuff */
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    dentry; dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-
-               if (req->req.length == 0) {
-                       csr1212_release_keyval(fi->csr1212_dirs[dr]);
-                       fi->csr1212_dirs[dr] = NULL;
-
-                       hpsb_update_config_rom_image(fi->host);
-                       free_pending_request(req);
-                       return 0;
-               }
-       }
-
-       cache = csr1212_rom_cache_malloc(0, req->req.length);
-       if (!cache) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               return -ENOMEM;
-       }
-
-       cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
-       if (!cache->filled_head) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-       cache->filled_tail = cache->filled_head;
-
-       if (copy_from_user(cache->data, int2ptr(req->req.sendb),
-                          req->req.length)) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               ret = -EFAULT;
-       } else {
-               cache->len = req->req.length;
-               cache->filled_head->offset_start = 0;
-               cache->filled_head->offset_end = cache->size - 1;
-
-               cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
-
-               ret = CSR1212_SUCCESS;
-               /* parse all the items */
-               for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv;
-                    kv = kv->next) {
-                       ret = csr1212_parse_keyval(kv, cache);
-               }
-
-               /* attach top level items to the root directory */
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
-                       ret =
-                           csr1212_attach_keyval_to_directory(fi->host->csr.
-                                                              rom->root_kv,
-                                                              dentry->kv);
-               }
-
-               if (ret == CSR1212_SUCCESS) {
-                       ret = hpsb_update_config_rom_image(fi->host);
-
-                       if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb),
-                                                    &dr, sizeof(dr))) {
-                               ret = -ENOMEM;
-                       }
-               }
-       }
-       kfree(cache->filled_head);
-       CSR1212_FREE(cache);
-
-       if (ret >= 0) {
-               /* we have to free the request, because we queue no response,
-                * and therefore nobody will free it */
-               free_pending_request(req);
-               return 0;
-       } else {
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    dentry; dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               return ret;
-       }
-}
-
-static int state_connected(struct file_info *fi, struct pending_request *req)
-{
-       int node = req->req.address >> 48;
-
-       req->req.error = RAW1394_ERROR_NONE;
-
-       switch (req->req.type) {
-
-       case RAW1394_REQ_ECHO:
-               queue_complete_req(req);
-               return 0;
-
-       case RAW1394_REQ_ARM_REGISTER:
-               return arm_register(fi, req);
-
-       case RAW1394_REQ_ARM_UNREGISTER:
-               return arm_unregister(fi, req);
-
-       case RAW1394_REQ_ARM_SET_BUF:
-               return arm_set_buf(fi, req);
-
-       case RAW1394_REQ_ARM_GET_BUF:
-               return arm_get_buf(fi, req);
-
-       case RAW1394_REQ_RESET_NOTIFY:
-               return reset_notification(fi, req);
-
-       case RAW1394_REQ_ISO_SEND:
-       case RAW1394_REQ_ISO_LISTEN:
-               printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
-               req->req.error = RAW1394_ERROR_COMPAT;
-               req->req.misc = RAW1394_KERNELAPI_VERSION;
-               queue_complete_req(req);
-               return 0;
-
-       case RAW1394_REQ_FCP_LISTEN:
-               handle_fcp_listen(fi, req);
-               return 0;
-
-       case RAW1394_REQ_RESET_BUS:
-               if (req->req.misc == RAW1394_LONG_RESET) {
-                       DBGMSG("busreset called (type: LONG)");
-                       hpsb_reset_bus(fi->host, LONG_RESET);
-                       free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                       return 0;
-               }
-               if (req->req.misc == RAW1394_SHORT_RESET) {
-                       DBGMSG("busreset called (type: SHORT)");
-                       hpsb_reset_bus(fi->host, SHORT_RESET);
-                       free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                       return 0;
-               }
-               /* error EINVAL (22) invalid argument */
-               return (-EINVAL);
-       case RAW1394_REQ_GET_ROM:
-               return get_config_rom(fi, req);
-
-       case RAW1394_REQ_UPDATE_ROM:
-               return update_config_rom(fi, req);
-
-       case RAW1394_REQ_MODIFY_ROM:
-               return modify_config_rom(fi, req);
-       }
-
-       if (req->req.generation != get_hpsb_generation(fi->host)) {
-               req->req.error = RAW1394_ERROR_GENERATION;
-               req->req.generation = get_hpsb_generation(fi->host);
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       switch (req->req.type) {
-       case RAW1394_REQ_PHYPACKET:
-               return write_phypacket(fi, req);
-       case RAW1394_REQ_ASYNC_SEND:
-               return handle_async_send(fi, req);
-       }
-
-       if (req->req.length == 0) {
-               req->req.error = RAW1394_ERROR_INVALID_ARG;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       return handle_async_request(fi, req, node);
-}
-
-static ssize_t raw1394_write(struct file *file, const char __user * buffer,
-                            size_t count, loff_t * offset_is_ignored)
-{
-       struct file_info *fi = file->private_data;
-       struct pending_request *req;
-       ssize_t retval = -EBADFD;
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req) &&
-           sizeof(struct compat_raw1394_req) !=
-                       sizeof(struct raw1394_request)) {
-               buffer = raw1394_compat_write(buffer);
-               if (IS_ERR((__force void *)buffer))
-                       return PTR_ERR((__force void *)buffer);
-       } else
-#endif
-       if (count != sizeof(struct raw1394_request)) {
-               return -EINVAL;
-       }
-
-       req = alloc_pending_request();
-       if (req == NULL) {
-               return -ENOMEM;
-       }
-       req->file_info = fi;
-
-       if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
-               free_pending_request(req);
-               return -EFAULT;
-       }
-
-       if (!mutex_trylock(&fi->state_mutex)) {
-               free_pending_request(req);
-               return -EAGAIN;
-       }
-
-       switch (fi->state) {
-       case opened:
-               retval = state_opened(fi, req);
-               break;
-
-       case initialized:
-               retval = state_initialized(fi, req);
-               break;
-
-       case connected:
-               retval = state_connected(fi, req);
-               break;
-       }
-
-       mutex_unlock(&fi->state_mutex);
-
-       if (retval < 0) {
-               free_pending_request(req);
-       } else {
-               BUG_ON(retval);
-               retval = count;
-       }
-
-       return retval;
-}
-
-/* rawiso operations */
-
-/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the
- * completion queue (reqlists_lock must be taken) */
-static inline int __rawiso_event_in_queue(struct file_info *fi)
-{
-       struct pending_request *req;
-
-       list_for_each_entry(req, &fi->req_complete, list)
-           if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
-               return 1;
-
-       return 0;
-}
-
-/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */
-static void queue_rawiso_event(struct file_info *fi)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-
-       /* only one ISO activity event may be in the queue */
-       if (!__rawiso_event_in_queue(fi)) {
-               struct pending_request *req =
-                   __alloc_pending_request(GFP_ATOMIC);
-
-               if (req) {
-                       req->file_info = fi;
-                       req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;
-                       req->req.generation = get_hpsb_generation(fi->host);
-                       __queue_complete_req(req);
-               } else {
-                       /* on allocation failure, signal an overflow */
-                       if (fi->iso_handle) {
-                               atomic_inc(&fi->iso_handle->overflows);
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-}
-
-static void rawiso_activity_cb(struct hpsb_iso *iso)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(iso->host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (fi->iso_handle == iso)
-                               queue_rawiso_event(fi);
-               }
-       }
-
-       spin_unlock_irqrestore(&host_info_lock, flags);
-}
-
-/* helper function - gather all the kernel iso status bits for returning to user-space */
-static void raw1394_iso_fill_status(struct hpsb_iso *iso,
-                                   struct raw1394_iso_status *stat)
-{
-       int overflows = atomic_read(&iso->overflows);
-       int skips = atomic_read(&iso->skips);
-
-       stat->config.data_buf_size = iso->buf_size;
-       stat->config.buf_packets = iso->buf_packets;
-       stat->config.channel = iso->channel;
-       stat->config.speed = iso->speed;
-       stat->config.irq_interval = iso->irq_interval;
-       stat->n_packets = hpsb_iso_n_ready(iso);
-       stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF));
-       stat->xmit_cycle = iso->xmit_cycle;
-}
-
-static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-
-       if (!fi->host)
-               return -EINVAL;
-
-       if (copy_from_user(&stat, uaddr, sizeof(stat)))
-               return -EFAULT;
-
-       fi->iso_handle = hpsb_iso_xmit_init(fi->host,
-                                           stat.config.data_buf_size,
-                                           stat.config.buf_packets,
-                                           stat.config.channel,
-                                           stat.config.speed,
-                                           stat.config.irq_interval,
-                                           rawiso_activity_cb);
-       if (!fi->iso_handle)
-               return -ENOMEM;
-
-       fi->iso_state = RAW1394_ISO_XMIT;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-
-       /* queue an event to get things started */
-       rawiso_activity_cb(fi->iso_handle);
-
-       return 0;
-}
-
-static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-
-       if (!fi->host)
-               return -EINVAL;
-
-       if (copy_from_user(&stat, uaddr, sizeof(stat)))
-               return -EFAULT;
-
-       fi->iso_handle = hpsb_iso_recv_init(fi->host,
-                                           stat.config.data_buf_size,
-                                           stat.config.buf_packets,
-                                           stat.config.channel,
-                                           stat.config.dma_mode,
-                                           stat.config.irq_interval,
-                                           rawiso_activity_cb);
-       if (!fi->iso_handle)
-               return -ENOMEM;
-
-       fi->iso_state = RAW1394_ISO_RECV;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-       return 0;
-}
-
-static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-       struct hpsb_iso *iso = fi->iso_handle;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-
-       /* reset overflow counter */
-       atomic_set(&iso->overflows, 0);
-       /* reset skip counter */
-       atomic_set(&iso->skips, 0);
-
-       return 0;
-}
-
-/* copy N packet_infos out of the ringbuffer into user-supplied array */
-static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_packets upackets;
-       unsigned int packet = fi->iso_handle->first_packet;
-       int i;
-
-       if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
-               return -EFAULT;
-
-       if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))
-               return -EINVAL;
-
-       /* ensure user-supplied buffer is accessible and big enough */
-       if (!access_ok(VERIFY_WRITE, upackets.infos,
-                      upackets.n_packets *
-                      sizeof(struct raw1394_iso_packet_info)))
-               return -EFAULT;
-
-       /* copy the packet_infos out */
-       for (i = 0; i < upackets.n_packets; i++) {
-               if (__copy_to_user(&upackets.infos[i],
-                                  &fi->iso_handle->infos[packet],
-                                  sizeof(struct raw1394_iso_packet_info)))
-                       return -EFAULT;
-
-               packet = (packet + 1) % fi->iso_handle->buf_packets;
-       }
-
-       return 0;
-}
-
-/* copy N packet_infos from user to ringbuffer, and queue them for transmission */
-static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_packets upackets;
-       int i, rv;
-
-       if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
-               return -EFAULT;
-
-       if (upackets.n_packets >= fi->iso_handle->buf_packets)
-               return -EINVAL;
-
-       if (upackets.n_packets >= hpsb_iso_n_ready(fi->iso_handle))
-               return -EAGAIN;
-
-       /* ensure user-supplied buffer is accessible and big enough */
-       if (!access_ok(VERIFY_READ, upackets.infos,
-                      upackets.n_packets *
-                      sizeof(struct raw1394_iso_packet_info)))
-               return -EFAULT;
-
-       /* copy the infos structs in and queue the packets */
-       for (i = 0; i < upackets.n_packets; i++) {
-               struct raw1394_iso_packet_info info;
-
-               if (__copy_from_user(&info, &upackets.infos[i],
-                                    sizeof(struct raw1394_iso_packet_info)))
-                       return -EFAULT;
-
-               rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
-                                               info.len, info.tag, info.sy);
-               if (rv)
-                       return rv;
-       }
-
-       return 0;
-}
-
-static void raw1394_iso_shutdown(struct file_info *fi)
-{
-       if (fi->iso_handle)
-               hpsb_iso_shutdown(fi->iso_handle);
-
-       fi->iso_handle = NULL;
-       fi->iso_state = RAW1394_ISO_INACTIVE;
-}
-
-static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_cycle_timer ct;
-       int err;
-
-       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
-       if (!err)
-               if (copy_to_user(uaddr, &ct, sizeof(ct)))
-                       err = -EFAULT;
-       return err;
-}
-
-/* mmap the rawiso xmit/recv buffer */
-static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct file_info *fi = file->private_data;
-       int ret;
-
-       if (!mutex_trylock(&fi->state_mutex))
-               return -EAGAIN;
-
-       if (fi->iso_state == RAW1394_ISO_INACTIVE)
-               ret = -EINVAL;
-       else
-               ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
-
-       mutex_unlock(&fi->state_mutex);
-
-       return ret;
-}
-
-static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
-                                  void __user *argp)
-{
-       switch (cmd) {
-       case RAW1394_IOC_ISO_XMIT_INIT:
-               return raw1394_iso_xmit_init(fi, argp);
-       case RAW1394_IOC_ISO_RECV_INIT:
-               return raw1394_iso_recv_init(fi, argp);
-       default:
-               return -EINVAL;
-       }
-}
-
-static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
-                              unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-
-       switch (cmd) {
-       case RAW1394_IOC_ISO_RECV_START:{
-                       int args[3];
-
-                       if (copy_from_user(&args[0], argp, sizeof(args)))
-                               return -EFAULT;
-                       return hpsb_iso_recv_start(fi->iso_handle,
-                                                  args[0], args[1], args[2]);
-               }
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-               hpsb_iso_stop(fi->iso_handle);
-               return 0;
-       case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-               return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-               return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
-                       u64 mask;
-
-                       if (copy_from_user(&mask, argp, sizeof(mask)))
-                               return -EFAULT;
-                       return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
-                                                             mask);
-               }
-       case RAW1394_IOC_ISO_GET_STATUS:
-               return raw1394_iso_get_status(fi, argp);
-       case RAW1394_IOC_ISO_RECV_PACKETS:
-               return raw1394_iso_recv_packets(fi, argp);
-       case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-               return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_FLUSH:
-               return hpsb_iso_recv_flush(fi->iso_handle);
-       case RAW1394_IOC_ISO_SHUTDOWN:
-               raw1394_iso_shutdown(fi);
-               return 0;
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               queue_rawiso_event(fi);
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
-                              void __user *argp)
-{
-       switch (cmd) {
-       case RAW1394_IOC_ISO_XMIT_START:{
-                       int args[2];
-
-                       if (copy_from_user(&args[0], argp, sizeof(args)))
-                               return -EFAULT;
-                       return hpsb_iso_xmit_start(fi->iso_handle,
-                                                  args[0], args[1]);
-               }
-       case RAW1394_IOC_ISO_XMIT_SYNC:
-               return hpsb_iso_xmit_sync(fi->iso_handle);
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-               hpsb_iso_stop(fi->iso_handle);
-               return 0;
-       case RAW1394_IOC_ISO_GET_STATUS:
-               return raw1394_iso_get_status(fi, argp);
-       case RAW1394_IOC_ISO_XMIT_PACKETS:
-               return raw1394_iso_send_packets(fi, argp);
-       case RAW1394_IOC_ISO_SHUTDOWN:
-               raw1394_iso_shutdown(fi);
-               return 0;
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               queue_rawiso_event(fi);
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-/* ioctl is only used for rawiso operations */
-static long raw1394_ioctl(struct file *file, unsigned int cmd,
-                         unsigned long arg)
-{
-       struct file_info *fi = file->private_data;
-       void __user *argp = (void __user *)arg;
-       long ret;
-
-       /* state-independent commands */
-       switch(cmd) {
-       case RAW1394_IOC_GET_CYCLE_TIMER:
-               return raw1394_read_cycle_timer(fi, argp);
-       default:
-               break;
-       }
-
-       if (!mutex_trylock(&fi->state_mutex))
-               return -EAGAIN;
-
-       switch (fi->iso_state) {
-       case RAW1394_ISO_INACTIVE:
-               ret = raw1394_ioctl_inactive(fi, cmd, argp);
-               break;
-       case RAW1394_ISO_RECV:
-               ret = raw1394_ioctl_recv(fi, cmd, arg);
-               break;
-       case RAW1394_ISO_XMIT:
-               ret = raw1394_ioctl_xmit(fi, cmd, argp);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       mutex_unlock(&fi->state_mutex);
-
-       return ret;
-}
-
-#ifdef CONFIG_COMPAT
-struct raw1394_iso_packets32 {
-        __u32 n_packets;
-        compat_uptr_t infos;
-} __attribute__((packed));
-
-struct raw1394_cycle_timer32 {
-        __u32 cycle_timer;
-        __u64 local_time;
-}
-#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
-__attribute__((packed))
-#endif
-;
-
-#define RAW1394_IOC_ISO_RECV_PACKETS32          \
-        _IOW ('#', 0x25, struct raw1394_iso_packets32)
-#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
-        _IOW ('#', 0x27, struct raw1394_iso_packets32)
-#define RAW1394_IOC_GET_CYCLE_TIMER32           \
-        _IOR ('#', 0x30, struct raw1394_cycle_timer32)
-
-static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
-                                          struct raw1394_iso_packets32 __user *arg)
-{
-       compat_uptr_t infos32;
-       void __user *infos;
-       long err = -EFAULT;
-       struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
-
-       if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
-           !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
-               infos = compat_ptr(infos32);
-               if (!copy_to_user(&dst->infos, &infos, sizeof infos))
-                       err = raw1394_ioctl(file, cmd, (unsigned long)dst);
-       }
-       return err;
-}
-
-static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_cycle_timer32 ct;
-       int err;
-
-       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
-       if (!err)
-               if (copy_to_user(uaddr, &ct, sizeof(ct)))
-                       err = -EFAULT;
-       return err;
-}
-
-static long raw1394_compat_ioctl(struct file *file,
-                                unsigned int cmd, unsigned long arg)
-{
-       struct file_info *fi = file->private_data;
-       void __user *argp = (void __user *)arg;
-       long err;
-
-       switch (cmd) {
-       /* These requests have same format as long as 'int' has same size. */
-       case RAW1394_IOC_ISO_RECV_INIT:
-       case RAW1394_IOC_ISO_RECV_START:
-       case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-       case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-       case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
-       case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-       case RAW1394_IOC_ISO_RECV_FLUSH:
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-       case RAW1394_IOC_ISO_XMIT_INIT:
-       case RAW1394_IOC_ISO_XMIT_START:
-       case RAW1394_IOC_ISO_XMIT_SYNC:
-       case RAW1394_IOC_ISO_GET_STATUS:
-       case RAW1394_IOC_ISO_SHUTDOWN:
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               err = raw1394_ioctl(file, cmd, arg);
-               break;
-       /* These request have different format. */
-       case RAW1394_IOC_ISO_RECV_PACKETS32:
-               err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
-               break;
-       case RAW1394_IOC_ISO_XMIT_PACKETS32:
-               err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
-               break;
-       case RAW1394_IOC_GET_CYCLE_TIMER32:
-               err = raw1394_read_cycle_timer32(fi, argp);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-
-       return err;
-}
-#endif
-
-static unsigned int raw1394_poll(struct file *file, poll_table * pt)
-{
-       struct file_info *fi = file->private_data;
-       unsigned int mask = POLLOUT | POLLWRNORM;
-       unsigned long flags;
-
-       poll_wait(file, &fi->wait_complete, pt);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       if (!list_empty(&fi->req_complete)) {
-               mask |= POLLIN | POLLRDNORM;
-       }
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       return mask;
-}
-
-static int raw1394_open(struct inode *inode, struct file *file)
-{
-       struct file_info *fi;
-
-       fi = kzalloc(sizeof(*fi), GFP_KERNEL);
-       if (!fi)
-               return -ENOMEM;
-
-       fi->notification = (u8) RAW1394_NOTIFY_ON;      /* busreset notification */
-
-       INIT_LIST_HEAD(&fi->list);
-       mutex_init(&fi->state_mutex);
-       fi->state = opened;
-       INIT_LIST_HEAD(&fi->req_pending);
-       INIT_LIST_HEAD(&fi->req_complete);
-       spin_lock_init(&fi->reqlists_lock);
-       init_waitqueue_head(&fi->wait_complete);
-       INIT_LIST_HEAD(&fi->addr_list);
-
-       file->private_data = fi;
-
-       return nonseekable_open(inode, file);
-}
-
-static int raw1394_release(struct inode *inode, struct file *file)
-{
-       struct file_info *fi = file->private_data;
-       struct list_head *lh;
-       struct pending_request *req;
-       int i, fail;
-       int retval = 0;
-       struct list_head *entry;
-       struct arm_addr *addr = NULL;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct arm_addr *arm_addr = NULL;
-       int another_host;
-       int csr_mod = 0;
-       unsigned long flags;
-
-       if (fi->iso_state != RAW1394_ISO_INACTIVE)
-               raw1394_iso_shutdown(fi);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-
-       fail = 0;
-       /* set address-entries invalid */
-
-       while (!list_empty(&fi->addr_list)) {
-               another_host = 0;
-               lh = fi->addr_list.next;
-               addr = list_entry(lh, struct arm_addr, addr_list);
-               /* another host with valid address-entry containing
-                  same addressrange? */
-               list_for_each_entry(hi, &host_info_list, list) {
-                       if (hi->host != fi->host) {
-                               list_for_each_entry(fi_hlp, &hi->file_info_list,
-                                                   list) {
-                                       entry = fi_hlp->addr_list.next;
-                                       while (entry != &(fi_hlp->addr_list)) {
-                                               arm_addr = list_entry(entry, struct
-                                                                     arm_addr,
-                                                                     addr_list);
-                                               if (arm_addr->start ==
-                                                   addr->start) {
-                                                       DBGMSG
-                                                           ("raw1394_release: "
-                                                            "another host ownes "
-                                                            "same addressrange");
-                                                       another_host = 1;
-                                                       break;
-                                               }
-                                               entry = entry->next;
-                                       }
-                                       if (another_host) {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               if (!another_host) {
-                       DBGMSG("raw1394_release: call hpsb_arm_unregister");
-                       retval =
-                           hpsb_unregister_addrspace(&raw1394_highlevel,
-                                                     fi->host, addr->start);
-                       if (!retval) {
-                               ++fail;
-                               printk(KERN_ERR
-                                      "raw1394_release arm_Unregister failed\n");
-                       }
-               }
-               DBGMSG("raw1394_release: delete addr_entry from list");
-               list_del(&addr->addr_list);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-       }                       /* while */
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       if (fail > 0) {
-               printk(KERN_ERR "raw1394: during addr_list-release "
-                      "error(s) occurred \n");
-       }
-
-       for (;;) {
-               /* This locked section guarantees that neither
-                * complete nor pending requests exist once i!=0 */
-               spin_lock_irqsave(&fi->reqlists_lock, flags);
-               while ((req = __next_complete_req(fi)))
-                       free_pending_request(req);
-
-               i = list_empty(&fi->req_pending);
-               spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-               if (i)
-                       break;
-               /*
-                * Sleep until more requests can be freed.
-                *
-                * NB: We call the macro wait_event() with a condition argument
-                * with side effect.  This is only possible because the side
-                * effect does not occur until the condition became true, and
-                * wait_event() won't evaluate the condition again after that.
-                */
-               wait_event(fi->wait_complete, (req = next_complete_req(fi)));
-               free_pending_request(req);
-       }
-
-       /* Remove any sub-trees left by user space programs */
-       for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
-               struct csr1212_dentry *dentry;
-               if (!fi->csr1212_dirs[i])
-                       continue;
-               for (dentry =
-                    fi->csr1212_dirs[i]->value.directory.dentries_head; dentry;
-                    dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-               csr1212_release_keyval(fi->csr1212_dirs[i]);
-               fi->csr1212_dirs[i] = NULL;
-               csr_mod = 1;
-       }
-
-       if ((csr_mod || fi->cfgrom_upd)
-           && hpsb_update_config_rom_image(fi->host) < 0)
-               HPSB_ERR
-                   ("Failed to generate Configuration ROM image for host %d",
-                    fi->host->id);
-
-       if (fi->state == connected) {
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_del(&fi->list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               put_device(&fi->host->device);
-       }
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       if (fi->host)
-               module_put(fi->host->driver->owner);
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       kfree(fi);
-
-       return 0;
-}
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id raw1394_id_table[] = {
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = AVC_SW_VERSION_ENTRY & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = CAMERA_SW_VERSION_ENTRY & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff},
-       {}
-};
-
-MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver raw1394_driver = {
-       .name = "raw1394",
-};
-
-/******************************************************************************/
-
-static struct hpsb_highlevel raw1394_highlevel = {
-       .name = RAW1394_DEVICE_NAME,
-       .add_host = add_host,
-       .remove_host = remove_host,
-       .host_reset = host_reset,
-       .fcp_request = fcp_request,
-};
-
-static struct cdev raw1394_cdev;
-static const struct file_operations raw1394_fops = {
-       .owner = THIS_MODULE,
-       .read = raw1394_read,
-       .write = raw1394_write,
-       .mmap = raw1394_mmap,
-       .unlocked_ioctl = raw1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = raw1394_compat_ioctl,
-#endif
-       .poll = raw1394_poll,
-       .open = raw1394_open,
-       .release = raw1394_release,
-       .llseek = no_llseek,
-};
-
-static int __init init_raw1394(void)
-{
-       int ret = 0;
-
-       hpsb_register_highlevel(&raw1394_highlevel);
-
-       if (IS_ERR
-           (device_create(hpsb_protocol_class, NULL,
-                          MKDEV(IEEE1394_MAJOR,
-                                IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-                          NULL, RAW1394_DEVICE_NAME))) {
-               ret = -EFAULT;
-               goto out_unreg;
-       }
-
-       cdev_init(&raw1394_cdev, &raw1394_fops);
-       raw1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
-       if (ret) {
-               HPSB_ERR("raw1394 failed to register minor device block");
-               goto out_dev;
-       }
-
-       HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
-
-       ret = hpsb_register_protocol(&raw1394_driver);
-       if (ret) {
-               HPSB_ERR("raw1394: failed to register protocol");
-               cdev_del(&raw1394_cdev);
-               goto out_dev;
-       }
-
-       goto out;
-
-      out_dev:
-       device_destroy(hpsb_protocol_class,
-                      MKDEV(IEEE1394_MAJOR,
-                            IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-      out_unreg:
-       hpsb_unregister_highlevel(&raw1394_highlevel);
-      out:
-       return ret;
-}
-
-static void __exit cleanup_raw1394(void)
-{
-       device_destroy(hpsb_protocol_class,
-                      MKDEV(IEEE1394_MAJOR,
-                            IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-       cdev_del(&raw1394_cdev);
-       hpsb_unregister_highlevel(&raw1394_highlevel);
-       hpsb_unregister_protocol(&raw1394_driver);
-}
-
-module_init(init_raw1394);
-module_exit(cleanup_raw1394);
-MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
deleted file mode 100644 (file)
index 963ac20..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#ifndef IEEE1394_RAW1394_H
-#define IEEE1394_RAW1394_H
-
-/* header for the raw1394 API that is exported to user-space */
-
-#define RAW1394_KERNELAPI_VERSION 4
-
-/* state: opened */
-#define RAW1394_REQ_INITIALIZE    1
-
-/* state: initialized */
-#define RAW1394_REQ_LIST_CARDS    2
-#define RAW1394_REQ_SET_CARD      3
-
-/* state: connected */
-#define RAW1394_REQ_ASYNC_READ      100
-#define RAW1394_REQ_ASYNC_WRITE     101
-#define RAW1394_REQ_LOCK            102
-#define RAW1394_REQ_LOCK64          103
-#define RAW1394_REQ_ISO_SEND        104 /* removed ABI, now a no-op */
-#define RAW1394_REQ_ASYNC_SEND      105
-#define RAW1394_REQ_ASYNC_STREAM    106
-
-#define RAW1394_REQ_ISO_LISTEN      200 /* removed ABI, now a no-op */
-#define RAW1394_REQ_FCP_LISTEN      201
-#define RAW1394_REQ_RESET_BUS       202
-#define RAW1394_REQ_GET_ROM         203
-#define RAW1394_REQ_UPDATE_ROM      204
-#define RAW1394_REQ_ECHO            205
-#define RAW1394_REQ_MODIFY_ROM      206
-
-#define RAW1394_REQ_ARM_REGISTER    300
-#define RAW1394_REQ_ARM_UNREGISTER  301
-#define RAW1394_REQ_ARM_SET_BUF     302
-#define RAW1394_REQ_ARM_GET_BUF     303
-
-#define RAW1394_REQ_RESET_NOTIFY    400
-
-#define RAW1394_REQ_PHYPACKET       500
-
-/* kernel to user */
-#define RAW1394_REQ_BUS_RESET        10000
-#define RAW1394_REQ_ISO_RECEIVE      10001
-#define RAW1394_REQ_FCP_REQUEST      10002
-#define RAW1394_REQ_ARM              10003
-#define RAW1394_REQ_RAWISO_ACTIVITY  10004
-
-/* error codes */
-#define RAW1394_ERROR_NONE        0
-#define RAW1394_ERROR_COMPAT      (-1001)
-#define RAW1394_ERROR_STATE_ORDER (-1002)
-#define RAW1394_ERROR_GENERATION  (-1003)
-#define RAW1394_ERROR_INVALID_ARG (-1004)
-#define RAW1394_ERROR_MEMFAULT    (-1005)
-#define RAW1394_ERROR_ALREADY     (-1006)
-
-#define RAW1394_ERROR_EXCESSIVE   (-1020)
-#define RAW1394_ERROR_UNTIDY_LEN  (-1021)
-
-#define RAW1394_ERROR_SEND_ERROR  (-1100)
-#define RAW1394_ERROR_ABORTED     (-1101)
-#define RAW1394_ERROR_TIMEOUT     (-1102)
-
-/* arm_codes */
-#define ARM_READ   1
-#define ARM_WRITE  2
-#define ARM_LOCK   4
-
-#define RAW1394_LONG_RESET  0
-#define RAW1394_SHORT_RESET 1
-
-/* busresetnotify ... */
-#define RAW1394_NOTIFY_OFF 0
-#define RAW1394_NOTIFY_ON  1
-
-#include <asm/types.h>
-
-struct raw1394_request {
-        __u32 type;
-        __s32 error;
-        __u32 misc;
-
-        __u32 generation;
-        __u32 length;
-
-        __u64 address;
-
-        __u64 tag;
-
-        __u64 sendb;
-        __u64 recvb;
-};
-
-struct raw1394_khost_list {
-        __u32 nodes;
-        __u8 name[32];
-};
-
-typedef struct arm_request {
-        __u16           destination_nodeid;
-        __u16           source_nodeid;
-        __u64           destination_offset;
-        __u8            tlabel;
-        __u8            tcode;
-        __u8            extended_transaction_code;
-        __u32           generation;
-        __u16           buffer_length;
-        __u8            __user *buffer;
-} *arm_request_t;
-
-typedef struct arm_response {
-        __s32           response_code;
-        __u16           buffer_length;
-        __u8            __user *buffer;
-} *arm_response_t;
-
-typedef struct arm_request_response {
-        struct arm_request  __user *request;
-        struct arm_response __user *response;
-} *arm_request_response_t;
-
-/* rawiso API */
-#include "ieee1394-ioctl.h"
-
-/* per-packet metadata embedded in the ringbuffer */
-/* must be identical to hpsb_iso_packet_info in iso.h! */
-struct raw1394_iso_packet_info {
-       __u32 offset;
-       __u16 len;
-       __u16 cycle;   /* recv only */
-       __u8  channel; /* recv only */
-       __u8  tag;
-       __u8  sy;
-};
-
-/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */
-struct raw1394_iso_packets {
-       __u32 n_packets;
-       struct raw1394_iso_packet_info __user *infos;
-};
-
-struct raw1394_iso_config {
-       /* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */
-       __u32 data_buf_size;
-
-       /* # of packets to buffer */
-       __u32 buf_packets;
-
-       /* iso channel (set to -1 for multi-channel recv) */
-       __s32 channel;
-
-       /* xmit only - iso transmission speed */
-       __u8 speed;
-
-       /* The mode of the dma when receiving iso data. Must be supported by chip */
-       __u8 dma_mode;
-
-       /* max. latency of buffer, in packets (-1 if you don't care) */
-       __s32 irq_interval;
-};
-
-/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */
-struct raw1394_iso_status {
-       /* current settings */
-       struct raw1394_iso_config config;
-
-       /* number of packets waiting to be filled with data (ISO transmission)
-          or containing data received (ISO reception) */
-       __u32 n_packets;
-
-       /* approximate number of packets dropped due to overflow or
-          underflow of the packet buffer (a value of zero guarantees
-          that no packets have been dropped) */
-       __u32 overflows;
-
-       /* cycle number at which next packet will be transmitted;
-          -1 if not known */
-       __s16 xmit_cycle;
-};
-
-/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
-struct raw1394_cycle_timer {
-       /* contents of Isochronous Cycle Timer register,
-          as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
-       __u32 cycle_timer;
-
-       /* local time in microseconds since Epoch,
-          simultaneously read with cycle timer */
-       __u64 local_time;
-};
-#endif /* IEEE1394_RAW1394_H */
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
deleted file mode 100644 (file)
index d6e251a..0000000
+++ /dev/null
@@ -1,2138 +0,0 @@
-/*
- * sbp2.c - SBP-2 protocol driver for IEEE-1394
- *
- * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com)
- * jamesg@filanet.com (JSG)
- *
- * Copyright (C) 2003 Ben Collins <bcollins@debian.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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Brief Description:
- *
- * This driver implements the Serial Bus Protocol 2 (SBP-2) over IEEE-1394
- * under Linux. The SBP-2 driver is implemented as an IEEE-1394 high-level
- * driver. It also registers as a SCSI lower-level driver in order to accept
- * SCSI commands for transport using SBP-2.
- *
- * You may access any attached SBP-2 (usually storage devices) as regular
- * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc..
- *
- * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2
- * specification and for where to purchase the official standard.
- *
- * TODO:
- *   - look into possible improvements of the SCSI error handlers
- *   - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size
- *   - handle Logical_Unit_Number.ordered
- *   - handle src == 1 in status blocks
- *   - reimplement the DMA mapping in absence of physical DMA so that
- *     bus_to_virt is no longer required
- *   - debug the handling of absent physical DMA
- *   - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection
- *     (this is easy but depends on the previous two TODO items)
- *   - make the parameter serialize_io configurable per device
- *   - move all requests to fetch agent registers into non-atomic context,
- *     replace all usages of sbp2util_node_write_no_wait by true transactions
- * Grep for inline FIXME comments below.
- */
-
-#include <linux/blkdev.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/scatterlist.h>
-
-#include <asm/byteorder.h>
-#include <asm/errno.h>
-#include <asm/param.h>
-#include <asm/system.h>
-#include <asm/types.h>
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-#include <asm/io.h> /* for bus_to_virt */
-#endif
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-
-#include "csr1212.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "sbp2.h"
-
-/*
- * Module load parameter definitions
- */
-
-/*
- * Change max_speed on module load if you have a bad IEEE-1394
- * controller that has trouble running 2KB packets at 400mb.
- *
- * NOTE: On certain OHCI parts I have seen short packets on async transmit
- * (probably due to PCI latency/throughput issues with the part). You can
- * bump down the speed if you are running into problems.
- */
-static int sbp2_max_speed = IEEE1394_SPEED_MAX;
-module_param_named(max_speed, sbp2_max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Limit data transfer speed (5 <= 3200, "
-                "4 <= 1600, 3 <= 800, 2 <= 400, 1 <= 200, 0 = 100 Mb/s)");
-
-/*
- * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
- * This is and always has been buggy in multiple subtle ways. See above TODOs.
- */
-static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
-                "(default = Y, faster but buggy = N)");
-
-/*
- * Adjust max_sectors if you'd like to influence how many sectors each SCSI
- * command can transfer at most. Please note that some older SBP-2 bridge
- * chips are broken for transfers greater or equal to 128KB, therefore
- * max_sectors used to be a safe 255 sectors for many years. We now have a
- * default of 0 here which means that we let the SCSI stack choose a limit.
- *
- * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds
- * module parameter or in the sbp2_workarounds_table[], will override the
- * value of max_sectors. We should use sbp2_workarounds_table[] to cover any
- * bridge chip which becomes known to need the 255 sectors limit.
- */
-static int sbp2_max_sectors;
-module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
-                "(default = 0 = use SCSI stack's default)");
-
-/*
- * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
- * do an exclusive login, as it's generally unsafe to have two hosts
- * talking to a single sbp2 device at the same time (filesystem coherency,
- * etc.). If you're running an sbp2 device that supports multiple logins,
- * and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster
- * File System, or Lustre, then set exclusive_login to zero.
- *
- * So far only bridges from Oxford Semiconductor are known to support
- * concurrent logins. Depending on firmware, four or two concurrent logins
- * are possible on OXFW911 and newer Oxsemi bridges.
- */
-static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
-MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-                "(default = Y, use N for concurrent initiators)");
-
-/*
- * If any of the following workarounds is required for your device to work,
- * please submit the kernel messages logged by sbp2 to the linux1394-devel
- * mailing list.
- *
- * - 128kB max transfer
- *   Limit transfer size. Necessary for some old bridges.
- *
- * - 36 byte inquiry
- *   When scsi_mod probes the device, let the inquiry command look like that
- *   from MS Windows.
- *
- * - skip mode page 8
- *   Suppress sending of mode_sense for mode page 8 if the device pretends to
- *   support the SCSI Primary Block commands instead of Reduced Block Commands.
- *
- * - fix capacity
- *   Tell sd_mod to correct the last sector number reported by read_capacity.
- *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
- *   Don't use this with devices which don't have this bug.
- *
- * - delay inquiry
- *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
- *
- * - power condition
- *   Set the power condition field in the START STOP UNIT commands sent by
- *   sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
- *   Some disks need this to spin down or to resume properly.
- *
- * - override internal blacklist
- *   Instead of adding to the built-in blacklist, use only the workarounds
- *   specified in the module load parameter.
- *   Useful if a blacklist entry interfered with a non-broken device.
- */
-static int sbp2_default_workarounds;
-module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
-MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
-       ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
-       ", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
-       ", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
-       ", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
-       ", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
-       ", set power condition in start stop unit = "
-                                 __stringify(SBP2_WORKAROUND_POWER_CONDITION)
-       ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
-       ", or a combination)");
-
-/*
- * This influences the format of the sysfs attribute
- * /sys/bus/scsi/devices/.../ieee1394_id.
- *
- * The default format is like in older kernels:  %016Lx:%d:%d
- * It contains the target's EUI-64, a number given to the logical unit by
- * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
- *
- * The long format is:  %016Lx:%06x:%04x
- * It contains the target's EUI-64, the unit directory's directory_ID as per
- * IEEE 1212 clause 7.7.19, and the LUN.  This format comes closest to the
- * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
- * Architecture Model) rev.2 to 4 annex A.  Therefore and because it is
- * independent of the implementation of the ieee1394 nodemgr, the longer format
- * is recommended for future use.
- */
-static int sbp2_long_sysfs_ieee1394_id;
-module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
-MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
-                "(default = backwards-compatible = N, SAM-conforming = Y)");
-
-
-#define SBP2_INFO(fmt, args...)        HPSB_INFO("sbp2: "fmt, ## args)
-#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
-
-/*
- * Globals
- */
-static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32);
-static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *,
-                                     void (*)(struct scsi_cmnd *));
-static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *);
-static int sbp2_start_device(struct sbp2_lu *);
-static void sbp2_remove_device(struct sbp2_lu *);
-static int sbp2_login_device(struct sbp2_lu *);
-static int sbp2_reconnect_device(struct sbp2_lu *);
-static int sbp2_logout_device(struct sbp2_lu *);
-static void sbp2_host_reset(struct hpsb_host *);
-static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *,
-                                   u64, size_t, u16);
-static int sbp2_agent_reset(struct sbp2_lu *, int);
-static void sbp2_parse_unit_directory(struct sbp2_lu *,
-                                     struct unit_directory *);
-static int sbp2_set_busy_timeout(struct sbp2_lu *);
-static int sbp2_max_speed_and_size(struct sbp2_lu *);
-
-
-static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xa, 0xa, 0xa };
-
-static DEFINE_RWLOCK(sbp2_hi_logical_units_lock);
-
-static struct hpsb_highlevel sbp2_highlevel = {
-       .name           = SBP2_DEVICE_NAME,
-       .host_reset     = sbp2_host_reset,
-};
-
-static const struct hpsb_address_ops sbp2_ops = {
-       .write          = sbp2_handle_status_write
-};
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *,
-                                    u64, size_t, u16);
-static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64,
-                                   size_t, u16);
-
-static const struct hpsb_address_ops sbp2_physdma_ops = {
-       .read           = sbp2_handle_physdma_read,
-       .write          = sbp2_handle_physdma_write,
-};
-#endif
-
-
-/*
- * Interface to driver core and IEEE 1394 core
- */
-static const struct ieee1394_device_id sbp2_id_table[] = {
-       {
-        .match_flags   = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id  = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version       = SBP2_SW_VERSION_ENTRY & 0xffffff},
-       {}
-};
-MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
-
-static int sbp2_probe(struct device *);
-static int sbp2_remove(struct device *);
-static int sbp2_update(struct unit_directory *);
-
-static struct hpsb_protocol_driver sbp2_driver = {
-       .name           = SBP2_DEVICE_NAME,
-       .id_table       = sbp2_id_table,
-       .update         = sbp2_update,
-       .driver         = {
-               .probe          = sbp2_probe,
-               .remove         = sbp2_remove,
-       },
-};
-
-
-/*
- * Interface to SCSI core
- */
-static int sbp2scsi_queuecommand(struct scsi_cmnd *,
-                                void (*)(struct scsi_cmnd *));
-static int sbp2scsi_abort(struct scsi_cmnd *);
-static int sbp2scsi_reset(struct scsi_cmnd *);
-static int sbp2scsi_slave_alloc(struct scsi_device *);
-static int sbp2scsi_slave_configure(struct scsi_device *);
-static void sbp2scsi_slave_destroy(struct scsi_device *);
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *,
-                                          struct device_attribute *, char *);
-
-static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
-
-static struct device_attribute *sbp2_sysfs_sdev_attrs[] = {
-       &dev_attr_ieee1394_id,
-       NULL
-};
-
-static struct scsi_host_template sbp2_shost_template = {
-       .module                  = THIS_MODULE,
-       .name                    = "SBP-2 IEEE-1394",
-       .proc_name               = SBP2_DEVICE_NAME,
-       .queuecommand            = sbp2scsi_queuecommand,
-       .eh_abort_handler        = sbp2scsi_abort,
-       .eh_device_reset_handler = sbp2scsi_reset,
-       .slave_alloc             = sbp2scsi_slave_alloc,
-       .slave_configure         = sbp2scsi_slave_configure,
-       .slave_destroy           = sbp2scsi_slave_destroy,
-       .this_id                 = -1,
-       .sg_tablesize            = SG_ALL,
-       .use_clustering          = ENABLE_CLUSTERING,
-       .cmd_per_lun             = SBP2_MAX_CMDS,
-       .can_queue               = SBP2_MAX_CMDS,
-       .sdev_attrs              = sbp2_sysfs_sdev_attrs,
-};
-
-#define SBP2_ROM_VALUE_WILDCARD ~0         /* match all */
-#define SBP2_ROM_VALUE_MISSING  0xff000000 /* not present in the unit dir. */
-
-/*
- * List of devices with known bugs.
- *
- * The firmware_revision field, masked with 0xffff00, is the best indicator
- * for the type of bridge chip of a device.  It yields a few false positives
- * but this did not break correctly behaving devices so far.
- */
-static const struct {
-       u32 firmware_revision;
-       u32 model;
-       unsigned workarounds;
-} sbp2_workarounds_table[] = {
-       /* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
-               .firmware_revision      = 0x002800,
-               .model                  = 0x001010,
-               .workarounds            = SBP2_WORKAROUND_INQUIRY_36 |
-                                         SBP2_WORKAROUND_MODE_SENSE_8 |
-                                         SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
-               .firmware_revision      = 0x002800,
-               .model                  = 0x000000,
-               .workarounds            = SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* Initio bridges, actually only needed for some older ones */ {
-               .firmware_revision      = 0x000200,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_INQUIRY_36,
-       },
-       /* PL-3507 bridge with Prolific firmware */ {
-               .firmware_revision      = 0x012800,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* Symbios bridge */ {
-               .firmware_revision      = 0xa0b800,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
-       },
-       /* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
-               .firmware_revision      = 0x002600,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
-       },
-       /*
-        * iPod 2nd generation: needs 128k max transfer size workaround
-        * iPod 3rd generation: needs fix capacity workaround
-        */
-       {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000000,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS |
-                                         SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod 4th generation */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000021,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod mini */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000022,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod mini */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000023,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod Photo */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x00007e,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       }
-};
-
-/**************************************
- * General utility functions
- **************************************/
-
-#ifndef __BIG_ENDIAN
-/*
- * Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
- */
-static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
-{
-       u32 *temp = buffer;
-
-       for (length = (length >> 2); length--; )
-               temp[length] = be32_to_cpu(temp[length]);
-}
-
-/*
- * Converts a buffer from cpu to be32 byte ordering. Length is in bytes.
- */
-static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
-{
-       u32 *temp = buffer;
-
-       for (length = (length >> 2); length--; )
-               temp[length] = cpu_to_be32(temp[length]);
-}
-#else /* BIG_ENDIAN */
-/* Why waste the cpu cycles? */
-#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0)
-#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq);
-
-/*
- * Waits for completion of an SBP-2 access request.
- * Returns nonzero if timed out or prematurely interrupted.
- */
-static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout)
-{
-       long leftover;
-
-       leftover = wait_event_interruptible_timeout(
-                       sbp2_access_wq, lu->access_complete, timeout);
-       lu->access_complete = 0;
-       return leftover <= 0;
-}
-
-static void sbp2_free_packet(void *packet)
-{
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-}
-
-/*
- * This is much like hpsb_node_write(), except it ignores the response
- * subaction and returns immediately. Can be used from atomic context.
- */
-static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
-                                      quadlet_t *buf, size_t len)
-{
-       struct hpsb_packet *packet;
-
-       packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len);
-       if (!packet)
-               return -ENOMEM;
-
-       hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet);
-       hpsb_node_fill_packet(ne, packet);
-       if (hpsb_send_packet(packet) < 0) {
-               sbp2_free_packet(packet);
-               return -EIO;
-       }
-       return 0;
-}
-
-static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset,
-                                       quadlet_t *data, size_t len)
-{
-       /* There is a small window after a bus reset within which the node
-        * entry's generation is current but the reconnect wasn't completed. */
-       if (unlikely(atomic_read(&lu->state) == SBP2LU_STATE_IN_RESET))
-               return;
-
-       if (hpsb_node_write(lu->ne, lu->command_block_agent_addr + offset,
-                           data, len))
-               SBP2_ERR("sbp2util_notify_fetch_agent failed.");
-
-       /* Now accept new SCSI commands, unless a bus reset happended during
-        * hpsb_node_write. */
-       if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_RESET))
-               scsi_unblock_requests(lu->shost);
-}
-
-static void sbp2util_write_orb_pointer(struct work_struct *work)
-{
-       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
-       quadlet_t data[2];
-
-       data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id);
-       data[1] = lu->last_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-       sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8);
-}
-
-static void sbp2util_write_doorbell(struct work_struct *work)
-{
-       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
-
-       sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4);
-}
-
-static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
-{
-       struct sbp2_command_info *cmd;
-       struct device *dmadev = lu->hi->host->device.parent;
-       int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
-
-       for (i = 0; i < orbs; i++) {
-               cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-               if (!cmd)
-                       goto failed_alloc;
-
-               cmd->command_orb_dma =
-                   dma_map_single(dmadev, &cmd->command_orb,
-                                  sizeof(struct sbp2_command_orb),
-                                  DMA_TO_DEVICE);
-               if (dma_mapping_error(dmadev, cmd->command_orb_dma))
-                       goto failed_orb;
-
-               cmd->sge_dma =
-                   dma_map_single(dmadev, &cmd->scatter_gather_element,
-                                  sizeof(cmd->scatter_gather_element),
-                                  DMA_TO_DEVICE);
-               if (dma_mapping_error(dmadev, cmd->sge_dma))
-                       goto failed_sge;
-
-               INIT_LIST_HEAD(&cmd->list);
-               list_add_tail(&cmd->list, &lu->cmd_orb_completed);
-       }
-       return 0;
-
-failed_sge:
-       dma_unmap_single(dmadev, cmd->command_orb_dma,
-                        sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-failed_orb:
-       kfree(cmd);
-failed_alloc:
-       return -ENOMEM;
-}
-
-static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
-                                            struct hpsb_host *host)
-{
-       struct list_head *lh, *next;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_completed))
-               list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
-                       cmd = list_entry(lh, struct sbp2_command_info, list);
-                       dma_unmap_single(host->device.parent,
-                                        cmd->command_orb_dma,
-                                        sizeof(struct sbp2_command_orb),
-                                        DMA_TO_DEVICE);
-                       dma_unmap_single(host->device.parent, cmd->sge_dma,
-                                        sizeof(cmd->scatter_gather_element),
-                                        DMA_TO_DEVICE);
-                       kfree(cmd);
-               }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return;
-}
-
-/*
- * Finds the sbp2_command for a given outstanding command ORB.
- * Only looks at the in-use list.
- */
-static struct sbp2_command_info *sbp2util_find_command_for_orb(
-                               struct sbp2_lu *lu, dma_addr_t orb)
-{
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_inuse))
-               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
-                       if (cmd->command_orb_dma == orb) {
-                               spin_unlock_irqrestore(
-                                               &lu->cmd_orb_lock, flags);
-                               return cmd;
-                       }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return NULL;
-}
-
-/*
- * Finds the sbp2_command for a given outstanding SCpnt.
- * Only looks at the in-use list.
- * Must be called with lu->cmd_orb_lock held.
- */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
-                               struct sbp2_lu *lu, void *SCpnt)
-{
-       struct sbp2_command_info *cmd;
-
-       if (!list_empty(&lu->cmd_orb_inuse))
-               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
-                       if (cmd->Current_SCpnt == SCpnt)
-                               return cmd;
-       return NULL;
-}
-
-static struct sbp2_command_info *sbp2util_allocate_command_orb(
-                               struct sbp2_lu *lu,
-                               struct scsi_cmnd *Current_SCpnt,
-                               void (*Current_done)(struct scsi_cmnd *))
-{
-       struct list_head *lh;
-       struct sbp2_command_info *cmd = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_completed)) {
-               lh = lu->cmd_orb_completed.next;
-               list_del(lh);
-               cmd = list_entry(lh, struct sbp2_command_info, list);
-               cmd->Current_done = Current_done;
-               cmd->Current_SCpnt = Current_SCpnt;
-               list_add_tail(&cmd->list, &lu->cmd_orb_inuse);
-       } else
-               SBP2_ERR("%s: no orbs available", __func__);
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return cmd;
-}
-
-/*
- * Unmaps the DMAs of a command and moves the command to the completed ORB list.
- * Must be called with lu->cmd_orb_lock held.
- */
-static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
-                                           struct sbp2_command_info *cmd)
-{
-       if (scsi_sg_count(cmd->Current_SCpnt))
-               dma_unmap_sg(lu->ud->ne->host->device.parent,
-                            scsi_sglist(cmd->Current_SCpnt),
-                            scsi_sg_count(cmd->Current_SCpnt),
-                            cmd->Current_SCpnt->sc_data_direction);
-       list_move_tail(&cmd->list, &lu->cmd_orb_completed);
-}
-
-/*
- * Is lu valid? Is the 1394 node still present?
- */
-static inline int sbp2util_node_is_available(struct sbp2_lu *lu)
-{
-       return lu && lu->ne && !lu->ne->in_limbo;
-}
-
-/*********************************************
- * IEEE-1394 core driver stack related section
- *********************************************/
-
-static int sbp2_probe(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct sbp2_lu *lu;
-
-       ud = container_of(dev, struct unit_directory, device);
-
-       /* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)
-        * instead. */
-       if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
-               return -ENODEV;
-
-       lu = sbp2_alloc_device(ud);
-       if (!lu)
-               return -ENOMEM;
-
-       sbp2_parse_unit_directory(lu, ud);
-       return sbp2_start_device(lu);
-}
-
-static int sbp2_remove(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct sbp2_lu *lu;
-       struct scsi_device *sdev;
-
-       ud = container_of(dev, struct unit_directory, device);
-       lu = dev_get_drvdata(&ud->device);
-       if (!lu)
-               return 0;
-
-       if (lu->shost) {
-               /* Get rid of enqueued commands if there is no chance to
-                * send them. */
-               if (!sbp2util_node_is_available(lu))
-                       sbp2scsi_complete_all_commands(lu, DID_NO_CONNECT);
-               /* scsi_remove_device() may trigger shutdown functions of SCSI
-                * highlevel drivers which would deadlock if blocked. */
-               atomic_set(&lu->state, SBP2LU_STATE_IN_SHUTDOWN);
-               scsi_unblock_requests(lu->shost);
-       }
-       sdev = lu->sdev;
-       if (sdev) {
-               lu->sdev = NULL;
-               scsi_remove_device(sdev);
-       }
-
-       sbp2_logout_device(lu);
-       sbp2_remove_device(lu);
-
-       return 0;
-}
-
-static int sbp2_update(struct unit_directory *ud)
-{
-       struct sbp2_lu *lu = dev_get_drvdata(&ud->device);
-
-       if (sbp2_reconnect_device(lu) != 0) {
-               /*
-                * Reconnect failed.  If another bus reset happened,
-                * let nodemgr proceed and call sbp2_update again later
-                * (or sbp2_remove if this node went away).
-                */
-               if (!hpsb_node_entry_valid(lu->ne))
-                       return 0;
-               /*
-                * Or the target rejected the reconnect because we weren't
-                * fast enough.  Try a regular login, but first log out
-                * just in case of any weirdness.
-                */
-               sbp2_logout_device(lu);
-
-               if (sbp2_login_device(lu) != 0) {
-                       if (!hpsb_node_entry_valid(lu->ne))
-                               return 0;
-
-                       /* Maybe another initiator won the login. */
-                       SBP2_ERR("Failed to reconnect to sbp2 device!");
-                       return -EBUSY;
-               }
-       }
-
-       sbp2_set_busy_timeout(lu);
-       sbp2_agent_reset(lu, 1);
-       sbp2_max_speed_and_size(lu);
-
-       /* Complete any pending commands with busy (so they get retried)
-        * and remove them from our queue. */
-       sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
-
-       /* Accept new commands unless there was another bus reset in the
-        * meantime. */
-       if (hpsb_node_entry_valid(lu->ne)) {
-               atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
-               scsi_unblock_requests(lu->shost);
-       }
-       return 0;
-}
-
-static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
-{
-       struct sbp2_fwhost_info *hi;
-       struct Scsi_Host *shost = NULL;
-       struct sbp2_lu *lu = NULL;
-       unsigned long flags;
-
-       lu = kzalloc(sizeof(*lu), GFP_KERNEL);
-       if (!lu) {
-               SBP2_ERR("failed to create lu");
-               goto failed_alloc;
-       }
-
-       lu->ne = ud->ne;
-       lu->ud = ud;
-       lu->speed_code = IEEE1394_SPEED_100;
-       lu->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
-       lu->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
-       INIT_LIST_HEAD(&lu->cmd_orb_inuse);
-       INIT_LIST_HEAD(&lu->cmd_orb_completed);
-       INIT_LIST_HEAD(&lu->lu_list);
-       spin_lock_init(&lu->cmd_orb_lock);
-       atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
-       INIT_WORK(&lu->protocol_work, NULL);
-
-       dev_set_drvdata(&ud->device, lu);
-
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
-       if (!hi) {
-               hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host,
-                                         sizeof(*hi));
-               if (!hi) {
-                       SBP2_ERR("failed to allocate hostinfo");
-                       goto failed_alloc;
-               }
-               hi->host = ud->ne->host;
-               INIT_LIST_HEAD(&hi->logical_units);
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-               /* Handle data movement if physical dma is not
-                * enabled or not supported on host controller */
-               if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,
-                                            &sbp2_physdma_ops,
-                                            0x0ULL, 0xfffffffcULL)) {
-                       SBP2_ERR("failed to register lower 4GB address range");
-                       goto failed_alloc;
-               }
-#endif
-       }
-
-       if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
-               BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
-                                           SBP2_MAX_SEG_SIZE));
-
-       /* Prevent unloading of the 1394 host */
-       if (!try_module_get(hi->host->driver->owner)) {
-               SBP2_ERR("failed to get a reference on 1394 host driver");
-               goto failed_alloc;
-       }
-
-       lu->hi = hi;
-
-       write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_add_tail(&lu->lu_list, &hi->logical_units);
-       write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       /* Register the status FIFO address range. We could use the same FIFO
-        * for targets at different nodes. However we need different FIFOs per
-        * target in order to support multi-unit devices.
-        * The FIFO is located out of the local host controller's physical range
-        * but, if possible, within the posted write area. Status writes will
-        * then be performed as unified transactions. This slightly reduces
-        * bandwidth usage, and some Prolific based devices seem to require it.
-        */
-       lu->status_fifo_addr = hpsb_allocate_and_register_addrspace(
-                       &sbp2_highlevel, ud->ne->host, &sbp2_ops,
-                       sizeof(struct sbp2_status_block), sizeof(quadlet_t),
-                       ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
-       if (lu->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
-               SBP2_ERR("failed to allocate status FIFO address range");
-               goto failed_alloc;
-       }
-
-       shost = scsi_host_alloc(&sbp2_shost_template, sizeof(unsigned long));
-       if (!shost) {
-               SBP2_ERR("failed to register scsi host");
-               goto failed_alloc;
-       }
-
-       shost->hostdata[0] = (unsigned long)lu;
-       shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
-
-       if (!scsi_add_host(shost, &ud->device)) {
-               lu->shost = shost;
-               return lu;
-       }
-
-       SBP2_ERR("failed to add scsi host");
-       scsi_host_put(shost);
-
-failed_alloc:
-       sbp2_remove_device(lu);
-       return NULL;
-}
-
-static void sbp2_host_reset(struct hpsb_host *host)
-{
-       struct sbp2_fwhost_info *hi;
-       struct sbp2_lu *lu;
-       unsigned long flags;
-
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-       if (!hi)
-               return;
-
-       read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-
-       list_for_each_entry(lu, &hi->logical_units, lu_list)
-               if (atomic_cmpxchg(&lu->state,
-                                  SBP2LU_STATE_RUNNING, SBP2LU_STATE_IN_RESET)
-                   == SBP2LU_STATE_RUNNING)
-                       scsi_block_requests(lu->shost);
-
-       read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-}
-
-static int sbp2_start_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       int error;
-
-       lu->login_response = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_login_response),
-                                    &lu->login_response_dma, GFP_KERNEL);
-       if (!lu->login_response)
-               goto alloc_fail;
-
-       lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_query_logins_orb),
-                                    &lu->query_logins_orb_dma, GFP_KERNEL);
-       if (!lu->query_logins_orb)
-               goto alloc_fail;
-
-       lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_query_logins_response),
-                                    &lu->query_logins_response_dma, GFP_KERNEL);
-       if (!lu->query_logins_response)
-               goto alloc_fail;
-
-       lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_reconnect_orb),
-                                    &lu->reconnect_orb_dma, GFP_KERNEL);
-       if (!lu->reconnect_orb)
-               goto alloc_fail;
-
-       lu->logout_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_logout_orb),
-                                    &lu->logout_orb_dma, GFP_KERNEL);
-       if (!lu->logout_orb)
-               goto alloc_fail;
-
-       lu->login_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_login_orb),
-                                    &lu->login_orb_dma, GFP_KERNEL);
-       if (!lu->login_orb)
-               goto alloc_fail;
-
-       if (sbp2util_create_command_orb_pool(lu))
-               goto alloc_fail;
-
-       /* Wait a second before trying to log in. Previously logged in
-        * initiators need a chance to reconnect. */
-       if (msleep_interruptible(1000)) {
-               sbp2_remove_device(lu);
-               return -EINTR;
-       }
-
-       if (sbp2_login_device(lu)) {
-               sbp2_remove_device(lu);
-               return -EBUSY;
-       }
-
-       sbp2_set_busy_timeout(lu);
-       sbp2_agent_reset(lu, 1);
-       sbp2_max_speed_and_size(lu);
-
-       if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
-               ssleep(SBP2_INQUIRY_DELAY);
-
-       error = scsi_add_device(lu->shost, 0, lu->ud->id, 0);
-       if (error) {
-               SBP2_ERR("scsi_add_device failed");
-               sbp2_logout_device(lu);
-               sbp2_remove_device(lu);
-               return error;
-       }
-
-       return 0;
-
-alloc_fail:
-       SBP2_ERR("Could not allocate memory for lu");
-       sbp2_remove_device(lu);
-       return -ENOMEM;
-}
-
-static void sbp2_remove_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi;
-       unsigned long flags;
-
-       if (!lu)
-               return;
-       hi = lu->hi;
-       if (!hi)
-               goto no_hi;
-
-       if (lu->shost) {
-               scsi_remove_host(lu->shost);
-               scsi_host_put(lu->shost);
-       }
-       flush_scheduled_work();
-       sbp2util_remove_command_orb_pool(lu, hi->host);
-
-       write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_del(&lu->lu_list);
-       write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       if (lu->login_response)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_login_response),
-                                   lu->login_response,
-                                   lu->login_response_dma);
-       if (lu->login_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_login_orb),
-                                   lu->login_orb,
-                                   lu->login_orb_dma);
-       if (lu->reconnect_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_reconnect_orb),
-                                   lu->reconnect_orb,
-                                   lu->reconnect_orb_dma);
-       if (lu->logout_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_logout_orb),
-                                   lu->logout_orb,
-                                   lu->logout_orb_dma);
-       if (lu->query_logins_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_query_logins_orb),
-                                   lu->query_logins_orb,
-                                   lu->query_logins_orb_dma);
-       if (lu->query_logins_response)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_query_logins_response),
-                                   lu->query_logins_response,
-                                   lu->query_logins_response_dma);
-
-       if (lu->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
-               hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
-                                         lu->status_fifo_addr);
-
-       dev_set_drvdata(&lu->ud->device, NULL);
-
-       module_put(hi->host->driver->owner);
-no_hi:
-       kfree(lu);
-}
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-/*
- * Deal with write requests on adapters which do not support physical DMA or
- * have it switched off.
- */
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
-                                    int destid, quadlet_t *data, u64 addr,
-                                    size_t length, u16 flags)
-{
-       memcpy(bus_to_virt((u32) addr), data, length);
-       return RCODE_COMPLETE;
-}
-
-/*
- * Deal with read requests on adapters which do not support physical DMA or
- * have it switched off.
- */
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
-                                   quadlet_t *data, u64 addr, size_t length,
-                                   u16 flags)
-{
-       memcpy(data, bus_to_virt((u32) addr), length);
-       return RCODE_COMPLETE;
-}
-#endif
-
-/**************************************
- * SBP-2 protocol related section
- **************************************/
-
-static int sbp2_query_logins(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int max_logins;
-       int active_logins;
-
-       lu->query_logins_orb->reserved1 = 0x0;
-       lu->query_logins_orb->reserved2 = 0x0;
-
-       lu->query_logins_orb->query_response_lo = lu->query_logins_response_dma;
-       lu->query_logins_orb->query_response_hi =
-                       ORB_SET_NODE_ID(hi->host->node_id);
-       lu->query_logins_orb->lun_misc =
-                       ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
-       lu->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
-       lu->query_logins_orb->lun_misc |= ORB_SET_LUN(lu->lun);
-
-       lu->query_logins_orb->reserved_resp_length =
-               ORB_SET_QUERY_LOGINS_RESP_LENGTH(
-                       sizeof(struct sbp2_query_logins_response));
-
-       lu->query_logins_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->query_logins_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->query_logins_orb,
-                                   sizeof(struct sbp2_query_logins_orb));
-
-       memset(lu->query_logins_response, 0,
-              sizeof(struct sbp2_query_logins_response));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->query_logins_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-
-       if (sbp2util_access_timeout(lu, 2*HZ)) {
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (lu->status_block.ORB_offset_lo != lu->query_logins_orb_dma) {
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_INFO("Error querying logins to SBP-2 device - failed");
-               return -EIO;
-       }
-
-       sbp2util_cpu_to_be32_buffer(lu->query_logins_response,
-                                   sizeof(struct sbp2_query_logins_response));
-
-       max_logins = RESPONSE_GET_MAX_LOGINS(
-                       lu->query_logins_response->length_max_logins);
-       SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
-
-       active_logins = RESPONSE_GET_ACTIVE_LOGINS(
-                       lu->query_logins_response->length_max_logins);
-       SBP2_INFO("Number of active logins: %d", active_logins);
-
-       if (active_logins >= max_logins) {
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int sbp2_login_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-
-       if (!lu->login_orb)
-               return -EIO;
-
-       if (!sbp2_exclusive_login && sbp2_query_logins(lu)) {
-               SBP2_INFO("Device does not support any more concurrent logins");
-               return -EIO;
-       }
-
-       /* assume no password */
-       lu->login_orb->password_hi = 0;
-       lu->login_orb->password_lo = 0;
-
-       lu->login_orb->login_response_lo = lu->login_response_dma;
-       lu->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       lu->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
-
-       /* one second reconnect time */
-       lu->login_orb->lun_misc |= ORB_SET_RECONNECT(0);
-       lu->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(sbp2_exclusive_login);
-       lu->login_orb->lun_misc |= ORB_SET_NOTIFY(1);
-       lu->login_orb->lun_misc |= ORB_SET_LUN(lu->lun);
-
-       lu->login_orb->passwd_resp_lengths =
-               ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
-
-       lu->login_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->login_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->login_orb,
-                                   sizeof(struct sbp2_login_orb));
-
-       memset(lu->login_response, 0, sizeof(struct sbp2_login_response));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->login_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-
-       /* wait up to 20 seconds for login status */
-       if (sbp2util_access_timeout(lu, 20*HZ)) {
-               SBP2_ERR("Error logging into SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       /* make sure that the returned status matches the login ORB */
-       if (lu->status_block.ORB_offset_lo != lu->login_orb_dma) {
-               SBP2_ERR("Error logging into SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_ERR("Error logging into SBP-2 device - failed");
-               return -EIO;
-       }
-
-       sbp2util_cpu_to_be32_buffer(lu->login_response,
-                                   sizeof(struct sbp2_login_response));
-       lu->command_block_agent_addr =
-                       ((u64)lu->login_response->command_block_agent_hi) << 32;
-       lu->command_block_agent_addr |=
-                       ((u64)lu->login_response->command_block_agent_lo);
-       lu->command_block_agent_addr &= 0x0000ffffffffffffULL;
-
-       SBP2_INFO("Logged into SBP-2 device");
-       return 0;
-}
-
-static int sbp2_logout_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int error;
-
-       lu->logout_orb->reserved1 = 0x0;
-       lu->logout_orb->reserved2 = 0x0;
-       lu->logout_orb->reserved3 = 0x0;
-       lu->logout_orb->reserved4 = 0x0;
-
-       lu->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST);
-       lu->logout_orb->login_ID_misc |=
-                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
-       lu->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
-
-       lu->logout_orb->reserved5 = 0x0;
-       lu->logout_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->logout_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->logout_orb,
-                                   sizeof(struct sbp2_logout_orb));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->logout_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-       if (error)
-               return error;
-
-       /* wait up to 1 second for the device to complete logout */
-       if (sbp2util_access_timeout(lu, HZ))
-               return -EIO;
-
-       SBP2_INFO("Logged out of SBP-2 device");
-       return 0;
-}
-
-static int sbp2_reconnect_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int error;
-
-       lu->reconnect_orb->reserved1 = 0x0;
-       lu->reconnect_orb->reserved2 = 0x0;
-       lu->reconnect_orb->reserved3 = 0x0;
-       lu->reconnect_orb->reserved4 = 0x0;
-
-       lu->reconnect_orb->login_ID_misc =
-                       ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST);
-       lu->reconnect_orb->login_ID_misc |=
-                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
-       lu->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
-
-       lu->reconnect_orb->reserved5 = 0x0;
-       lu->reconnect_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->reconnect_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->reconnect_orb,
-                                   sizeof(struct sbp2_reconnect_orb));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->reconnect_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-       if (error)
-               return error;
-
-       /* wait up to 1 second for reconnect status */
-       if (sbp2util_access_timeout(lu, HZ)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       /* make sure that the returned status matches the reconnect ORB */
-       if (lu->status_block.ORB_offset_lo != lu->reconnect_orb_dma) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - failed");
-               return -EIO;
-       }
-
-       SBP2_INFO("Reconnected to SBP-2 device");
-       return 0;
-}
-
-/*
- * Set the target node's Single Phase Retry limit. Affects the target's retry
- * behaviour if our node is too busy to accept requests.
- */
-static int sbp2_set_busy_timeout(struct sbp2_lu *lu)
-{
-       quadlet_t data;
-
-       data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-       if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
-               SBP2_ERR("%s error", __func__);
-       return 0;
-}
-
-static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
-                                     struct unit_directory *ud)
-{
-       struct csr1212_keyval *kv;
-       struct csr1212_dentry *dentry;
-       u64 management_agent_addr;
-       u32 firmware_revision, model;
-       unsigned workarounds;
-       int i;
-
-       management_agent_addr = 0;
-       firmware_revision = SBP2_ROM_VALUE_MISSING;
-       model = ud->flags & UNIT_DIRECTORY_MODEL_ID ?
-                               ud->model_id : SBP2_ROM_VALUE_MISSING;
-
-       csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_DEPENDENT_INFO:
-                       if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET)
-                               management_agent_addr =
-                                   CSR1212_REGISTER_SPACE_BASE +
-                                   (kv->value.csr_offset << 2);
-
-                       else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE)
-                               lu->lun = ORB_SET_LUN(kv->value.immediate);
-                       break;
-
-
-               case SBP2_FIRMWARE_REVISION_KEY:
-                       firmware_revision = kv->value.immediate;
-                       break;
-
-               default:
-                       /* FIXME: Check for SBP2_UNIT_CHARACTERISTICS_KEY
-                        * mgt_ORB_timeout and ORB_size, SBP-2 clause 7.4.8. */
-
-                       /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY.
-                        * Its "ordered" bit has consequences for command ORB
-                        * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */
-                       break;
-               }
-       }
-
-       workarounds = sbp2_default_workarounds;
-
-       if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
-               for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
-                       if (sbp2_workarounds_table[i].firmware_revision !=
-                           SBP2_ROM_VALUE_WILDCARD &&
-                           sbp2_workarounds_table[i].firmware_revision !=
-                           (firmware_revision & 0xffff00))
-                               continue;
-                       if (sbp2_workarounds_table[i].model !=
-                           SBP2_ROM_VALUE_WILDCARD &&
-                           sbp2_workarounds_table[i].model != model)
-                               continue;
-                       workarounds |= sbp2_workarounds_table[i].workarounds;
-                       break;
-               }
-
-       if (workarounds)
-               SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
-                         "(firmware_revision 0x%06x, vendor_id 0x%06x,"
-                         " model_id 0x%06x)",
-                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
-                         workarounds, firmware_revision, ud->vendor_id,
-                         model);
-
-       /* We would need one SCSI host template for each target to adjust
-        * max_sectors on the fly, therefore warn only. */
-       if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
-           (sbp2_max_sectors * 512) > (128 * 1024))
-               SBP2_INFO("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
-                         "max transfer size. WARNING: Current max_sectors "
-                         "setting is larger than 128KB (%d sectors)",
-                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
-                         sbp2_max_sectors);
-
-       /* If this is a logical unit directory entry, process the parent
-        * to get the values. */
-       if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
-               struct unit_directory *parent_ud = container_of(
-                       ud->device.parent, struct unit_directory, device);
-               sbp2_parse_unit_directory(lu, parent_ud);
-       } else {
-               lu->management_agent_addr = management_agent_addr;
-               lu->workarounds = workarounds;
-               if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
-                       lu->lun = ORB_SET_LUN(ud->lun);
-       }
-}
-
-#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))
-
-/*
- * This function is called in order to determine the max speed and packet
- * size we can use in our ORBs. Note, that we (the driver and host) only
- * initiate the transaction. The SBP-2 device actually transfers the data
- * (by reading from the DMA area we tell it). This means that the SBP-2
- * device decides the actual maximum data it can transfer. We just tell it
- * the speed that it needs to use, and the max_rec the host supports, and
- * it takes care of the rest.
- */
-static int sbp2_max_speed_and_size(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       u8 payload;
-
-       lu->speed_code = hi->host->speed[NODEID_TO_NODE(lu->ne->nodeid)];
-
-       if (lu->speed_code > sbp2_max_speed) {
-               lu->speed_code = sbp2_max_speed;
-               SBP2_INFO("Reducing speed to %s",
-                         hpsb_speedto_str[sbp2_max_speed]);
-       }
-
-       /* Payload size is the lesser of what our speed supports and what
-        * our host supports.  */
-       payload = min(sbp2_speedto_max_payload[lu->speed_code],
-                     (u8) (hi->host->csr.max_rec - 1));
-
-       /* If physical DMA is off, work around limitation in ohci1394:
-        * packet size must not exceed PAGE_SIZE */
-       if (lu->ne->host->low_addr_space < (1ULL << 32))
-               while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
-                      payload)
-                       payload--;
-
-       SBP2_INFO("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
-                 NODE_BUS_ARGS(hi->host, lu->ne->nodeid),
-                 hpsb_speedto_str[lu->speed_code],
-                 SBP2_PAYLOAD_TO_BYTES(payload));
-
-       lu->max_payload_size = payload;
-       return 0;
-}
-
-static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
-{
-       quadlet_t data;
-       u64 addr;
-       int retval;
-       unsigned long flags;
-
-       /* flush lu->protocol_work */
-       if (wait)
-               flush_scheduled_work();
-
-       data = ntohl(SBP2_AGENT_RESET_DATA);
-       addr = lu->command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
-
-       if (wait)
-               retval = hpsb_node_write(lu->ne, addr, &data, 4);
-       else
-               retval = sbp2util_node_write_no_wait(lu->ne, addr, &data, 4);
-
-       if (retval < 0) {
-               SBP2_ERR("hpsb_node_write failed.\n");
-               return -EIO;
-       }
-
-       /* make sure that the ORB_POINTER is written on next command */
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       lu->last_orb = NULL;
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       return 0;
-}
-
-static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
-                                   struct sbp2_fwhost_info *hi,
-                                   struct sbp2_command_info *cmd,
-                                   unsigned int sg_count,
-                                   struct scatterlist *sg,
-                                   u32 orb_direction,
-                                   enum dma_data_direction dma_dir)
-{
-       struct device *dmadev = hi->host->device.parent;
-       struct sbp2_unrestricted_page_table *pt;
-       int i, n;
-
-       n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
-       if (n == 0)
-               return -ENOMEM;
-
-       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-       /* special case if only one element (and less than 64KB in size) */
-       if (n == 1) {
-               orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
-               orb->data_descriptor_lo = sg_dma_address(sg);
-       } else {
-               pt = &cmd->scatter_gather_element[0];
-
-               dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
-
-               for_each_sg(sg, sg, n, i) {
-                       pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
-                       pt[i].low = cpu_to_be32(sg_dma_address(sg));
-               }
-
-               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
-                            ORB_SET_DATA_SIZE(n);
-               orb->data_descriptor_lo = cmd->sge_dma;
-
-               dma_sync_single_for_device(dmadev, cmd->sge_dma,
-                                          sizeof(cmd->scatter_gather_element),
-                                          DMA_TO_DEVICE);
-       }
-       return 0;
-}
-
-static int sbp2_create_command_orb(struct sbp2_lu *lu,
-                                  struct sbp2_command_info *cmd,
-                                  struct scsi_cmnd *SCpnt)
-{
-       struct device *dmadev = lu->hi->host->device.parent;
-       struct sbp2_command_orb *orb = &cmd->command_orb;
-       unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
-       enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
-       u32 orb_direction;
-       int ret;
-
-       dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
-                               sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-       /*
-        * Set-up our command ORB.
-        *
-        * NOTE: We're doing unrestricted page tables (s/g), as this is
-        * best performance (at least with the devices I have). This means
-        * that data_size becomes the number of s/g elements, and
-        * page_size should be zero (for unrestricted).
-        */
-       orb->next_ORB_hi = ORB_SET_NULL_PTR(1);
-       orb->next_ORB_lo = 0x0;
-       orb->misc = ORB_SET_MAX_PAYLOAD(lu->max_payload_size);
-       orb->misc |= ORB_SET_SPEED(lu->speed_code);
-       orb->misc |= ORB_SET_NOTIFY(1);
-
-       if (dma_dir == DMA_NONE)
-               orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-       else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
-               orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
-       else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
-               orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
-       else {
-               SBP2_INFO("Falling back to DMA_NONE");
-               orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-       }
-
-       /* set up our page table stuff */
-       if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-               orb->data_descriptor_hi = 0x0;
-               orb->data_descriptor_lo = 0x0;
-               orb->misc |= ORB_SET_DIRECTION(1);
-               ret = 0;
-       } else {
-               ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
-                                              scsi_sg_count(SCpnt),
-                                              scsi_sglist(SCpnt),
-                                              orb_direction, dma_dir);
-       }
-       sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
-
-       memset(orb->cdb, 0, sizeof(orb->cdb));
-       memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-
-       dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
-                       sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-       return ret;
-}
-
-static void sbp2_link_orb_command(struct sbp2_lu *lu,
-                                 struct sbp2_command_info *cmd)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       struct sbp2_command_orb *last_orb;
-       dma_addr_t last_orb_dma;
-       u64 addr = lu->command_block_agent_addr;
-       quadlet_t data[2];
-       size_t length;
-       unsigned long flags;
-
-       /* check to see if there are any previous orbs to use */
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       last_orb = lu->last_orb;
-       last_orb_dma = lu->last_orb_dma;
-       if (!last_orb) {
-               /*
-                * last_orb == NULL means: We know that the target's fetch agent
-                * is not active right now.
-                */
-               addr += SBP2_ORB_POINTER_OFFSET;
-               data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-               data[1] = cmd->command_orb_dma;
-               sbp2util_cpu_to_be32_buffer(data, 8);
-               length = 8;
-       } else {
-               /*
-                * last_orb != NULL means: We know that the target's fetch agent
-                * is (very probably) not dead or in reset state right now.
-                * We have an ORB already sent that we can append a new one to.
-                * The target's fetch agent may or may not have read this
-                * previous ORB yet.
-                */
-               dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma,
-                                       sizeof(struct sbp2_command_orb),
-                                       DMA_TO_DEVICE);
-               last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
-               wmb();
-               /* Tells hardware that this pointer is valid */
-               last_orb->next_ORB_hi = 0;
-               dma_sync_single_for_device(hi->host->device.parent,
-                                          last_orb_dma,
-                                          sizeof(struct sbp2_command_orb),
-                                          DMA_TO_DEVICE);
-               addr += SBP2_DOORBELL_OFFSET;
-               data[0] = 0;
-               length = 4;
-       }
-       lu->last_orb = &cmd->command_orb;
-       lu->last_orb_dma = cmd->command_orb_dma;
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       if (sbp2util_node_write_no_wait(lu->ne, addr, data, length)) {
-               /*
-                * sbp2util_node_write_no_wait failed. We certainly ran out
-                * of transaction labels, perhaps just because there were no
-                * context switches which gave khpsbpkt a chance to collect
-                * free tlabels. Try again in non-atomic context. If necessary,
-                * the workqueue job will sleep to guaranteedly get a tlabel.
-                * We do not accept new commands until the job is over.
-                */
-               scsi_block_requests(lu->shost);
-               PREPARE_WORK(&lu->protocol_work,
-                            last_orb ? sbp2util_write_doorbell:
-                                       sbp2util_write_orb_pointer);
-               schedule_work(&lu->protocol_work);
-       }
-}
-
-static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
-                            void (*done)(struct scsi_cmnd *))
-{
-       struct sbp2_command_info *cmd;
-
-       cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
-       if (!cmd)
-               return -EIO;
-
-       if (sbp2_create_command_orb(lu, cmd, SCpnt))
-               return -ENOMEM;
-
-       sbp2_link_orb_command(lu, cmd);
-       return 0;
-}
-
-/*
- * Translates SBP-2 status into SCSI sense data for check conditions
- */
-static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
-                                             unchar *sense_data)
-{
-       /* OK, it's pretty ugly... ;-) */
-       sense_data[0] = 0x70;
-       sense_data[1] = 0x0;
-       sense_data[2] = sbp2_status[9];
-       sense_data[3] = sbp2_status[12];
-       sense_data[4] = sbp2_status[13];
-       sense_data[5] = sbp2_status[14];
-       sense_data[6] = sbp2_status[15];
-       sense_data[7] = 10;
-       sense_data[8] = sbp2_status[16];
-       sense_data[9] = sbp2_status[17];
-       sense_data[10] = sbp2_status[18];
-       sense_data[11] = sbp2_status[19];
-       sense_data[12] = sbp2_status[10];
-       sense_data[13] = sbp2_status[11];
-       sense_data[14] = sbp2_status[20];
-       sense_data[15] = sbp2_status[21];
-
-       return sbp2_status[8] & 0x3f;
-}
-
-static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
-                                   int destid, quadlet_t *data, u64 addr,
-                                   size_t length, u16 fl)
-{
-       struct sbp2_fwhost_info *hi;
-       struct sbp2_lu *lu = NULL, *lu_tmp;
-       struct scsi_cmnd *SCpnt = NULL;
-       struct sbp2_status_block *sb;
-       u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {
-               SBP2_ERR("Wrong size of status block");
-               return RCODE_ADDRESS_ERROR;
-       }
-       if (unlikely(!host)) {
-               SBP2_ERR("host is NULL - this is bad!");
-               return RCODE_ADDRESS_ERROR;
-       }
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-       if (unlikely(!hi)) {
-               SBP2_ERR("host info is NULL - this is bad!");
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       /* Find the unit which wrote the status. */
-       read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) {
-               if (lu_tmp->ne->nodeid == nodeid &&
-                   lu_tmp->status_fifo_addr == addr) {
-                       lu = lu_tmp;
-                       break;
-               }
-       }
-       read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       if (unlikely(!lu)) {
-               SBP2_ERR("lu is NULL - device is gone?");
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       /* Put response into lu status fifo buffer. The first two bytes
-        * come in big endian bit order. Often the target writes only a
-        * truncated status block, minimally the first two quadlets. The rest
-        * is implied to be zeros. */
-       sb = &lu->status_block;
-       memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));
-       memcpy(sb, data, length);
-       sbp2util_be32_to_cpu_buffer(sb, 8);
-
-       /* Ignore unsolicited status. Handle command ORB status. */
-       if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))
-               cmd = NULL;
-       else
-               cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
-       if (cmd) {
-               /* Grab SCSI command pointers and check status. */
-               /*
-                * FIXME: If the src field in the status is 1, the ORB DMA must
-                * not be reused until status for a subsequent ORB is received.
-                */
-               SCpnt = cmd->Current_SCpnt;
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               sbp2util_mark_command_completed(lu, cmd);
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-               if (SCpnt) {
-                       u32 h = sb->ORB_offset_hi_misc;
-                       u32 r = STATUS_GET_RESP(h);
-
-                       if (r != RESP_STATUS_REQUEST_COMPLETE) {
-                               SBP2_INFO("resp 0x%x, sbp_status 0x%x",
-                                         r, STATUS_GET_SBP_STATUS(h));
-                               scsi_status =
-                                       r == RESP_STATUS_TRANSPORT_FAILURE ?
-                                       SBP2_SCSI_STATUS_BUSY :
-                                       SBP2_SCSI_STATUS_COMMAND_TERMINATED;
-                       }
-
-                       if (STATUS_GET_LEN(h) > 1)
-                               scsi_status = sbp2_status_to_sense_data(
-                                       (unchar *)sb, SCpnt->sense_buffer);
-
-                       if (STATUS_TEST_DEAD(h))
-                                sbp2_agent_reset(lu, 0);
-               }
-
-               /* Check here to see if there are no commands in-use. If there
-                * are none, we know that the fetch agent left the active state
-                * _and_ that we did not reactivate it yet. Therefore clear
-                * last_orb so that next time we write directly to the
-                * ORB_POINTER register. That way the fetch agent does not need
-                * to refetch the next_ORB. */
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               if (list_empty(&lu->cmd_orb_inuse))
-                       lu->last_orb = NULL;
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       } else {
-               /* It's probably status after a management request. */
-               if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->login_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->query_logins_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->logout_orb_dma)) {
-                       lu->access_complete = 1;
-                       wake_up_interruptible(&sbp2_access_wq);
-               }
-       }
-
-       if (SCpnt)
-               sbp2scsi_complete_command(lu, scsi_status, SCpnt,
-                                         cmd->Current_done);
-       return RCODE_COMPLETE;
-}
-
-/**************************************
- * SCSI interface related section
- **************************************/
-
-static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
-                                void (*done)(struct scsi_cmnd *))
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-       struct sbp2_fwhost_info *hi;
-       int result = DID_NO_CONNECT << 16;
-
-       if (unlikely(!sbp2util_node_is_available(lu)))
-               goto done;
-
-       hi = lu->hi;
-
-       if (unlikely(!hi)) {
-               SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!");
-               goto done;
-       }
-
-       /* Multiple units are currently represented to the SCSI core as separate
-        * targets, not as one target with multiple LUs. Therefore return
-        * selection time-out to any IO directed at non-zero LUNs. */
-       if (unlikely(SCpnt->device->lun))
-               goto done;
-
-       if (unlikely(!hpsb_node_entry_valid(lu->ne))) {
-               SBP2_ERR("Bus reset in progress - rejecting command");
-               result = DID_BUS_BUSY << 16;
-               goto done;
-       }
-
-       /* Bidirectional commands are not yet implemented,
-        * and unknown transfer direction not handled. */
-       if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) {
-               SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
-               result = DID_ERROR << 16;
-               goto done;
-       }
-
-       if (sbp2_send_command(lu, SCpnt, done)) {
-               SBP2_ERR("Error sending SCSI command");
-               sbp2scsi_complete_command(lu,
-                                         SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
-                                         SCpnt, done);
-       }
-       return 0;
-
-done:
-       SCpnt->result = result;
-       done(SCpnt);
-       return 0;
-}
-
-static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
-{
-       struct list_head *lh;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       while (!list_empty(&lu->cmd_orb_inuse)) {
-               lh = lu->cmd_orb_inuse.next;
-               cmd = list_entry(lh, struct sbp2_command_info, list);
-               sbp2util_mark_command_completed(lu, cmd);
-               if (cmd->Current_SCpnt) {
-                       cmd->Current_SCpnt->result = status << 16;
-                       cmd->Current_done(cmd->Current_SCpnt);
-               }
-       }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       return;
-}
-
-/*
- * Complete a regular SCSI command. Can be called in atomic context.
- */
-static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status,
-                                     struct scsi_cmnd *SCpnt,
-                                     void (*done)(struct scsi_cmnd *))
-{
-       if (!SCpnt) {
-               SBP2_ERR("SCpnt is NULL");
-               return;
-       }
-
-       switch (scsi_status) {
-       case SBP2_SCSI_STATUS_GOOD:
-               SCpnt->result = DID_OK << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_BUSY:
-               SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
-               SCpnt->result = DID_BUS_BUSY << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_CHECK_CONDITION:
-               SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
-               SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
-               SCpnt->result = DID_NO_CONNECT << 16;
-               scsi_print_command(SCpnt);
-               break;
-
-       case SBP2_SCSI_STATUS_CONDITION_MET:
-       case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
-       case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
-               SBP2_ERR("Bad SCSI status = %x", scsi_status);
-               SCpnt->result = DID_ERROR << 16;
-               scsi_print_command(SCpnt);
-               break;
-
-       default:
-               SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
-               SCpnt->result = DID_ERROR << 16;
-       }
-
-       /* If a bus reset is in progress and there was an error, complete
-        * the command as busy so that it will get retried. */
-       if (!hpsb_node_entry_valid(lu->ne)
-           && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
-               SBP2_ERR("Completing command with busy (bus reset)");
-               SCpnt->result = DID_BUS_BUSY << 16;
-       }
-
-       /* Tell the SCSI stack that we're done with this command. */
-       done(SCpnt);
-}
-
-static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
-
-       if (sdev->lun != 0 || sdev->id != lu->ud->id || sdev->channel != 0)
-               return -ENODEV;
-
-       lu->sdev = sdev;
-       sdev->allow_restart = 1;
-
-       /* SBP-2 requires quadlet alignment of the data buffers. */
-       blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
-
-       if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
-               sdev->inquiry_len = 36;
-       return 0;
-}
-
-static int sbp2scsi_slave_configure(struct scsi_device *sdev)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
-
-       sdev->use_10_for_rw = 1;
-
-       if (sbp2_exclusive_login)
-               sdev->manage_start_stop = 1;
-       if (sdev->type == TYPE_ROM)
-               sdev->use_10_for_ms = 1;
-       if (sdev->type == TYPE_DISK &&
-           lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
-               sdev->skip_ms_page_8 = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
-               sdev->fix_capacity = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_POWER_CONDITION)
-               sdev->start_stop_pwr_cond = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
-               blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512);
-
-       blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
-       return 0;
-}
-
-static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
-{
-       ((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL;
-       return;
-}
-
-/*
- * Called by scsi stack when something has really gone wrong.
- * Usually called when a command has timed-out for some reason.
- */
-static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       SBP2_INFO("aborting sbp2 command");
-       scsi_print_command(SCpnt);
-
-       if (sbp2util_node_is_available(lu)) {
-               sbp2_agent_reset(lu, 1);
-
-               /* Return a matching command structure to the free pool. */
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
-               if (cmd) {
-                       sbp2util_mark_command_completed(lu, cmd);
-                       if (cmd->Current_SCpnt) {
-                               cmd->Current_SCpnt->result = DID_ABORT << 16;
-                               cmd->Current_done(cmd->Current_SCpnt);
-                       }
-               }
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-               sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
-       }
-
-       return SUCCESS;
-}
-
-/*
- * Called by scsi stack when something has really gone wrong.
- */
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-
-       SBP2_INFO("reset requested");
-
-       if (sbp2util_node_is_available(lu)) {
-               SBP2_INFO("generating sbp2 fetch agent reset");
-               sbp2_agent_reset(lu, 1);
-       }
-
-       return SUCCESS;
-}
-
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
-{
-       struct scsi_device *sdev;
-       struct sbp2_lu *lu;
-
-       if (!(sdev = to_scsi_device(dev)))
-               return 0;
-
-       if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
-               return 0;
-
-       if (sbp2_long_sysfs_ieee1394_id)
-               return sprintf(buf, "%016Lx:%06x:%04x\n",
-                               (unsigned long long)lu->ne->guid,
-                               lu->ud->directory_id, ORB_SET_LUN(lu->lun));
-       else
-               return sprintf(buf, "%016Lx:%d:%d\n",
-                               (unsigned long long)lu->ne->guid,
-                               lu->ud->id, ORB_SET_LUN(lu->lun));
-}
-
-MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
-MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
-MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
-MODULE_LICENSE("GPL");
-
-static int sbp2_module_init(void)
-{
-       int ret;
-
-       if (sbp2_serialize_io) {
-               sbp2_shost_template.can_queue = 1;
-               sbp2_shost_template.cmd_per_lun = 1;
-       }
-
-       sbp2_shost_template.max_sectors = sbp2_max_sectors;
-
-       hpsb_register_highlevel(&sbp2_highlevel);
-       ret = hpsb_register_protocol(&sbp2_driver);
-       if (ret) {
-               SBP2_ERR("Failed to register protocol");
-               hpsb_unregister_highlevel(&sbp2_highlevel);
-               return ret;
-       }
-       return 0;
-}
-
-static void __exit sbp2_module_exit(void)
-{
-       hpsb_unregister_protocol(&sbp2_driver);
-       hpsb_unregister_highlevel(&sbp2_highlevel);
-}
-
-module_init(sbp2_module_init);
-module_exit(sbp2_module_exit);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
deleted file mode 100644 (file)
index 64a3a66..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * sbp2.h - Defines and prototypes for sbp2.c
- *
- * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com)
- * jamesg@filanet.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.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef SBP2_H
-#define SBP2_H
-
-#define SBP2_DEVICE_NAME               "sbp2"
-
-/*
- * There is no transport protocol limit to the CDB length,  but we implement
- * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
- */
-#define SBP2_MAX_CDB_SIZE              16
-
-/*
- * SBP-2 specific definitions
- */
-
-#define ORB_DIRECTION_WRITE_TO_MEDIA   0x0
-#define ORB_DIRECTION_READ_FROM_MEDIA  0x1
-#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
-
-#define ORB_SET_NULL_PTR(v)            (((v) & 0x1) << 31)
-#define ORB_SET_NOTIFY(v)              (((v) & 0x1) << 31)
-#define ORB_SET_RQ_FMT(v)              (((v) & 0x3) << 29)
-#define ORB_SET_NODE_ID(v)             (((v) & 0xffff) << 16)
-#define ORB_SET_STATUS_FIFO_HI(v, id)  ((v) >> 32 | ORB_SET_NODE_ID(id))
-#define ORB_SET_STATUS_FIFO_LO(v)      ((v) & 0xffffffff)
-#define ORB_SET_DATA_SIZE(v)           ((v) & 0xffff)
-#define ORB_SET_PAGE_SIZE(v)           (((v) & 0x7) << 16)
-#define ORB_SET_PAGE_TABLE_PRESENT(v)  (((v) & 0x1) << 19)
-#define ORB_SET_MAX_PAYLOAD(v)         (((v) & 0xf) << 20)
-#define ORB_SET_SPEED(v)               (((v) & 0x7) << 24)
-#define ORB_SET_DIRECTION(v)           (((v) & 0x1) << 27)
-
-struct sbp2_command_orb {
-       u32 next_ORB_hi;
-       u32 next_ORB_lo;
-       u32 data_descriptor_hi;
-       u32 data_descriptor_lo;
-       u32 misc;
-       u8 cdb[SBP2_MAX_CDB_SIZE];
-} __attribute__((packed));
-
-#define SBP2_LOGIN_REQUEST             0x0
-#define SBP2_QUERY_LOGINS_REQUEST      0x1
-#define SBP2_RECONNECT_REQUEST         0x3
-#define SBP2_SET_PASSWORD_REQUEST      0x4
-#define SBP2_LOGOUT_REQUEST            0x7
-#define SBP2_ABORT_TASK_REQUEST                0xb
-#define SBP2_ABORT_TASK_SET            0xc
-#define SBP2_LOGICAL_UNIT_RESET                0xe
-#define SBP2_TARGET_RESET_REQUEST      0xf
-
-#define ORB_SET_LUN(v)                 ((v) & 0xffff)
-#define ORB_SET_FUNCTION(v)            (((v) & 0xf) << 16)
-#define ORB_SET_RECONNECT(v)           (((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v)           ((v) ? 1 << 28 : 0)
-#define ORB_SET_LOGIN_RESP_LENGTH(v)   ((v) & 0xffff)
-#define ORB_SET_PASSWD_LENGTH(v)       (((v) & 0xffff) << 16)
-
-struct sbp2_login_orb {
-       u32 password_hi;
-       u32 password_lo;
-       u32 login_response_hi;
-       u32 login_response_lo;
-       u32 lun_misc;
-       u32 passwd_resp_lengths;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-#define RESPONSE_GET_LOGIN_ID(v)       ((v) & 0xffff)
-#define RESPONSE_GET_LENGTH(v)         (((v) >> 16) & 0xffff)
-#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff)
-
-struct sbp2_login_response {
-       u32 length_login_ID;
-       u32 command_block_agent_hi;
-       u32 command_block_agent_lo;
-       u32 reconnect_hold;
-} __attribute__((packed));
-
-#define ORB_SET_LOGIN_ID(v)                 ((v) & 0xffff)
-#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff)
-
-struct sbp2_query_logins_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 query_response_hi;
-       u32 query_response_lo;
-       u32 lun_misc;
-       u32 reserved_resp_length;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-#define RESPONSE_GET_MAX_LOGINS(v)     ((v) & 0xffff)
-#define RESPONSE_GET_ACTIVE_LOGINS(v)  ((RESPONSE_GET_LENGTH((v)) - 4) / 12)
-
-struct sbp2_query_logins_response {
-       u32 length_max_logins;
-       u32 misc_IDs;
-       u32 initiator_misc_hi;
-       u32 initiator_misc_lo;
-} __attribute__((packed));
-
-struct sbp2_reconnect_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 reserved3;
-       u32 reserved4;
-       u32 login_ID_misc;
-       u32 reserved5;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-struct sbp2_logout_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 reserved3;
-       u32 reserved4;
-       u32 login_ID_misc;
-       u32 reserved5;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-struct sbp2_unrestricted_page_table {
-       __be32 high;
-       __be32 low;
-};
-
-#define RESP_STATUS_REQUEST_COMPLETE           0x0
-#define RESP_STATUS_TRANSPORT_FAILURE          0x1
-#define RESP_STATUS_ILLEGAL_REQUEST            0x2
-#define RESP_STATUS_VENDOR_DEPENDENT           0x3
-
-#define SBP2_STATUS_NO_ADDITIONAL_INFO         0x0
-#define SBP2_STATUS_REQ_TYPE_NOT_SUPPORTED     0x1
-#define SBP2_STATUS_SPEED_NOT_SUPPORTED                0x2
-#define SBP2_STATUS_PAGE_SIZE_NOT_SUPPORTED    0x3
-#define SBP2_STATUS_ACCESS_DENIED              0x4
-#define SBP2_STATUS_LU_NOT_SUPPORTED           0x5
-#define SBP2_STATUS_MAX_PAYLOAD_TOO_SMALL      0x6
-#define SBP2_STATUS_RESOURCES_UNAVAILABLE      0x8
-#define SBP2_STATUS_FUNCTION_REJECTED          0x9
-#define SBP2_STATUS_LOGIN_ID_NOT_RECOGNIZED    0xa
-#define SBP2_STATUS_DUMMY_ORB_COMPLETED                0xb
-#define SBP2_STATUS_REQUEST_ABORTED            0xc
-#define SBP2_STATUS_UNSPECIFIED_ERROR          0xff
-
-#define SFMT_CURRENT_ERROR                     0x0
-#define SFMT_DEFERRED_ERROR                    0x1
-#define SFMT_VENDOR_DEPENDENT_STATUS           0x3
-
-#define STATUS_GET_SRC(v)                      (((v) >> 30) & 0x3)
-#define STATUS_GET_RESP(v)                     (((v) >> 28) & 0x3)
-#define STATUS_GET_LEN(v)                      (((v) >> 24) & 0x7)
-#define STATUS_GET_SBP_STATUS(v)               (((v) >> 16) & 0xff)
-#define STATUS_GET_ORB_OFFSET_HI(v)            ((v) & 0x0000ffff)
-#define STATUS_TEST_DEAD(v)                    ((v) & 0x08000000)
-/* test 'resp' | 'dead' | 'sbp2_status' */
-#define STATUS_TEST_RDS(v)                     ((v) & 0x38ff0000)
-
-struct sbp2_status_block {
-       u32 ORB_offset_hi_misc;
-       u32 ORB_offset_lo;
-       u8 command_set_dependent[24];
-} __attribute__((packed));
-
-
-/*
- * SBP2 related configuration ROM definitions
- */
-
-#define SBP2_UNIT_DIRECTORY_OFFSET_KEY         0xd1
-#define SBP2_CSR_OFFSET_KEY                    0x54
-#define SBP2_UNIT_SPEC_ID_KEY                  0x12
-#define SBP2_UNIT_SW_VERSION_KEY               0x13
-#define SBP2_COMMAND_SET_SPEC_ID_KEY           0x38
-#define SBP2_COMMAND_SET_KEY                   0x39
-#define SBP2_UNIT_CHARACTERISTICS_KEY          0x3a
-#define SBP2_DEVICE_TYPE_AND_LUN_KEY           0x14
-#define SBP2_FIRMWARE_REVISION_KEY             0x3c
-
-#define SBP2_AGENT_STATE_OFFSET                        0x00ULL
-#define SBP2_AGENT_RESET_OFFSET                        0x04ULL
-#define SBP2_ORB_POINTER_OFFSET                        0x08ULL
-#define SBP2_DOORBELL_OFFSET                   0x10ULL
-#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET  0x14ULL
-#define SBP2_UNSOLICITED_STATUS_VALUE          0xf
-
-#define SBP2_BUSY_TIMEOUT_ADDRESS              0xfffff0000210ULL
-/* biggest possible value for Single Phase Retry count is 0xf */
-#define SBP2_BUSY_TIMEOUT_VALUE                        0xf
-
-#define SBP2_AGENT_RESET_DATA                  0xf
-
-#define SBP2_UNIT_SPEC_ID_ENTRY                        0x0000609e
-#define SBP2_SW_VERSION_ENTRY                  0x00010483
-
-/*
- * The default maximum s/g segment size of a FireWire controller is
- * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
- * be quadlet-aligned, we set the length limit to 0xffff & ~3.
- */
-#define SBP2_MAX_SEG_SIZE                      0xfffc
-
-/*
- * There is no real limitation of the queue depth (i.e. length of the linked
- * list of command ORBs) at the target. The chosen depth is merely an
- * implementation detail of the sbp2 driver.
- */
-#define SBP2_MAX_CMDS                          8
-
-#define SBP2_SCSI_STATUS_GOOD                  0x0
-#define SBP2_SCSI_STATUS_CHECK_CONDITION       0x2
-#define SBP2_SCSI_STATUS_CONDITION_MET         0x4
-#define SBP2_SCSI_STATUS_BUSY                  0x8
-#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT  0x18
-#define SBP2_SCSI_STATUS_COMMAND_TERMINATED    0x22
-#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT     0xff
-
-
-/*
- * Representations of commands and devices
- */
-
-/* Per SCSI command */
-struct sbp2_command_info {
-       struct list_head list;
-       struct sbp2_command_orb command_orb;
-       dma_addr_t command_orb_dma;
-       struct scsi_cmnd *Current_SCpnt;
-       void (*Current_done)(struct scsi_cmnd *);
-
-       /* Also need s/g structure for each sbp2 command */
-       struct sbp2_unrestricted_page_table
-               scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
-       dma_addr_t sge_dma;
-};
-
-/* Per FireWire host */
-struct sbp2_fwhost_info {
-       struct hpsb_host *host;
-       struct list_head logical_units;
-};
-
-/* Per logical unit */
-struct sbp2_lu {
-       /* Operation request blocks */
-       struct sbp2_command_orb *last_orb;
-       dma_addr_t last_orb_dma;
-       struct sbp2_login_orb *login_orb;
-       dma_addr_t login_orb_dma;
-       struct sbp2_login_response *login_response;
-       dma_addr_t login_response_dma;
-       struct sbp2_query_logins_orb *query_logins_orb;
-       dma_addr_t query_logins_orb_dma;
-       struct sbp2_query_logins_response *query_logins_response;
-       dma_addr_t query_logins_response_dma;
-       struct sbp2_reconnect_orb *reconnect_orb;
-       dma_addr_t reconnect_orb_dma;
-       struct sbp2_logout_orb *logout_orb;
-       dma_addr_t logout_orb_dma;
-       struct sbp2_status_block status_block;
-
-       /* How to talk to the unit */
-       u64 management_agent_addr;
-       u64 command_block_agent_addr;
-       u32 speed_code;
-       u32 max_payload_size;
-       u16 lun;
-
-       /* Address for the unit to write status blocks to */
-       u64 status_fifo_addr;
-
-       /* Waitqueue flag for logins, reconnects, logouts, query logins */
-       unsigned int access_complete:1;
-
-       /* Pool of command ORBs for this logical unit */
-       spinlock_t cmd_orb_lock;
-       struct list_head cmd_orb_inuse;
-       struct list_head cmd_orb_completed;
-
-       /* Backlink to FireWire host; list of units attached to the host */
-       struct sbp2_fwhost_info *hi;
-       struct list_head lu_list;
-
-       /* IEEE 1394 core's device representations */
-       struct node_entry *ne;
-       struct unit_directory *ud;
-
-       /* SCSI core's device representations */
-       struct scsi_device *sdev;
-       struct Scsi_Host *shost;
-
-       /* Device specific workarounds/brokeness */
-       unsigned workarounds;
-
-       /* Connection state */
-       atomic_t state;
-
-       /* For deferred requests to the fetch agent */
-       struct work_struct protocol_work;
-};
-
-/* For use in sbp2_lu.state */
-enum sbp2lu_state_types {
-       SBP2LU_STATE_RUNNING,           /* all normal */
-       SBP2LU_STATE_IN_RESET,          /* between bus reset and reconnect */
-       SBP2LU_STATE_IN_SHUTDOWN        /* when sbp2_remove was called */
-};
-
-/* For use in sbp2_lu.workarounds and in the corresponding
- * module load parameter */
-#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
-#define SBP2_WORKAROUND_INQUIRY_36     0x2
-#define SBP2_WORKAROUND_MODE_SENSE_8   0x4
-#define SBP2_WORKAROUND_FIX_CAPACITY   0x8
-#define SBP2_WORKAROUND_DELAY_INQUIRY  0x10
-#define SBP2_INQUIRY_DELAY             12
-#define SBP2_WORKAROUND_POWER_CONDITION        0x20
-#define SBP2_WORKAROUND_OVERRIDE       0x100
-
-#endif /* SBP2_H */
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
deleted file mode 100644 (file)
index 5c74f79..0000000
+++ /dev/null
@@ -1,1528 +0,0 @@
-/*
- * video1394.c - video driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Peter Schlaile <udbz@rz.uni-karlsruhe.de>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * NOTES:
- *
- * ioctl return codes:
- * EFAULT is only for invalid address for the argp
- * EINVAL for out of range values
- * EBUSY when trying to use an already used resource
- * ESRCH when trying to free/stop a not used resource
- * EAGAIN for resource allocation failure that could perhaps succeed later
- * ENOTTY for unsupported ioctl request
- *
- */
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/timex.h>
-#include <linux/mm.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-
-#include "dma.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "ohci1394.h"
-#include "video1394.h"
-
-#define ISO_CHANNELS 64
-
-struct it_dma_prg {
-       struct dma_cmd begin;
-       quadlet_t data[4];
-       struct dma_cmd end;
-       quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
-};
-
-struct dma_iso_ctx {
-       struct ti_ohci *ohci;
-       int type; /* OHCI_ISO_TRANSMIT or OHCI_ISO_RECEIVE */
-       struct ohci1394_iso_tasklet iso_tasklet;
-       int channel;
-       int ctx;
-       int last_buffer;
-       int * next_buffer;  /* For ISO Transmit of video packets
-                              to write the correct SYT field
-                              into the next block */
-       unsigned int num_desc;
-       unsigned int buf_size;
-       unsigned int frame_size;
-       unsigned int packet_size;
-       unsigned int left_size;
-       unsigned int nb_cmd;
-
-       struct dma_region dma;
-
-       struct dma_prog_region *prg_reg;
-
-        struct dma_cmd **ir_prg;
-       struct it_dma_prg **it_prg;
-
-       unsigned int *buffer_status;
-       unsigned int *buffer_prg_assignment;
-        struct timeval *buffer_time; /* time when the buffer was received */
-       unsigned int *last_used_cmd; /* For ISO Transmit with
-                                       variable sized packets only ! */
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-       int ctxMatch;
-       wait_queue_head_t waitq;
-       spinlock_t lock;
-       unsigned int syt_offset;
-       int flags;
-
-       struct list_head link;
-};
-
-
-struct file_ctx {
-       struct ti_ohci *ohci;
-       struct list_head context_list;
-       struct dma_iso_ctx *current_ctx;
-};
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define VIDEO1394_DEBUG
-#endif
-
-#ifdef DBGMSG
-#undef DBGMSG
-#endif
-
-#ifdef VIDEO1394_DEBUG
-#define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args)
-#else
-#define DBGMSG(card, fmt, args...) do {} while (0)
-#endif
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) \
-printk(level "video1394: " fmt "\n" , ## args)
-
-/* print card specific information */
-#define PRINT(level, card, fmt, args...) \
-printk(level "video1394_%d: " fmt "\n" , card , ## args)
-
-static void wakeup_dma_ir_ctx(unsigned long l);
-static void wakeup_dma_it_ctx(unsigned long l);
-
-static struct hpsb_highlevel video1394_highlevel;
-
-static int free_dma_iso_ctx(struct dma_iso_ctx *d)
-{
-       int i;
-
-       DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx);
-
-       ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-       if (d->iso_tasklet.link.next != NULL)
-               ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet);
-
-       dma_region_free(&d->dma);
-
-       if (d->prg_reg) {
-               for (i = 0; i < d->num_desc; i++)
-                       dma_prog_region_free(&d->prg_reg[i]);
-               kfree(d->prg_reg);
-       }
-
-       kfree(d->ir_prg);
-       kfree(d->it_prg);
-       kfree(d->buffer_status);
-       kfree(d->buffer_prg_assignment);
-       kfree(d->buffer_time);
-       kfree(d->last_used_cmd);
-       kfree(d->next_buffer);
-       list_del(&d->link);
-       kfree(d);
-
-       return 0;
-}
-
-static struct dma_iso_ctx *
-alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
-                 int buf_size, int channel, unsigned int packet_size)
-{
-       struct dma_iso_ctx *d;
-       int i;
-
-       d = kzalloc(sizeof(*d), GFP_KERNEL);
-       if (!d) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
-               return NULL;
-       }
-
-       d->ohci = ohci;
-       d->type = type;
-       d->channel = channel;
-       d->num_desc = num_desc;
-       d->frame_size = buf_size;
-       d->buf_size = PAGE_ALIGN(buf_size);
-       d->last_buffer = -1;
-       INIT_LIST_HEAD(&d->link);
-       init_waitqueue_head(&d->waitq);
-
-       /* Init the regions for easy cleanup */
-       dma_region_init(&d->dma);
-
-       if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev,
-                            PCI_DMA_BIDIRECTIONAL)) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-
-       if (type == OHCI_ISO_RECEIVE)
-               ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
-                                         wakeup_dma_ir_ctx,
-                                         (unsigned long) d);
-       else
-               ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
-                                         wakeup_dma_it_ctx,
-                                         (unsigned long) d);
-
-       if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) {
-               PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts",
-                     type == OHCI_ISO_RECEIVE ? "receive" : "transmit");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-       d->ctx = d->iso_tasklet.context;
-
-       d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
-       if (!d->prg_reg) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-       /* Makes for easier cleanup */
-       for (i = 0; i < d->num_desc; i++)
-               dma_prog_region_init(&d->prg_reg[i]);
-
-       if (type == OHCI_ISO_RECEIVE) {
-               d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx;
-               d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx;
-               d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
-               d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
-
-               d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
-                                   GFP_KERNEL);
-
-               if (!d->ir_prg) {
-                       PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
-               d->left_size = (d->frame_size % PAGE_SIZE) ?
-                       d->frame_size % PAGE_SIZE : PAGE_SIZE;
-
-               for (i = 0;i < d->num_desc; i++) {
-                       if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
-                                                 sizeof(struct dma_cmd), ohci->dev)) {
-                               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
-                               free_dma_iso_ctx(d);
-                               return NULL;
-                       }
-                       d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt;
-               }
-
-       } else {  /* OHCI_ISO_TRANSMIT */
-               d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx;
-               d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
-               d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
-
-               d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
-                                   GFP_KERNEL);
-
-               if (!d->it_prg) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Failed to allocate dma it prg");
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->packet_size = packet_size;
-
-               if (PAGE_SIZE % packet_size || packet_size>4096) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Packet size %d (page_size: %ld) "
-                             "not yet supported\n",
-                             packet_size, PAGE_SIZE);
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->nb_cmd = d->frame_size / d->packet_size;
-               if (d->frame_size % d->packet_size) {
-                       d->nb_cmd++;
-                       d->left_size = d->frame_size % d->packet_size;
-               } else
-                       d->left_size = d->packet_size;
-
-               for (i = 0; i < d->num_desc; i++) {
-                       if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
-                                               sizeof(struct it_dma_prg), ohci->dev)) {
-                               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg");
-                               free_dma_iso_ctx(d);
-                               return NULL;
-                       }
-                       d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt;
-               }
-       }
-
-       d->buffer_status =
-           kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
-       d->buffer_prg_assignment =
-           kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
-       d->buffer_time =
-           kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
-       d->last_used_cmd =
-           kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
-       d->next_buffer =
-           kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
-
-       if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
-           !d->last_used_cmd || !d->next_buffer) {
-               PRINT(KERN_ERR, ohci->host->id,
-                     "Failed to allocate dma_iso_ctx member");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-
-        spin_lock_init(&d->lock);
-
-       DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers "
-             "of size %d allocated for a frame size %d, each with %d prgs",
-             (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
-             d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
-
-       return d;
-}
-
-static void reset_ir_status(struct dma_iso_ctx *d, int n)
-{
-       int i;
-       d->ir_prg[n][0].status = cpu_to_le32(4);
-       d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4);
-       for (i = 2; i < d->nb_cmd - 1; i++)
-               d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE);
-       d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
-}
-
-static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags)
-{
-       struct dma_cmd *ir_prg = d->ir_prg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
-       int i;
-
-       d->buffer_prg_assignment[n] = buffer;
-
-       ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
-                               (unsigned long)d->dma.kvirt));
-       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                               (buf + 4) - (unsigned long)d->dma.kvirt));
-
-       for (i=2;i<d->nb_cmd-1;i++) {
-               ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf+(i-1)*PAGE_SIZE) -
-                                               (unsigned long)d->dma.kvirt));
-       }
-
-       ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                 DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-       ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                 (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt));
-}
-
-static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
-{
-       struct dma_cmd *ir_prg = d->ir_prg[n];
-       struct dma_prog_region *ir_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt;
-       int i;
-
-       /* the first descriptor will read only 4 bytes */
-       ir_prg[0].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-               DMA_CTL_BRANCH | 4);
-
-       /* set the sync flag */
-       if (flags & VIDEO1394_SYNC_FRAMES)
-               ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT);
-
-       ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
-                               (unsigned long)d->dma.kvirt));
-       ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                       1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-       /* If there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
-       if (d->nb_cmd > 2) {
-               /* The second descriptor will read PAGE_SIZE-4 bytes */
-               ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_BRANCH | (PAGE_SIZE-4));
-               ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
-                                               (unsigned long)d->dma.kvirt));
-               ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                                     2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-               for (i = 2; i < d->nb_cmd - 1; i++) {
-                       ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                                       DMA_CTL_BRANCH | PAGE_SIZE);
-                       ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                                       (buf+(i-1)*PAGE_SIZE) -
-                                                       (unsigned long)d->dma.kvirt));
-
-                       ir_prg[i].branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                           (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-               }
-
-               /* The last descriptor will generate an interrupt */
-               ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-               ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf+(i-1)*PAGE_SIZE) -
-                                               (unsigned long)d->dma.kvirt));
-       } else {
-               /* Only one DMA page is used. Read d->left_size immediately and */
-               /* generate an interrupt as this is also the last page. */
-               ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
-               ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf + 4) - (unsigned long)d->dma.kvirt));
-       }
-}
-
-static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
-{
-       struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
-       int i;
-
-       d->flags = flags;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0;i<d->num_desc;i++) {
-               initialize_dma_ir_prg(d, i, flags);
-               reset_ir_status(d, i);
-       }
-
-       /* reset the ctrl register */
-       reg_write(ohci, d->ctrlClear, 0xf0000000);
-
-       /* Set bufferFill */
-       reg_write(ohci, d->ctrlSet, 0x80000000);
-
-       /* Set isoch header */
-       if (flags & VIDEO1394_INCLUDE_ISO_HEADERS)
-               reg_write(ohci, d->ctrlSet, 0x40000000);
-
-       /* Set the context match register to match on all tags,
-          sync for sync tag, and listen to d->channel */
-       reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel);
-
-       /* Set up isoRecvIntMask to generate interrupts */
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<<d->ctx);
-}
-
-/* find which context is listening to this channel */
-static struct dma_iso_ctx *
-find_ctx(struct list_head *list, int type, int channel)
-{
-       struct dma_iso_ctx *ctx;
-
-       list_for_each_entry(ctx, list, link) {
-               if (ctx->type == type && ctx->channel == channel)
-                       return ctx;
-       }
-
-       return NULL;
-}
-
-static void wakeup_dma_ir_ctx(unsigned long l)
-{
-       struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
-       int i;
-
-       spin_lock(&d->lock);
-
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
-                       reset_ir_status(d, i);
-                       d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
-                       do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
-                       dma_region_sync_for_cpu(&d->dma,
-                               d->buffer_prg_assignment[i] * d->buf_size,
-                               d->buf_size);
-               }
-       }
-
-       spin_unlock(&d->lock);
-
-       if (waitqueue_active(&d->waitq))
-               wake_up_interruptible(&d->waitq);
-}
-
-static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
-                                int n)
-{
-       unsigned char* buf = d->dma.kvirt + n * d->buf_size;
-       u32 cycleTimer;
-       u32 timeStamp;
-
-       if (n == -1) {
-         return;
-       }
-
-       cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-
-       timeStamp = ((cycleTimer & 0x0fff) + d->syt_offset); /* 11059 = 450 us */
-       timeStamp = (timeStamp % 3072 + ((timeStamp / 3072) << 12)
-               + (cycleTimer & 0xf000)) & 0xffff;
-
-       buf[6] = timeStamp >> 8;
-       buf[7] = timeStamp & 0xff;
-
-    /* if first packet is empty packet, then put timestamp into the next full one too */
-    if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
-           buf += d->packet_size;
-       buf[6] = timeStamp >> 8;
-           buf[7] = timeStamp & 0xff;
-       }
-
-    /* do the next buffer frame too in case of irq latency */
-       n = d->next_buffer[n];
-       if (n == -1) {
-         return;
-       }
-       buf = d->dma.kvirt + n * d->buf_size;
-
-       timeStamp += (d->last_used_cmd[n] << 12) & 0xffff;
-
-       buf[6] = timeStamp >> 8;
-       buf[7] = timeStamp & 0xff;
-
-    /* if first packet is empty packet, then put timestamp into the next full one too */
-    if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
-           buf += d->packet_size;
-       buf[6] = timeStamp >> 8;
-           buf[7] = timeStamp & 0xff;
-       }
-
-#if 0
-       printk("curr: %d, next: %d, cycleTimer: %08x timeStamp: %08x\n",
-              curr, n, cycleTimer, timeStamp);
-#endif
-}
-
-static void wakeup_dma_it_ctx(unsigned long l)
-{
-       struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
-       struct ti_ohci *ohci = d->ohci;
-       int i;
-
-       spin_lock(&d->lock);
-
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->it_prg[i][d->last_used_cmd[i]].end.status &
-                   cpu_to_le32(0xFFFF0000)) {
-                       int next = d->next_buffer[i];
-                       put_timestamp(ohci, d, next);
-                       d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
-                       d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
-               }
-       }
-
-       spin_unlock(&d->lock);
-
-       if (waitqueue_active(&d->waitq))
-               wake_up_interruptible(&d->waitq);
-}
-
-static void reprogram_dma_it_prg(struct dma_iso_ctx  *d, int n, int buffer)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
-       int i;
-
-       d->buffer_prg_assignment[n] = buffer;
-       for (i=0;i<d->nb_cmd;i++) {
-         it_prg[i].end.address =
-               cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                       (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
-       }
-}
-
-static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       struct dma_prog_region *it_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt;
-       int i;
-       d->last_used_cmd[n] = d->nb_cmd - 1;
-       for (i=0;i<d->nb_cmd;i++) {
-
-               it_prg[i].begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                       DMA_CTL_IMMEDIATE | 8) ;
-               it_prg[i].begin.address = 0;
-
-               it_prg[i].begin.status = 0;
-
-               it_prg[i].data[0] = cpu_to_le32(
-                       (IEEE1394_SPEED_100 << 16)
-                       | (/* tag */ 1 << 14)
-                       | (d->channel << 8)
-                       | (TCODE_ISO_DATA << 4));
-               if (i==0) it_prg[i].data[0] |= cpu_to_le32(sync_tag);
-               it_prg[i].data[1] = cpu_to_le32(d->packet_size << 16);
-               it_prg[i].data[2] = 0;
-               it_prg[i].data[3] = 0;
-
-               it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                            DMA_CTL_BRANCH);
-               it_prg[i].end.address =
-                       cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) -
-                                               (unsigned long)d->dma.kvirt));
-
-               if (i<d->nb_cmd-1) {
-                       it_prg[i].end.control |= cpu_to_le32(d->packet_size);
-                       it_prg[i].begin.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-                       it_prg[i].end.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-               } else {
-                       /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
-                               DMA_CTL_IRQ | d->left_size);
-                       /* the last prg doesn't branch */
-                       it_prg[i].begin.branchAddress = 0;
-                       it_prg[i].end.branchAddress = 0;
-               }
-               it_prg[i].end.status = 0;
-       }
-}
-
-static void initialize_dma_it_prg_var_packet_queue(
-       struct dma_iso_ctx *d, int n, unsigned int * packet_sizes,
-       struct ti_ohci *ohci)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       struct dma_prog_region *it_reg = &d->prg_reg[n];
-       int i;
-
-#if 0
-       if (n != -1) {
-               put_timestamp(ohci, d, n);
-       }
-#endif
-       d->last_used_cmd[n] = d->nb_cmd - 1;
-
-       for (i = 0; i < d->nb_cmd; i++) {
-               unsigned int size;
-               if (packet_sizes[i] > d->packet_size) {
-                       size = d->packet_size;
-               } else {
-                       size = packet_sizes[i];
-               }
-               it_prg[i].data[1] = cpu_to_le32(size << 16);
-               it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH);
-
-               if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
-                       it_prg[i].end.control |= cpu_to_le32(size);
-                       it_prg[i].begin.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-                       it_prg[i].end.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-               } else {
-                       /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
-                               DMA_CTL_IRQ | size);
-                       /* the last prg doesn't branch */
-                       it_prg[i].begin.branchAddress = 0;
-                       it_prg[i].end.branchAddress = 0;
-                       d->last_used_cmd[n] = i;
-                       break;
-               }
-       }
-}
-
-static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag,
-                                 unsigned int syt_offset, int flags)
-{
-       struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
-       int i;
-
-       d->flags = flags;
-       d->syt_offset = (syt_offset == 0 ? 11000 : syt_offset);
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0;i<d->num_desc;i++)
-               initialize_dma_it_prg(d, i, sync_tag);
-
-       /* Set up isoRecvIntMask to generate interrupts */
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
-}
-
-static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
-                                             unsigned int buffer)
-{
-       unsigned long flags;
-       unsigned int ret;
-       spin_lock_irqsave(&d->lock, flags);
-       ret = d->buffer_status[buffer];
-       spin_unlock_irqrestore(&d->lock, flags);
-       return ret;
-}
-
-static long video1394_ioctl(struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       struct file_ctx *ctx = file->private_data;
-       struct ti_ohci *ohci = ctx->ohci;
-       unsigned long flags;
-       void __user *argp = (void __user *)arg;
-
-       switch(cmd)
-       {
-       case VIDEO1394_IOC_LISTEN_CHANNEL:
-       case VIDEO1394_IOC_TALK_CHANNEL:
-       {
-               struct video1394_mmap v;
-               u64 mask;
-               struct dma_iso_ctx *d;
-               int i;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               /* if channel < 0, find lowest available one */
-               if (v.channel < 0) {
-                   mask = (u64)0x1;
-                   for (i=0; ; i++) {
-                       if (i == ISO_CHANNELS) {
-                           PRINT(KERN_ERR, ohci->host->id, 
-                                 "No free channel found");
-                           return -EAGAIN;
-                       }
-                       if (!(ohci->ISO_channel_usage & mask)) {
-                           v.channel = i;
-                           PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
-                           break;
-                       }
-                       mask = mask << 1;
-                   }
-               } else if (v.channel >= ISO_CHANNELS) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Iso channel %d out of bounds", v.channel);
-                       return -EINVAL;
-               } else {
-                       mask = (u64)0x1<<v.channel;
-               }
-               DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
-                       (u32)(mask>>32),(u32)(mask&0xffffffff),
-                       (u32)(ohci->ISO_channel_usage>>32),
-                       (u32)(ohci->ISO_channel_usage&0xffffffff));
-               if (ohci->ISO_channel_usage & mask) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Channel %d is already taken", v.channel);
-                       return -EBUSY;
-               }
-
-               if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Invalid %d length buffer requested",v.buf_size);
-                       return -EINVAL;
-               }
-
-               if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Invalid %d buffers requested",v.nb_buffers);
-                       return -EINVAL;
-               }
-
-               if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "%d buffers of size %d bytes is too big",
-                             v.nb_buffers, v.buf_size);
-                       return -EINVAL;
-               }
-
-               if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
-                       d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
-                                             v.nb_buffers + 1, v.buf_size,
-                                             v.channel, 0);
-
-                       if (d == NULL) {
-                               PRINT(KERN_ERR, ohci->host->id,
-                                     "Couldn't allocate ir context");
-                               return -EAGAIN;
-                       }
-                       initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
-
-                       ctx->current_ctx = d;
-
-                       v.buf_size = d->buf_size;
-                       list_add_tail(&d->link, &ctx->context_list);
-
-                       DBGMSG(ohci->host->id,
-                             "iso context %d listen on channel %d",
-                             d->ctx, v.channel);
-               }
-               else {
-                       d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
-                                             v.nb_buffers + 1, v.buf_size,
-                                             v.channel, v.packet_size);
-
-                       if (d == NULL) {
-                               PRINT(KERN_ERR, ohci->host->id,
-                                     "Couldn't allocate it context");
-                               return -EAGAIN;
-                       }
-                       initialize_dma_it_ctx(d, v.sync_tag,
-                                             v.syt_offset, v.flags);
-
-                       ctx->current_ctx = d;
-
-                       v.buf_size = d->buf_size;
-
-                       list_add_tail(&d->link, &ctx->context_list);
-
-                       DBGMSG(ohci->host->id,
-                             "Iso context %d talk on channel %d", d->ctx,
-                             v.channel);
-               }
-
-               if (copy_to_user(argp, &v, sizeof(v))) {
-                       /* FIXME : free allocated dma resources */
-                       return -EFAULT;
-               }
-               
-               ohci->ISO_channel_usage |= mask;
-
-               return 0;
-       }
-       case VIDEO1394_IOC_UNLISTEN_CHANNEL:
-       case VIDEO1394_IOC_UNTALK_CHANNEL:
-       {
-               int channel;
-               u64 mask;
-               struct dma_iso_ctx *d;
-
-               if (copy_from_user(&channel, argp, sizeof(int)))
-                       return -EFAULT;
-
-               if (channel < 0 || channel >= ISO_CHANNELS) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Iso channel %d out of bound", channel);
-                       return -EINVAL;
-               }
-               mask = (u64)0x1<<channel;
-               if (!(ohci->ISO_channel_usage & mask)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Channel %d is not being used", channel);
-                       return -ESRCH;
-               }
-
-               /* Mark this channel as unused */
-               ohci->ISO_channel_usage &= ~mask;
-
-               if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL)
-                       d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);
-               else
-                       d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
-
-               if (d == NULL) return -ESRCH;
-               DBGMSG(ohci->host->id, "Iso context %d "
-                     "stop talking on channel %d", d->ctx, channel);
-               free_dma_iso_ctx(d);
-
-               return 0;
-       }
-       case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-               int next_prg;
-
-               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (unlikely(d == NULL))
-                       return -EFAULT;
-
-               if (unlikely(v.buffer >= d->num_desc - 1)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               spin_lock_irqsave(&d->lock,flags);
-
-               if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is already used",v.buffer);
-                       spin_unlock_irqrestore(&d->lock,flags);
-                       return -EBUSY;
-               }
-
-               d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
-
-               next_prg = (d->last_buffer + 1) % d->num_desc;
-               if (d->last_buffer>=0)
-                       d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
-                                       & 0xfffffff0) | 0x1);
-
-               d->last_buffer = next_prg;
-               reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
-
-               d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
-
-               spin_unlock_irqrestore(&d->lock,flags);
-
-               if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
-               {
-                       DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx);
-
-                       /* Tell the controller where the first program is */
-                       reg_write(ohci, d->cmdPtr,
-                                 dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
-
-                       /* Run IR context */
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-               }
-               else {
-                       /* Wake up dma context if necessary */
-                       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-                               DBGMSG(ohci->host->id,
-                                     "Waking up iso dma ctx=%d", d->ctx);
-                               reg_write(ohci, d->ctrlSet, 0x1000);
-                       }
-               }
-               return 0;
-
-       }
-       case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:
-       case VIDEO1394_IOC_LISTEN_POLL_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-               int i = 0;
-
-               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (unlikely(d == NULL))
-                       return -EFAULT;
-
-               if (unlikely(v.buffer > d->num_desc - 1)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               /*
-                * I change the way it works so that it returns
-                * the last received frame.
-                */
-               spin_lock_irqsave(&d->lock, flags);
-               switch(d->buffer_status[v.buffer]) {
-               case VIDEO1394_BUFFER_READY:
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       break;
-               case VIDEO1394_BUFFER_QUEUED:
-                       if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) {
-                           /* for polling, return error code EINTR */
-                           spin_unlock_irqrestore(&d->lock, flags);
-                           return -EINTR;
-                       }
-
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       wait_event_interruptible(d->waitq,
-                                       video1394_buffer_state(d, v.buffer) ==
-                                        VIDEO1394_BUFFER_READY);
-                       if (signal_pending(current))
-                                return -EINTR;
-                       spin_lock_irqsave(&d->lock, flags);
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       break;
-               default:
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is not queued",v.buffer);
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return -ESRCH;
-               }
-
-               /* set time of buffer */
-               v.filltime = d->buffer_time[v.buffer];
-
-               /*
-                * Look ahead to see how many more buffers have been received
-                */
-               i=0;
-               while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
-                      VIDEO1394_BUFFER_READY) {
-                       v.buffer=(v.buffer+1)%(d->num_desc - 1);
-                       i++;
-               }
-               spin_unlock_irqrestore(&d->lock, flags);
-
-               v.buffer=i;
-               if (unlikely(copy_to_user(argp, &v, sizeof(v))))
-                       return -EFAULT;
-
-               return 0;
-       }
-       case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
-       {
-               struct video1394_wait v;
-               unsigned int *psizes = NULL;
-               struct dma_iso_ctx *d;
-               int next_prg;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
-               if (d == NULL) return -EFAULT;
-
-               if (v.buffer >= d->num_desc - 1) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
-                       int buf_size = d->nb_cmd * sizeof(*psizes);
-                       struct video1394_queue_variable __user *p = argp;
-                       unsigned int __user *qv;
-
-                       if (get_user(qv, &p->packet_sizes))
-                               return -EFAULT;
-
-                       psizes = memdup_user(qv, buf_size);
-                       if (IS_ERR(psizes))
-                               return PTR_ERR(psizes);
-               }
-
-               spin_lock_irqsave(&d->lock,flags);
-
-               /* last_buffer is last_prg */
-               next_prg = (d->last_buffer + 1) % d->num_desc;
-               if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is already used",v.buffer);
-                       spin_unlock_irqrestore(&d->lock,flags);
-                       kfree(psizes);
-                       return -EBUSY;
-               }
-
-               if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
-                       initialize_dma_it_prg_var_packet_queue(
-                               d, next_prg, psizes, ohci);
-               }
-
-               d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
-
-               if (d->last_buffer >= 0) {
-                       d->it_prg[d->last_buffer]
-                               [ d->last_used_cmd[d->last_buffer] ].end.branchAddress =
-                                       cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
-                                               0) & 0xfffffff0) | 0x3);
-
-                       d->it_prg[d->last_buffer]
-                               [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
-                                       cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
-                                               0) & 0xfffffff0) | 0x3);
-                       d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1);
-               }
-               d->last_buffer = next_prg;
-               reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
-               d->next_buffer[d->last_buffer] = -1;
-
-               d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;
-
-               spin_unlock_irqrestore(&d->lock,flags);
-
-               if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
-               {
-                       DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",
-                              d->ctx);
-                       put_timestamp(ohci, d, d->last_buffer);
-                       dma_region_sync_for_device(&d->dma,
-                               v.buffer * d->buf_size, d->buf_size);
-
-                       /* Tell the controller where the first program is */
-                       reg_write(ohci, d->cmdPtr,
-                               dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
-
-                       /* Run IT context */
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-               }
-               else {
-                       /* Wake up dma context if necessary */
-                       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-                               DBGMSG(ohci->host->id,
-                                     "Waking up iso transmit dma ctx=%d",
-                                     d->ctx);
-                               put_timestamp(ohci, d, d->last_buffer);
-                               dma_region_sync_for_device(&d->dma,
-                                       v.buffer * d->buf_size, d->buf_size);
-
-                               reg_write(ohci, d->ctrlSet, 0x1000);
-                       }
-               }
-
-               kfree(psizes);
-               return 0;
-
-       }
-       case VIDEO1394_IOC_TALK_WAIT_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
-               if (d == NULL) return -EFAULT;
-
-               if (v.buffer >= d->num_desc - 1) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               switch(d->buffer_status[v.buffer]) {
-               case VIDEO1394_BUFFER_READY:
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       return 0;
-               case VIDEO1394_BUFFER_QUEUED:
-                       wait_event_interruptible(d->waitq,
-                                       (d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY));
-                       if (signal_pending(current))
-                               return -EINTR;
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       return 0;
-               default:
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is not queued",v.buffer);
-                       return -ESRCH;
-               }
-       }
-       default:
-               return -ENOTTY;
-       }
-}
-
-/*
- *     This maps the vmalloced and reserved buffer to user space.
- *
- *  FIXME:
- *  - PAGE_READONLY should suffice!?
- *  - remap_pfn_range is kind of inefficient for page by page remapping.
- *    But e.g. pte_alloc() does not work in modules ... :-(
- */
-
-static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct file_ctx *ctx = file->private_data;
-
-       if (ctx->current_ctx == NULL) {
-               PRINT(KERN_ERR, ctx->ohci->host->id,
-                               "Current iso context not set");
-               return -EINVAL;
-       }
-
-       return dma_region_mmap(&ctx->current_ctx->dma, file, vma);
-}
-
-static unsigned int video1394_poll(struct file *file, poll_table *pt)
-{
-       struct file_ctx *ctx;
-       unsigned int mask = 0;
-       unsigned long flags;
-       struct dma_iso_ctx *d;
-       int i;
-
-       ctx = file->private_data;
-       d = ctx->current_ctx;
-       if (d == NULL) {
-               PRINT(KERN_ERR, ctx->ohci->host->id,
-                               "Current iso context not set");
-               return POLLERR;
-       }
-
-       poll_wait(file, &d->waitq, pt);
-
-       spin_lock_irqsave(&d->lock, flags);
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->buffer_status[i] == VIDEO1394_BUFFER_READY) {
-                       mask |= POLLIN | POLLRDNORM;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&d->lock, flags);
-
-       return mask;
-}
-
-static int video1394_open(struct inode *inode, struct file *file)
-{
-       int i = ieee1394_file_to_instance(file);
-       struct ti_ohci *ohci;
-       struct file_ctx *ctx;
-
-       ohci = hpsb_get_hostinfo_bykey(&video1394_highlevel, i);
-        if (ohci == NULL)
-                return -EIO;
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)  {
-               PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
-               return -ENOMEM;
-       }
-
-       ctx->ohci = ohci;
-       INIT_LIST_HEAD(&ctx->context_list);
-       ctx->current_ctx = NULL;
-       file->private_data = ctx;
-
-       return nonseekable_open(inode, file);
-}
-
-static int video1394_release(struct inode *inode, struct file *file)
-{
-       struct file_ctx *ctx = file->private_data;
-       struct ti_ohci *ohci = ctx->ohci;
-       struct list_head *lh, *next;
-       u64 mask;
-
-       list_for_each_safe(lh, next, &ctx->context_list) {
-               struct dma_iso_ctx *d;
-               d = list_entry(lh, struct dma_iso_ctx, link);
-               mask = (u64) 1 << d->channel;
-
-               if (!(ohci->ISO_channel_usage & mask))
-                       PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d "
-                             "is not being used", d->channel);
-               else
-                       ohci->ISO_channel_usage &= ~mask;
-               DBGMSG(ohci->host->id, "On release: Iso %s context "
-                     "%d stop listening on channel %d",
-                     d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit",
-                     d->ctx, d->channel);
-               free_dma_iso_ctx(d);
-       }
-
-       kfree(ctx);
-       file->private_data = NULL;
-
-       return 0;
-}
-
-#ifdef CONFIG_COMPAT
-static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
-#endif
-
-static struct cdev video1394_cdev;
-static const struct file_operations video1394_fops=
-{
-       .owner =        THIS_MODULE,
-       .unlocked_ioctl = video1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = video1394_compat_ioctl,
-#endif
-       .poll =         video1394_poll,
-       .mmap =         video1394_mmap,
-       .open =         video1394_open,
-       .release =      video1394_release,
-       .llseek =       no_llseek,
-};
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id video1394_id_table[] = {
-       {
-               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-               .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-               .version        = CAMERA_SW_VERSION_ENTRY & 0xffffff
-       },
-        {
-                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-                .version        = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff
-        },
-        {
-                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-                .version        = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
-        },
-       { }
-};
-
-MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver video1394_driver = {
-       .name = VIDEO1394_DRIVER_NAME,
-};
-
-
-static void video1394_add_host (struct hpsb_host *host)
-{
-       struct ti_ohci *ohci;
-       int minor;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       ohci = (struct ti_ohci *)host->hostdata;
-
-       if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) {
-               PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo");
-               return;
-       }
-
-       hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
-       hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
-
-       minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-       device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor),
-                     NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
-}
-
-
-static void video1394_remove_host (struct hpsb_host *host)
-{
-       struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
-
-       if (ohci)
-               device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-                              IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
-       return;
-}
-
-
-static struct hpsb_highlevel video1394_highlevel = {
-       .name =         VIDEO1394_DRIVER_NAME,
-       .add_host =     video1394_add_host,
-       .remove_host =  video1394_remove_host,
-};
-
-MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
-MODULE_DESCRIPTION("driver for digital video on OHCI board");
-MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-#ifdef CONFIG_COMPAT
-
-#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER     \
-       _IOW ('#', 0x12, struct video1394_wait32)
-#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER      \
-       _IOWR('#', 0x13, struct video1394_wait32)
-#define VIDEO1394_IOC32_TALK_WAIT_BUFFER        \
-       _IOW ('#', 0x17, struct video1394_wait32)
-#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER      \
-       _IOWR('#', 0x18, struct video1394_wait32)
-
-struct video1394_wait32 {
-       u32 channel;
-       u32 buffer;
-       struct compat_timeval filltime;
-};
-
-static int video1394_wr_wait32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        struct video1394_wait32 __user *argp = (void __user *)arg;
-        struct video1394_wait32 wait32;
-        struct video1394_wait wait;
-        mm_segment_t old_fs;
-        int ret;
-
-        if (copy_from_user(&wait32, argp, sizeof(wait32)))
-                return -EFAULT;
-
-        wait.channel = wait32.channel;
-        wait.buffer = wait32.buffer;
-        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
-        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
-
-        old_fs = get_fs();
-        set_fs(KERNEL_DS);
-        if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
-                                     (unsigned long) &wait);
-        else
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_POLL_BUFFER,
-                                     (unsigned long) &wait);
-        set_fs(old_fs);
-
-        if (!ret) {
-                wait32.channel = wait.channel;
-                wait32.buffer = wait.buffer;
-                wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
-                wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
-
-                if (copy_to_user(argp, &wait32, sizeof(wait32)))
-                        ret = -EFAULT;
-        }
-
-        return ret;
-}
-
-static int video1394_w_wait32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        struct video1394_wait32 wait32;
-        struct video1394_wait wait;
-        mm_segment_t old_fs;
-        int ret;
-
-        if (copy_from_user(&wait32, (void __user *)arg, sizeof(wait32)))
-                return -EFAULT;
-
-        wait.channel = wait32.channel;
-        wait.buffer = wait32.buffer;
-        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
-        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
-
-        old_fs = get_fs();
-        set_fs(KERNEL_DS);
-        if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
-                                     (unsigned long) &wait);
-        else
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_TALK_WAIT_BUFFER,
-                                     (unsigned long) &wait);
-        set_fs(old_fs);
-
-        return ret;
-}
-
-static int video1394_queue_buf32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        return -EFAULT;   /* ??? was there before. */
-
-       return video1394_ioctl(file,
-                               VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
-}
-
-static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case VIDEO1394_IOC_LISTEN_CHANNEL:
-       case VIDEO1394_IOC_UNLISTEN_CHANNEL:
-       case VIDEO1394_IOC_TALK_CHANNEL:
-       case VIDEO1394_IOC_UNTALK_CHANNEL:
-               return video1394_ioctl(f, cmd, arg);
-
-       case VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER:
-               return video1394_w_wait32(f, cmd, arg);
-       case VIDEO1394_IOC32_LISTEN_WAIT_BUFFER:
-               return video1394_wr_wait32(f, cmd, arg);
-       case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
-               return video1394_queue_buf32(f, cmd, arg);
-       case VIDEO1394_IOC32_TALK_WAIT_BUFFER:
-               return video1394_w_wait32(f, cmd, arg);
-       case VIDEO1394_IOC32_LISTEN_POLL_BUFFER:
-               return video1394_wr_wait32(f, cmd, arg);
-       default:
-               return -ENOIOCTLCMD;
-       }
-}
-
-#endif /* CONFIG_COMPAT */
-
-static void __exit video1394_exit_module (void)
-{
-       hpsb_unregister_protocol(&video1394_driver);
-       hpsb_unregister_highlevel(&video1394_highlevel);
-       cdev_del(&video1394_cdev);
-       PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
-}
-
-static int __init video1394_init_module (void)
-{
-       int ret;
-
-       hpsb_init_highlevel(&video1394_highlevel);
-
-       cdev_init(&video1394_cdev, &video1394_fops);
-       video1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
-       if (ret) {
-               PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
-               return ret;
-        }
-
-       hpsb_register_highlevel(&video1394_highlevel);
-
-       ret = hpsb_register_protocol(&video1394_driver);
-       if (ret) {
-               PRINT_G(KERN_ERR, "video1394: failed to register protocol");
-               hpsb_unregister_highlevel(&video1394_highlevel);
-               cdev_del(&video1394_cdev);
-               return ret;
-       }
-
-       PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
-       return 0;
-}
-
-
-module_init(video1394_init_module);
-module_exit(video1394_exit_module);
diff --git a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h
deleted file mode 100644 (file)
index 9a89d9c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * video1394.h - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Peter Schlaile <udbz@rz.uni-karlsruhe.de>
- *
- * 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, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _VIDEO_1394_H
-#define _VIDEO_1394_H
-
-#include "ieee1394-ioctl.h"
-
-#define VIDEO1394_DRIVER_NAME "video1394"
-
-#define VIDEO1394_MAX_SIZE 0x4000000
-
-enum {
-       VIDEO1394_BUFFER_FREE = 0,
-       VIDEO1394_BUFFER_QUEUED,
-       VIDEO1394_BUFFER_READY
-};
-
-#define VIDEO1394_SYNC_FRAMES          0x00000001
-#define VIDEO1394_INCLUDE_ISO_HEADERS  0x00000002
-#define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004
-
-struct video1394_mmap {
-       int channel;                    /* -1 to find an open channel in LISTEN/TALK */
-       unsigned int sync_tag;
-       unsigned int nb_buffers;
-       unsigned int buf_size;
-       unsigned int packet_size; /* For VARIABLE_PACKET_SIZE:
-                                    Maximum packet size */
-       unsigned int fps;
-       unsigned int syt_offset;
-       unsigned int flags;
-};
-
-/* For TALK_QUEUE_BUFFER with VIDEO1394_VARIABLE_PACKET_SIZE use */
-struct video1394_queue_variable {
-       unsigned int channel;
-       unsigned int buffer;
-       unsigned int __user * packet_sizes; /* Buffer of size:
-                                      buf_size / packet_size  */
-};
-
-struct video1394_wait {
-       unsigned int channel;
-       unsigned int buffer;
-       struct timeval filltime;        /* time of buffer full */
-};
-
-
-#endif
index 535fea4..e3f7fc6 100644 (file)
@@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
+static int evdev_handle_get_keycode(struct input_dev *dev,
+                                   void __user *p, size_t size)
+{
+       struct input_keymap_entry ke;
+       int error;
+
+       memset(&ke, 0, sizeof(ke));
+
+       if (size == sizeof(unsigned int[2])) {
+               /* legacy case */
+               int __user *ip = (int __user *)p;
+
+               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+                       return -EFAULT;
+
+               ke.len = sizeof(unsigned int);
+               ke.flags = 0;
+
+               error = input_get_keycode(dev, &ke);
+               if (error)
+                       return error;
+
+               if (put_user(ke.keycode, ip + 1))
+                       return -EFAULT;
+
+       } else {
+               size = min(size, sizeof(ke));
+
+               if (copy_from_user(&ke, p, size))
+                       return -EFAULT;
+
+               error = input_get_keycode(dev, &ke);
+               if (error)
+                       return error;
+
+               if (copy_to_user(p, &ke, size))
+                       return -EFAULT;
+       }
+       return 0;
+}
+
+static int evdev_handle_set_keycode(struct input_dev *dev,
+                                   void __user *p, size_t size)
+{
+       struct input_keymap_entry ke;
+
+       memset(&ke, 0, sizeof(ke));
+
+       if (size == sizeof(unsigned int[2])) {
+               /* legacy case */
+               int __user *ip = (int __user *)p;
+
+               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+                       return -EFAULT;
+
+               if (get_user(ke.keycode, ip + 1))
+                       return -EFAULT;
+
+               ke.len = sizeof(unsigned int);
+               ke.flags = 0;
+
+       } else {
+               size = min(size, sizeof(ke));
+
+               if (copy_from_user(&ke, p, size))
+                       return -EFAULT;
+
+               if (ke.len > sizeof(ke.scancode))
+                       return -EINVAL;
+       }
+
+       return input_set_keycode(dev, &ke);
+}
+
 static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                           void __user *p, int compat_mode)
 {
@@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                return 0;
 
-       case EVIOCGKEYCODE:
-               if (get_user(t, ip))
-                       return -EFAULT;
-
-               error = input_get_keycode(dev, t, &v);
-               if (error)
-                       return error;
-
-               if (put_user(v, ip + 1))
-                       return -EFAULT;
-
-               return 0;
-
-       case EVIOCSKEYCODE:
-               if (get_user(t, ip) || get_user(v, ip + 1))
-                       return -EFAULT;
-
-               return input_set_keycode(dev, t, v);
-
        case EVIOCRMFF:
                return input_ff_erase(dev, (int)(unsigned long) p, file);
 
@@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
        /* Now check variable-length commands */
 #define EVIOC_MASK_SIZE(nr)    ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
-
        switch (EVIOC_MASK_SIZE(cmd)) {
 
        case EVIOCGKEY(0):
@@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
+
+       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
+               return evdev_handle_get_keycode(dev, p, size);
+
+       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
+               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 7392992..422aa0a 100644 (file)
@@ -59,44 +59,52 @@ MODULE_DEVICE_TABLE(pci, emu_tbl);
 
 static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       int ioport, iolen;
        struct emu *emu;
        struct gameport *port;
-
-       if (pci_enable_device(pdev))
-               return -EBUSY;
-
-       ioport = pci_resource_start(pdev, 0);
-       iolen = pci_resource_len(pdev, 0);
-
-       if (!request_region(ioport, iolen, "emu10k1-gp"))
-               return -EBUSY;
+       int error;
 
        emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!emu || !port) {
                printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
-               release_region(ioport, iolen);
-               kfree(emu);
-               gameport_free_port(port);
-               return -ENOMEM;
+               error = -ENOMEM;
+               goto err_out_free;
        }
 
-       emu->io = ioport;
-       emu->size = iolen;
+       error = pci_enable_device(pdev);
+       if (error)
+               goto err_out_free;
+
+       emu->io = pci_resource_start(pdev, 0);
+       emu->size = pci_resource_len(pdev, 0);
+
        emu->dev = pdev;
        emu->gameport = port;
 
        gameport_set_name(port, "EMU10K1");
        gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
        port->dev.parent = &pdev->dev;
-       port->io = ioport;
+       port->io = emu->io;
+
+       if (!request_region(emu->io, emu->size, "emu10k1-gp")) {
+               printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n",
+                       emu->io, emu->io + emu->size - 1);
+               error = -EBUSY;
+               goto err_out_disable_dev;
+       }
 
        pci_set_drvdata(pdev, emu);
 
        gameport_register_port(port);
 
        return 0;
+
+ err_out_disable_dev:
+       pci_disable_device(pdev);
+ err_out_free:
+       gameport_free_port(port);
+       kfree(emu);
+       return error;
 }
 
 static void __devexit emu_remove(struct pci_dev *pdev)
@@ -106,6 +114,8 @@ static void __devexit emu_remove(struct pci_dev *pdev)
        gameport_unregister_port(emu->gameport);
        release_region(emu->io, emu->size);
        kfree(emu);
+
+       pci_disable_device(pdev);
 }
 
 static struct pci_driver emu_driver = {
index 14d3f3e..a3b70ff 100644 (file)
@@ -133,11 +133,11 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci)
 {
        struct fm801_gp *gp = pci_get_drvdata(pci);
 
-       if (gp) {
-               gameport_unregister_port(gp->gameport);
-               release_resource(gp->res_port);
-               kfree(gp);
-       }
+       gameport_unregister_port(gp->gameport);
+       release_resource(gp->res_port);
+       kfree(gp);
+
+       pci_disable_device(pci);
 }
 
 static const struct pci_device_id fm801_gp_id_table[] = {
index 7919c25..d092ef9 100644 (file)
@@ -171,7 +171,7 @@ static int input_handle_abs_event(struct input_dev *dev,
        if (code == ABS_MT_SLOT) {
                /*
                 * "Stage" the event; we'll flush it later, when we
-                * get actiual touch data.
+                * get actual touch data.
                 */
                if (*pval >= 0 && *pval < dev->mtsize)
                        dev->slot = *pval;
@@ -188,7 +188,7 @@ static int input_handle_abs_event(struct input_dev *dev,
                pold = &mtslot->abs[code - ABS_MT_FIRST];
        } else {
                /*
-                * Bypass filtering for multitouch events when
+                * Bypass filtering for multi-touch events when
                 * not employing slots.
                 */
                pold = NULL;
@@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev)
        spin_unlock_irq(&dev->event_lock);
 }
 
-static int input_fetch_keycode(struct input_dev *dev, int scancode)
+/**
+ * input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry
+ * @ke: keymap entry containing scancode to be converted.
+ * @scancode: pointer to the location where converted scancode should
+ *     be stored.
+ *
+ * This function is used to convert scancode stored in &struct keymap_entry
+ * into scalar form understood by legacy keymap handling methods. These
+ * methods expect scancodes to be represented as 'unsigned int'.
+ */
+int input_scancode_to_scalar(const struct input_keymap_entry *ke,
+                            unsigned int *scancode)
+{
+       switch (ke->len) {
+       case 1:
+               *scancode = *((u8 *)ke->scancode);
+               break;
+
+       case 2:
+               *scancode = *((u16 *)ke->scancode);
+               break;
+
+       case 4:
+               *scancode = *((u32 *)ke->scancode);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(input_scancode_to_scalar);
+
+/*
+ * Those routines handle the default case where no [gs]etkeycode() is
+ * defined. In this case, an array indexed by the scancode is used.
+ */
+
+static unsigned int input_fetch_keycode(struct input_dev *dev,
+                                       unsigned int index)
 {
        switch (dev->keycodesize) {
-               case 1:
-                       return ((u8 *)dev->keycode)[scancode];
+       case 1:
+               return ((u8 *)dev->keycode)[index];
 
-               case 2:
-                       return ((u16 *)dev->keycode)[scancode];
+       case 2:
+               return ((u16 *)dev->keycode)[index];
 
-               default:
-                       return ((u32 *)dev->keycode)[scancode];
+       default:
+               return ((u32 *)dev->keycode)[index];
        }
 }
 
 static int input_default_getkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int *keycode)
+                                   struct input_keymap_entry *ke)
 {
+       unsigned int index;
+       int error;
+
        if (!dev->keycodesize)
                return -EINVAL;
 
-       if (scancode >= dev->keycodemax)
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               index = ke->index;
+       else {
+               error = input_scancode_to_scalar(ke, &index);
+               if (error)
+                       return error;
+       }
+
+       if (index >= dev->keycodemax)
                return -EINVAL;
 
-       *keycode = input_fetch_keycode(dev, scancode);
+       ke->keycode = input_fetch_keycode(dev, index);
+       ke->index = index;
+       ke->len = sizeof(index);
+       memcpy(ke->scancode, &index, sizeof(index));
 
        return 0;
 }
 
 static int input_default_setkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int keycode)
+                                   const struct input_keymap_entry *ke,
+                                   unsigned int *old_keycode)
 {
-       int old_keycode;
+       unsigned int index;
+       int error;
        int i;
 
-       if (scancode >= dev->keycodemax)
+       if (!dev->keycodesize)
                return -EINVAL;
 
-       if (!dev->keycodesize)
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+       } else {
+               error = input_scancode_to_scalar(ke, &index);
+               if (error)
+                       return error;
+       }
+
+       if (index >= dev->keycodemax)
                return -EINVAL;
 
-       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+       if (dev->keycodesize < sizeof(dev->keycode) &&
+                       (ke->keycode >> (dev->keycodesize * 8)))
                return -EINVAL;
 
        switch (dev->keycodesize) {
                case 1: {
                        u8 *k = (u8 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
                case 2: {
                        u16 *k = (u16 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
                default: {
                        u32 *k = (u32 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
        }
 
-       __clear_bit(old_keycode, dev->keybit);
-       __set_bit(keycode, dev->keybit);
+       __clear_bit(*old_keycode, dev->keybit);
+       __set_bit(ke->keycode, dev->keybit);
 
        for (i = 0; i < dev->keycodemax; i++) {
-               if (input_fetch_keycode(dev, i) == old_keycode) {
-                       __set_bit(old_keycode, dev->keybit);
+               if (input_fetch_keycode(dev, i) == *old_keycode) {
+                       __set_bit(*old_keycode, dev->keybit);
                        break; /* Setting the bit twice is useless, so break */
                }
        }
@@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev,
 /**
  * input_get_keycode - retrieve keycode currently mapped to a given scancode
  * @dev: input device which keymap is being queried
- * @scancode: scancode (or its equivalent for device in question) for which
- *     keycode is needed
- * @keycode: result
+ * @ke: keymap entry
  *
  * This function should be called by anyone interested in retrieving current
- * keymap. Presently keyboard and evdev handlers use it.
+ * keymap. Presently evdev handlers use it.
  */
-int input_get_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int *keycode)
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
 {
        unsigned long flags;
        int retval;
 
        spin_lock_irqsave(&dev->event_lock, flags);
-       retval = dev->getkeycode(dev, scancode, keycode);
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
+       if (dev->getkeycode) {
+               /*
+                * Support for legacy drivers, that don't implement the new
+                * ioctls
+                */
+               u32 scancode = ke->index;
+
+               memcpy(ke->scancode, &scancode, sizeof(scancode));
+               ke->len = sizeof(scancode);
+               retval = dev->getkeycode(dev, scancode, &ke->keycode);
+       } else {
+               retval = dev->getkeycode_new(dev, ke);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
        return retval;
 }
 EXPORT_SYMBOL(input_get_keycode);
 
 /**
- * input_get_keycode - assign new keycode to a given scancode
+ * input_set_keycode - attribute a keycode to a given scancode
  * @dev: input device which keymap is being updated
- * @scancode: scancode (or its equivalent for device in question)
- * @keycode: new keycode to be assigned to the scancode
+ * @ke: new keymap entry
  *
  * This function should be called by anyone needing to update current
  * keymap. Presently keyboard and evdev handlers use it.
  */
 int input_set_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int keycode)
+                     const struct input_keymap_entry *ke)
 {
        unsigned long flags;
        unsigned int old_keycode;
        int retval;
 
-       if (keycode > KEY_MAX)
+       if (ke->keycode > KEY_MAX)
                return -EINVAL;
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
-       retval = dev->getkeycode(dev, scancode, &old_keycode);
-       if (retval)
-               goto out;
+       if (dev->setkeycode) {
+               /*
+                * Support for legacy drivers, that don't implement the new
+                * ioctls
+                */
+               unsigned int scancode;
+
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               /*
+                * We need to know the old scancode, in order to generate a
+                * keyup effect, if the set operation happens successfully
+                */
+               if (!dev->getkeycode) {
+                       retval = -EINVAL;
+                       goto out;
+               }
+
+               retval = dev->getkeycode(dev, scancode, &old_keycode);
+               if (retval)
+                       goto out;
+
+               retval = dev->setkeycode(dev, scancode, ke->keycode);
+       } else {
+               retval = dev->setkeycode_new(dev, ke, &old_keycode);
+       }
 
-       retval = dev->setkeycode(dev, scancode, keycode);
        if (retval)
                goto out;
 
@@ -1601,7 +1697,7 @@ EXPORT_SYMBOL(input_free_device);
  *
  * This function allocates all necessary memory for MT slot handling in the
  * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
- * are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1.
+ * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
  */
 int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
 {
@@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev)
                dev->rep[REP_PERIOD] = 33;
        }
 
-       if (!dev->getkeycode)
-               dev->getkeycode = input_default_getkeycode;
+       if (!dev->getkeycode && !dev->getkeycode_new)
+               dev->getkeycode_new = input_default_getkeycode;
 
-       if (!dev->setkeycode)
-               dev->setkeycode = input_default_setkeycode;
+       if (!dev->setkeycode && !dev->setkeycode_new)
+               dev->setkeycode_new = input_default_setkeycode;
 
        dev_set_name(&dev->dev, "input%ld",
                     (unsigned long) atomic_inc_return(&input_no) - 1);
index aa037fe..b8c51b9 100644 (file)
@@ -327,6 +327,16 @@ config KEYBOARD_NEWTON
          To compile this driver as a module, choose M here: the
          module will be called newtonkbd.
 
+config KEYBOARD_NOMADIK
+       tristate "ST-Ericsson Nomadik SKE keyboard"
+       depends on PLAT_NOMADIK
+       help
+         Say Y here if you want to use a keypad provided on the SKE controller
+         used on the Ux500 and Nomadik platforms
+
+         To compile this driver as a module, choose M here: the
+         module will be called nmk-ske-keypad.
+
 config KEYBOARD_OPENCORES
        tristate "OpenCores Keyboard Controller"
        help
@@ -424,6 +434,24 @@ config KEYBOARD_OMAP
          To compile this driver as a module, choose M here: the
          module will be called omap-keypad.
 
+config KEYBOARD_OMAP4
+       tristate "TI OMAP4 keypad support"
+       depends on ARCH_OMAP4
+       help
+         Say Y here if you want to use the OMAP4 keypad.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap4-keypad.
+
+config KEYBOARD_TNETV107X
+       tristate "TI TNETV107X keypad support"
+       depends on ARCH_DAVINCI_TNETV107X
+       help
+         Say Y here if you want to use the TNETV107X keypad.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tnetv107x-keypad.
+
 config KEYBOARD_TWL4030
        tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
        depends on TWL4030_CORE
index 504b591..a34452e 100644 (file)
@@ -28,7 +28,9 @@ obj-$(CONFIG_KEYBOARD_MATRIX)         += matrix_keypad.o
 obj-$(CONFIG_KEYBOARD_MAX7359)         += max7359_keypad.o
 obj-$(CONFIG_KEYBOARD_MCS)             += mcs_touchkey.o
 obj-$(CONFIG_KEYBOARD_NEWTON)          += newtonkbd.o
+obj-$(CONFIG_KEYBOARD_NOMADIK)         += nomadik-ske-keypad.o
 obj-$(CONFIG_KEYBOARD_OMAP)            += omap-keypad.o
+obj-$(CONFIG_KEYBOARD_OMAP4)           += omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)       += opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
@@ -38,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC)               += sh_keysc.o
 obj-$(CONFIG_KEYBOARD_STMPE)           += stmpe-keypad.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)                += stowaway.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)          += sunkbd.o
+obj-$(CONFIG_KEYBOARD_TNETV107X)       += tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)         += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)         += w90p910_keypad.o
index d6918cb..b92d1cd 100644 (file)
@@ -660,7 +660,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = {
 #endif
 
 static const struct i2c_device_id adp5588_id[] = {
-       { KBUILD_MODNAME, 0 },
+       { "adp5588-keys", 0 },
        { "adp5587-keys", 0 },
        { }
 };
index 19fa94a..fed31e0 100644 (file)
@@ -570,6 +570,8 @@ static struct serio_device_id hil_dev_ids[] = {
        { 0 }
 };
 
+MODULE_DEVICE_TABLE(serio, hil_dev_ids);
+
 static struct serio_driver hil_serio_drv = {
        .driver         = {
                .name   = "hil_dev",
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
new file mode 100644 (file)
index 0000000..6e0f230
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * License terms:GNU General Public License (GPL) version 2
+ *
+ * Keypad controller driver for the SKE (Scroll Key Encoder) module used in
+ * the Nomadik 8815 and Ux500 platforms.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <plat/ske.h>
+
+/* SKE_CR bits */
+#define SKE_KPMLT      (0x1 << 6)
+#define SKE_KPCN       (0x7 << 3)
+#define SKE_KPASEN     (0x1 << 2)
+#define SKE_KPASON     (0x1 << 7)
+
+/* SKE_IMSC bits */
+#define SKE_KPIMA      (0x1 << 2)
+
+/* SKE_ICR bits */
+#define SKE_KPICS      (0x1 << 3)
+#define SKE_KPICA      (0x1 << 2)
+
+/* SKE_RIS bits */
+#define SKE_KPRISA     (0x1 << 2)
+
+#define SKE_KEYPAD_ROW_SHIFT   3
+#define SKE_KPD_KEYMAP_SIZE    (8 * 8)
+
+/* keypad auto scan registers */
+#define SKE_ASR0       0x20
+#define SKE_ASR1       0x24
+#define SKE_ASR2       0x28
+#define SKE_ASR3       0x2C
+
+#define SKE_NUM_ASRX_REGISTERS (4)
+
+/**
+ * struct ske_keypad  - data structure used by keypad driver
+ * @irq:       irq no
+ * @reg_base:  ske regsiters base address
+ * @input:     pointer to input device object
+ * @board:     keypad platform device
+ * @keymap:    matrix scan code table for keycodes
+ * @clk:       clock structure pointer
+ */
+struct ske_keypad {
+       int irq;
+       void __iomem *reg_base;
+       struct input_dev *input;
+       const struct ske_keypad_platform_data *board;
+       unsigned short keymap[SKE_KPD_KEYMAP_SIZE];
+       struct clk *clk;
+       spinlock_t ske_keypad_lock;
+};
+
+static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
+               u8 mask, u8 data)
+{
+       u32 ret;
+
+       spin_lock(&keypad->ske_keypad_lock);
+
+       ret = readl(keypad->reg_base + addr);
+       ret &= ~mask;
+       ret |= data;
+       writel(ret, keypad->reg_base + addr);
+
+       spin_unlock(&keypad->ske_keypad_lock);
+}
+
+/*
+ * ske_keypad_chip_init: init keypad controller configuration
+ *
+ * Enable Multi key press detection, auto scan mode
+ */
+static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad)
+{
+       u32 value;
+       int timeout = 50;
+
+       /* check SKE_RIS to be 0 */
+       while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
+               cpu_relax();
+
+       if (!timeout)
+               return -EINVAL;
+
+       /*
+        * set debounce value
+        * keypad dbounce is configured in DBCR[15:8]
+        * dbounce value in steps of 32/32.768 ms
+        */
+       spin_lock(&keypad->ske_keypad_lock);
+       value = readl(keypad->reg_base + SKE_DBCR);
+       value = value & 0xff;
+       value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
+       writel(value, keypad->reg_base + SKE_DBCR);
+       spin_unlock(&keypad->ske_keypad_lock);
+
+       /* enable multi key detection */
+       ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
+
+       /*
+        * set up the number of columns
+        * KPCN[5:3] defines no. of keypad columns to be auto scanned
+        */
+       value = (keypad->board->kcol - 1) << 3;
+       ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
+
+       /* clear keypad interrupt for auto(and pending SW) scans */
+       ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
+
+       /* un-mask keypad interrupts */
+       ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       /* enable automatic scan */
+       ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
+
+       return 0;
+}
+
+static void ske_keypad_read_data(struct ske_keypad *keypad)
+{
+       struct input_dev *input = keypad->input;
+       u16 status;
+       int col = 0, row = 0, code;
+       int ske_asr, ske_ris, key_pressed, i;
+
+       /*
+        * Read the auto scan registers
+        *
+        * Each SKE_ASRx (x=0 to x=3) contains two row values.
+        * lower byte contains row value for column 2*x,
+        * upper byte contains row value for column 2*x + 1
+        */
+       for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
+               ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
+               if (!ske_asr)
+                       continue;
+
+               /* now that ASRx is zero, find out the column x and row y*/
+               if (ske_asr & 0xff) {
+                       col = i * 2;
+                       status = ske_asr & 0xff;
+               } else {
+                       col = (i * 2) + 1;
+                       status = (ske_asr & 0xff00) >> 8;
+               }
+
+               /* find out the row */
+               row = __ffs(status);
+
+               code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
+               ske_ris = readl(keypad->reg_base + SKE_RIS);
+               key_pressed = ske_ris & SKE_KPRISA;
+
+               input_event(input, EV_MSC, MSC_SCAN, code);
+               input_report_key(input, keypad->keymap[code], key_pressed);
+               input_sync(input);
+       }
+}
+
+static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
+{
+       struct ske_keypad *keypad = dev_id;
+       int retries = 20;
+
+       /* disable auto scan interrupt; mask the interrupt generated */
+       ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+       ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
+
+       while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --retries)
+               msleep(5);
+
+       if (retries) {
+               /* SKEx registers are stable and can be read */
+               ske_keypad_read_data(keypad);
+       }
+
+       /* enable auto scan interrupts */
+       ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit ske_keypad_probe(struct platform_device *pdev)
+{
+       const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
+       struct ske_keypad *keypad;
+       struct input_dev *input;
+       struct resource *res;
+       int irq;
+       int error;
+
+       if (!plat) {
+               dev_err(&pdev->dev, "invalid keypad platform data\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get keypad irq\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "missing platform resources\n");
+               return -EINVAL;
+       }
+
+       keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!keypad || !input) {
+               dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       keypad->irq = irq;
+       keypad->board = plat;
+       keypad->input = input;
+       spin_lock_init(&keypad->ske_keypad_lock);
+
+       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       keypad->reg_base = ioremap(res->start, resource_size(res));
+       if (!keypad->reg_base) {
+               dev_err(&pdev->dev, "failed to remap I/O memory\n");
+               error = -ENXIO;
+               goto err_free_mem_region;
+       }
+
+       keypad->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(keypad->clk)) {
+               dev_err(&pdev->dev, "failed to get clk\n");
+               error = PTR_ERR(keypad->clk);
+               goto err_iounmap;
+       }
+
+       input->id.bustype = BUS_HOST;
+       input->name = "ux500-ske-keypad";
+       input->dev.parent = &pdev->dev;
+
+       input->keycode = keypad->keymap;
+       input->keycodesize = sizeof(keypad->keymap[0]);
+       input->keycodemax = ARRAY_SIZE(keypad->keymap);
+
+       input_set_capability(input, EV_MSC, MSC_SCAN);
+
+       __set_bit(EV_KEY, input->evbit);
+       if (!plat->no_autorepeat)
+               __set_bit(EV_REP, input->evbit);
+
+       matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
+                       input->keycode, input->keybit);
+
+       clk_enable(keypad->clk);
+
+       /* go through board initialization helpers */
+       if (keypad->board->init)
+               keypad->board->init();
+
+       error = ske_keypad_chip_init(keypad);
+       if (error) {
+               dev_err(&pdev->dev, "unable to init keypad hardware\n");
+               goto err_clk_disable;
+       }
+
+       error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
+                                    IRQF_ONESHOT, "ske-keypad", keypad);
+       if (error) {
+               dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
+               goto err_clk_disable;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev,
+                               "unable to register input device: %d\n", error);
+               goto err_free_irq;
+       }
+
+       if (plat->wakeup_enable)
+               device_init_wakeup(&pdev->dev, true);
+
+       platform_set_drvdata(pdev, keypad);
+
+       return 0;
+
+err_free_irq:
+       free_irq(keypad->irq, keypad);
+err_clk_disable:
+       clk_disable(keypad->clk);
+       clk_put(keypad->clk);
+err_iounmap:
+       iounmap(keypad->reg_base);
+err_free_mem_region:
+       release_mem_region(res->start, resource_size(res));
+err_free_mem:
+       input_free_device(input);
+       kfree(keypad);
+       return error;
+}
+
+static int __devexit ske_keypad_remove(struct platform_device *pdev)
+{
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       free_irq(keypad->irq, keypad);
+
+       input_unregister_device(keypad->input);
+
+       clk_disable(keypad->clk);
+       clk_put(keypad->clk);
+
+       if (keypad->board->exit)
+               keypad->board->exit();
+
+       iounmap(keypad->reg_base);
+       release_mem_region(res->start, resource_size(res));
+       kfree(keypad);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ske_keypad_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(irq);
+       else
+               ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+
+       return 0;
+}
+
+static int ske_keypad_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(irq);
+       else
+               ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       return 0;
+}
+
+static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
+       .suspend = ske_keypad_suspend,
+       .resume = ske_keypad_resume,
+};
+#endif
+
+struct platform_driver ske_keypad_driver = {
+       .driver = {
+               .name = "nmk-ske-keypad",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm = &ske_keypad_dev_pm_ops,
+#endif
+       },
+       .probe = ske_keypad_probe,
+       .remove = __devexit_p(ske_keypad_remove),
+};
+
+static int __init ske_keypad_init(void)
+{
+       return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
+}
+module_init(ske_keypad_init);
+
+static void __exit ske_keypad_exit(void)
+{
+       platform_driver_unregister(&ske_keypad_driver);
+}
+module_exit(ske_keypad_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
+MODULE_ALIAS("platform:nomadik-ske-keypad");
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
new file mode 100644 (file)
index 0000000..45bd097
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * OMAP4 Keypad Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author: Abraham Arce <x0066660@ti.com>
+ * Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <plat/omap4-keypad.h>
+
+/* OMAP4 registers */
+#define OMAP4_KBD_REVISION             0x00
+#define OMAP4_KBD_SYSCONFIG            0x10
+#define OMAP4_KBD_SYSSTATUS            0x14
+#define OMAP4_KBD_IRQSTATUS            0x18
+#define OMAP4_KBD_IRQENABLE            0x1C
+#define OMAP4_KBD_WAKEUPENABLE         0x20
+#define OMAP4_KBD_PENDING              0x24
+#define OMAP4_KBD_CTRL                 0x28
+#define OMAP4_KBD_DEBOUNCINGTIME       0x2C
+#define OMAP4_KBD_LONGKEYTIME          0x30
+#define OMAP4_KBD_TIMEOUT              0x34
+#define OMAP4_KBD_STATEMACHINE         0x38
+#define OMAP4_KBD_ROWINPUTS            0x3C
+#define OMAP4_KBD_COLUMNOUTPUTS                0x40
+#define OMAP4_KBD_FULLCODE31_0         0x44
+#define OMAP4_KBD_FULLCODE63_32                0x48
+
+/* OMAP4 bit definitions */
+#define OMAP4_DEF_IRQENABLE_EVENTEN    (1 << 0)
+#define OMAP4_DEF_IRQENABLE_LONGKEY    (1 << 1)
+#define OMAP4_DEF_IRQENABLE_TIMEOUTEN  (1 << 2)
+#define OMAP4_DEF_WUP_EVENT_ENA                (1 << 0)
+#define OMAP4_DEF_WUP_LONG_KEY_ENA     (1 << 1)
+#define OMAP4_DEF_CTRL_NOSOFTMODE      (1 << 1)
+#define OMAP4_DEF_CTRLPTVVALUE         (1 << 2)
+#define OMAP4_DEF_CTRLPTV              (1 << 1)
+
+/* OMAP4 values */
+#define OMAP4_VAL_IRQDISABLE           0x00
+#define OMAP4_VAL_DEBOUNCINGTIME       0x07
+#define OMAP4_VAL_FUNCTIONALCFG                0x1E
+
+#define OMAP4_MASK_IRQSTATUSDISABLE    0xFFFF
+
+struct omap4_keypad {
+       struct input_dev *input;
+
+       void __iomem *base;
+       int irq;
+
+       unsigned int rows;
+       unsigned int cols;
+       unsigned int row_shift;
+       unsigned char key_state[8];
+       unsigned short keymap[];
+};
+
+static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
+{
+       __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
+                       keypad_data->base + OMAP4_KBD_CTRL);
+       __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
+                       keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+                       keypad_data->base + OMAP4_KBD_IRQENABLE);
+       __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
+                       keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+}
+
+/* Interrupt handler */
+static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
+{
+       struct omap4_keypad *keypad_data = dev_id;
+       struct input_dev *input_dev = keypad_data->input;
+       unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
+       unsigned int col, row, code, changed;
+       u32 *new_state = (u32 *) key_state;
+
+       /* Disable interrupts */
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                    keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+       *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
+       *(new_state + 1) = __raw_readl(keypad_data->base
+                                               + OMAP4_KBD_FULLCODE63_32);
+
+       for (row = 0; row < keypad_data->rows; row++) {
+               changed = key_state[row] ^ keypad_data->key_state[row];
+               if (!changed)
+                       continue;
+
+               for (col = 0; col < keypad_data->cols; col++) {
+                       if (changed & (1 << col)) {
+                               code = MATRIX_SCAN_CODE(row, col,
+                                               keypad_data->row_shift);
+                               input_event(input_dev, EV_MSC, MSC_SCAN, code);
+                               input_report_key(input_dev,
+                                                keypad_data->keymap[code],
+                                                key_state[row] & (1 << col));
+                       }
+               }
+       }
+
+       input_sync(input_dev);
+
+       memcpy(keypad_data->key_state, key_state,
+               sizeof(keypad_data->key_state));
+
+       /* clear pending interrupts */
+       __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+
+       /* enable interrupts */
+       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+                       keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit omap4_keypad_probe(struct platform_device *pdev)
+{
+       const struct omap4_keypad_platform_data *pdata;
+       struct omap4_keypad *keypad_data;
+       struct input_dev *input_dev;
+       struct resource *res;
+       resource_size_t size;
+       unsigned int row_shift, max_keys;
+       int irq;
+       int error;
+
+       /* platform data */
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no base address specified\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no keyboard irq assigned\n");
+               return -EINVAL;
+       }
+
+       if (!pdata->keymap_data) {
+               dev_err(&pdev->dev, "no keymap data defined\n");
+               return -EINVAL;
+       }
+
+       row_shift = get_count_order(pdata->cols);
+       max_keys = pdata->rows << row_shift;
+
+       keypad_data = kzalloc(sizeof(struct omap4_keypad) +
+                               max_keys * sizeof(keypad_data->keymap[0]),
+                             GFP_KERNEL);
+       if (!keypad_data) {
+               dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       size = resource_size(res);
+
+       res = request_mem_region(res->start, size, pdev->name);
+       if (!res) {
+               dev_err(&pdev->dev, "can't request mem region\n");
+               error = -EBUSY;
+               goto err_free_keypad;
+       }
+
+       keypad_data->base = ioremap(res->start, resource_size(res));
+       if (!keypad_data->base) {
+               dev_err(&pdev->dev, "can't ioremap mem resource\n");
+               error = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       keypad_data->irq = irq;
+       keypad_data->row_shift = row_shift;
+       keypad_data->rows = pdata->rows;
+       keypad_data->cols = pdata->cols;
+
+       /* input device allocation */
+       keypad_data->input = input_dev = input_allocate_device();
+       if (!input_dev) {
+               error = -ENOMEM;
+               goto err_unmap;
+       }
+
+       input_dev->name = pdev->name;
+       input_dev->dev.parent = &pdev->dev;
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0001;
+
+       input_dev->keycode      = keypad_data->keymap;
+       input_dev->keycodesize  = sizeof(keypad_data->keymap[0]);
+       input_dev->keycodemax   = max_keys;
+
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(EV_REP, input_dev->evbit);
+
+       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+       input_set_drvdata(input_dev, keypad_data);
+
+       matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
+                       input_dev->keycode, input_dev->keybit);
+
+       omap4_keypad_config(keypad_data);
+
+       error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
+                            IRQF_TRIGGER_RISING,
+                            "omap4-keypad", keypad_data);
+       if (error) {
+               dev_err(&pdev->dev, "failed to register interrupt\n");
+               goto err_free_input;
+       }
+
+       error = input_register_device(keypad_data->input);
+       if (error < 0) {
+               dev_err(&pdev->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+
+       platform_set_drvdata(pdev, keypad_data);
+       return 0;
+
+err_free_irq:
+       free_irq(keypad_data->irq, keypad_data);
+err_free_input:
+       input_free_device(input_dev);
+err_unmap:
+       iounmap(keypad_data->base);
+err_release_mem:
+       release_mem_region(res->start, size);
+err_free_keypad:
+       kfree(keypad_data);
+       return error;
+}
+
+static int __devexit omap4_keypad_remove(struct platform_device *pdev)
+{
+       struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       free_irq(keypad_data->irq, keypad_data);
+       input_unregister_device(keypad_data->input);
+
+       iounmap(keypad_data->base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(keypad_data);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver omap4_keypad_driver = {
+       .probe          = omap4_keypad_probe,
+       .remove         = __devexit_p(omap4_keypad_remove),
+       .driver         = {
+               .name   = "omap4-keypad",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init omap4_keypad_init(void)
+{
+       return platform_driver_register(&omap4_keypad_driver);
+}
+module_init(omap4_keypad_init);
+
+static void __exit omap4_keypad_exit(void)
+{
+       platform_driver_unregister(&omap4_keypad_driver);
+}
+module_exit(omap4_keypad_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("OMAP4 Keypad Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap4-keypad");
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c
new file mode 100644 (file)
index 0000000..b4a81eb
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Texas Instruments TNETV107X Keypad Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/input/matrix_keypad.h>
+
+#define BITS(x)                        (BIT(x) - 1)
+
+#define KEYPAD_ROWS            9
+#define KEYPAD_COLS            9
+
+#define DEBOUNCE_MIN           0x400ul
+#define DEBOUNCE_MAX           0x3ffffffful
+
+struct keypad_regs {
+       u32     rev;
+       u32     mode;
+       u32     mask;
+       u32     pol;
+       u32     dclock;
+       u32     rclock;
+       u32     stable_cnt;
+       u32     in_en;
+       u32     out;
+       u32     out_en;
+       u32     in;
+       u32     lock;
+       u32     pres[3];
+};
+
+#define keypad_read(kp, reg)           __raw_readl(&(kp)->regs->reg)
+#define keypad_write(kp, reg, val)     __raw_writel(val, &(kp)->regs->reg)
+
+struct keypad_data {
+       struct input_dev                *input_dev;
+       struct resource                 *res;
+       struct keypad_regs __iomem      *regs;
+       struct clk                      *clk;
+       struct device                   *dev;
+       spinlock_t                      lock;
+       u32                             irq_press;
+       u32                             irq_release;
+       int                             rows, cols, row_shift;
+       int                             debounce_ms, active_low;
+       u32                             prev_keys[3];
+       unsigned short                  keycodes[];
+};
+
+static irqreturn_t keypad_irq(int irq, void *data)
+{
+       struct keypad_data *kp = data;
+       int i, bit, val, row, col, code;
+       unsigned long flags;
+       u32 curr_keys[3];
+       u32 change;
+
+       spin_lock_irqsave(&kp->lock, flags);
+
+       memset(curr_keys, 0, sizeof(curr_keys));
+       if (irq == kp->irq_press)
+               for (i = 0; i < 3; i++)
+                       curr_keys[i] = keypad_read(kp, pres[i]);
+
+       for (i = 0; i < 3; i++) {
+               change = curr_keys[i] ^ kp->prev_keys[i];
+
+               while (change) {
+                       bit     = fls(change) - 1;
+                       change ^= BIT(bit);
+                       val     = curr_keys[i] & BIT(bit);
+                       bit    += i * 32;
+                       row     = bit / KEYPAD_COLS;
+                       col     = bit % KEYPAD_COLS;
+
+                       code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
+                       input_event(kp->input_dev, EV_MSC, MSC_SCAN, code);
+                       input_report_key(kp->input_dev, kp->keycodes[code],
+                                        val);
+               }
+       }
+       input_sync(kp->input_dev);
+       memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys));
+
+       if (irq == kp->irq_press)
+               keypad_write(kp, lock, 0); /* Allow hardware updates */
+
+       spin_unlock_irqrestore(&kp->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static int keypad_start(struct input_dev *dev)
+{
+       struct keypad_data *kp = input_get_drvdata(dev);
+       unsigned long mask, debounce, clk_rate_khz;
+       unsigned long flags;
+
+       clk_enable(kp->clk);
+       clk_rate_khz = clk_get_rate(kp->clk) / 1000;
+
+       spin_lock_irqsave(&kp->lock, flags);
+
+       /* Initialize device registers */
+       keypad_write(kp, mode, 0);
+
+       mask  = BITS(kp->rows) << KEYPAD_COLS;
+       mask |= BITS(kp->cols);
+       keypad_write(kp, mask, ~mask);
+
+       keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff);
+       keypad_write(kp, stable_cnt, 3);
+
+       debounce = kp->debounce_ms * clk_rate_khz;
+       debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX);
+       keypad_write(kp, dclock, debounce);
+       keypad_write(kp, rclock, 4 * debounce);
+
+       keypad_write(kp, in_en, 1);
+
+       spin_unlock_irqrestore(&kp->lock, flags);
+
+       return 0;
+}
+
+static void keypad_stop(struct input_dev *dev)
+{
+       struct keypad_data *kp = input_get_drvdata(dev);
+
+       synchronize_irq(kp->irq_press);
+       synchronize_irq(kp->irq_release);
+       clk_disable(kp->clk);
+}
+
+static int __devinit keypad_probe(struct platform_device *pdev)
+{
+       const struct matrix_keypad_platform_data *pdata;
+       const struct matrix_keymap_data *keymap_data;
+       struct device *dev = &pdev->dev;
+       struct keypad_data *kp;
+       int error = 0, sz, row_shift;
+       u32 rev = 0;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(dev, "cannot find device data\n");
+               return -EINVAL;
+       }
+
+       keymap_data = pdata->keymap_data;
+       if (!keymap_data) {
+               dev_err(dev, "cannot find keymap data\n");
+               return -EINVAL;
+       }
+
+       row_shift = get_count_order(pdata->num_col_gpios);
+       sz  = offsetof(struct keypad_data, keycodes);
+       sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]);
+       kp = kzalloc(sz, GFP_KERNEL);
+       if (!kp) {
+               dev_err(dev, "cannot allocate device info\n");
+               return -ENOMEM;
+       }
+
+       kp->dev  = dev;
+       kp->rows = pdata->num_row_gpios;
+       kp->cols = pdata->num_col_gpios;
+       kp->row_shift = row_shift;
+       platform_set_drvdata(pdev, kp);
+       spin_lock_init(&kp->lock);
+
+       kp->irq_press   = platform_get_irq_byname(pdev, "press");
+       kp->irq_release = platform_get_irq_byname(pdev, "release");
+       if (kp->irq_press < 0 || kp->irq_release < 0) {
+               dev_err(dev, "cannot determine device interrupts\n");
+               error = -ENODEV;
+               goto error_res;
+       }
+
+       kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!kp->res) {
+               dev_err(dev, "cannot determine register area\n");
+               error = -ENODEV;
+               goto error_res;
+       }
+
+       if (!request_mem_region(kp->res->start, resource_size(kp->res),
+                               pdev->name)) {
+               dev_err(dev, "cannot claim register memory\n");
+               kp->res = NULL;
+               error = -EINVAL;
+               goto error_res;
+       }
+
+       kp->regs = ioremap(kp->res->start, resource_size(kp->res));
+       if (!kp->regs) {
+               dev_err(dev, "cannot map register memory\n");
+               error = -ENOMEM;
+               goto error_map;
+       }
+
+       kp->clk = clk_get(dev, NULL);
+       if (!kp->clk) {
+               dev_err(dev, "cannot claim device clock\n");
+               error = -EINVAL;
+               goto error_clk;
+       }
+
+       error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0,
+                                    dev_name(dev), kp);
+       if (error < 0) {
+               dev_err(kp->dev, "Could not allocate keypad press key irq\n");
+               goto error_irq_press;
+       }
+
+       error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0,
+                                    dev_name(dev), kp);
+       if (error < 0) {
+               dev_err(kp->dev, "Could not allocate keypad release key irq\n");
+               goto error_irq_release;
+       }
+
+       kp->input_dev = input_allocate_device();
+       if (!kp->input_dev) {
+               dev_err(dev, "cannot allocate input device\n");
+               error = -ENOMEM;
+               goto error_input;
+       }
+       input_set_drvdata(kp->input_dev, kp);
+
+       kp->input_dev->name       = pdev->name;
+       kp->input_dev->dev.parent = &pdev->dev;
+       kp->input_dev->open       = keypad_start;
+       kp->input_dev->close      = keypad_stop;
+       kp->input_dev->evbit[0]   = BIT_MASK(EV_KEY);
+       if (!pdata->no_autorepeat)
+               kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
+
+       clk_enable(kp->clk);
+       rev = keypad_read(kp, rev);
+       kp->input_dev->id.bustype = BUS_HOST;
+       kp->input_dev->id.product = ((rev >>  8) & 0x07);
+       kp->input_dev->id.version = ((rev >> 16) & 0xfff);
+       clk_disable(kp->clk);
+
+       kp->input_dev->keycode     = kp->keycodes;
+       kp->input_dev->keycodesize = sizeof(kp->keycodes[0]);
+       kp->input_dev->keycodemax  = kp->rows << kp->row_shift;
+
+       matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes,
+                                  kp->input_dev->keybit);
+
+       input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
+
+       error = input_register_device(kp->input_dev);
+       if (error < 0) {
+               dev_err(dev, "Could not register input device\n");
+               goto error_reg;
+       }
+
+       return 0;
+
+
+error_reg:
+       input_free_device(kp->input_dev);
+error_input:
+       free_irq(kp->irq_release, kp);
+error_irq_release:
+       free_irq(kp->irq_press, kp);
+error_irq_press:
+       clk_put(kp->clk);
+error_clk:
+       iounmap(kp->regs);
+error_map:
+       release_mem_region(kp->res->start, resource_size(kp->res));
+error_res:
+       platform_set_drvdata(pdev, NULL);
+       kfree(kp);
+       return error;
+}
+
+static int __devexit keypad_remove(struct platform_device *pdev)
+{
+       struct keypad_data *kp = platform_get_drvdata(pdev);
+
+       free_irq(kp->irq_press, kp);
+       free_irq(kp->irq_release, kp);
+       input_unregister_device(kp->input_dev);
+       clk_put(kp->clk);
+       iounmap(kp->regs);
+       release_mem_region(kp->res->start, resource_size(kp->res));
+       platform_set_drvdata(pdev, NULL);
+       kfree(kp);
+
+       return 0;
+}
+
+static struct platform_driver keypad_driver = {
+       .probe          = keypad_probe,
+       .remove         = __devexit_p(keypad_remove),
+       .driver.name    = "tnetv107x-keypad",
+       .driver.owner   = THIS_MODULE,
+};
+
+static int __init keypad_init(void)
+{
+       return platform_driver_register(&keypad_driver);
+}
+
+static void __exit keypad_exit(void)
+{
+       platform_driver_unregister(&keypad_driver);
+}
+
+module_init(keypad_init);
+module_exit(keypad_exit);
+
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_DESCRIPTION("TNETV107X Keypad Driver");
+MODULE_ALIAS("platform: tnetv107x-keypad");
+MODULE_LICENSE("GPL");
index fb16b5e..09bef79 100644 (file)
@@ -406,23 +406,22 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
        if (error) {
                dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
                        kp->irq);
-               goto err3;
+               goto err2;
        }
 
        /* Enable KP and TO interrupts now. */
        reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
        if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) {
                error = -EIO;
-               goto err4;
+               goto err3;
        }
 
        platform_set_drvdata(pdev, kp);
        return 0;
 
-err4:
+err3:
        /* mask all events - we don't care about the result */
        (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1);
-err3:
        free_irq(kp->irq, NULL);
 err2:
        input_unregister_device(input);
index b49e233..b99b8cb 100644 (file)
@@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY
          To compile this driver as a module, choose M here: the module
          will be called 88pm860x_onkey.
 
+config INPUT_AB8500_PONKEY
+       tristate "AB8500 Pon (PowerOn) Key"
+       depends on AB8500_CORE
+       help
+         Say Y here to use the PowerOn Key for ST-Ericsson's AB8500
+         Mix-Sig PMIC.
+
+         To compile this driver as a module, choose M here: the module
+         will be called ab8500-ponkey.
+
 config INPUT_AD714X
        tristate "Analog Devices AD714x Capacitance Touch Sensor"
        help
index 19ccca7..1fe1f6c 100644 (file)
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT_88PM860X_ONKEY)     += 88pm860x_onkey.o
+obj-$(CONFIG_INPUT_AB8500_PONKEY)      += ab8500-ponkey.o
 obj-$(CONFIG_INPUT_AD714X)             += ad714x.o
 obj-$(CONFIG_INPUT_AD714X_I2C)         += ad714x-i2c.o
 obj-$(CONFIG_INPUT_AD714X_SPI)         += ad714x-spi.o
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
new file mode 100644 (file)
index 0000000..3d3288a
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * AB8500 Power-On Key handler
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/slab.h>
+
+/**
+ * struct ab8500_ponkey - ab8500 ponkey information
+ * @input_dev: pointer to input device
+ * @ab8500: ab8500 parent
+ * @irq_dbf: irq number for falling transition
+ * @irq_dbr: irq number for rising transition
+ */
+struct ab8500_ponkey {
+       struct input_dev        *idev;
+       struct ab8500           *ab8500;
+       int                     irq_dbf;
+       int                     irq_dbr;
+};
+
+/* AB8500 gives us an interrupt when ONKEY is held */
+static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
+{
+       struct ab8500_ponkey *ponkey = data;
+
+       if (irq == ponkey->irq_dbf)
+               input_report_key(ponkey->idev, KEY_POWER, true);
+       else if (irq == ponkey->irq_dbr)
+               input_report_key(ponkey->idev, KEY_POWER, false);
+
+       input_sync(ponkey->idev);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
+{
+       struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+       struct ab8500_ponkey *ponkey;
+       struct input_dev *input;
+       int irq_dbf, irq_dbr;
+       int error;
+
+       irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF");
+       if (irq_dbf < 0) {
+               dev_err(&pdev->dev, "No IRQ for ONKEY_DBF, error=%d\n", irq_dbf);
+               return irq_dbf;
+       }
+
+       irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR");
+       if (irq_dbr < 0) {
+               dev_err(&pdev->dev, "No IRQ for ONKEY_DBR, error=%d\n", irq_dbr);
+               return irq_dbr;
+       }
+
+       ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!ponkey || !input) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       ponkey->idev = input;
+       ponkey->ab8500 = ab8500;
+       ponkey->irq_dbf = irq_dbf;
+       ponkey->irq_dbr = irq_dbr;
+
+       input->name = "AB8500 POn(PowerOn) Key";
+       input->dev.parent = &pdev->dev;
+
+       input_set_capability(input, EV_KEY, KEY_POWER);
+
+       error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler,
+                                       0, "ab8500-ponkey-dbf", ponkey);
+       if (error < 0) {
+               dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",
+                       ponkey->irq_dbf, error);
+               goto err_free_mem;
+       }
+
+       error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler,
+                                       0, "ab8500-ponkey-dbr", ponkey);
+       if (error < 0) {
+               dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",
+                       ponkey->irq_dbr, error);
+               goto err_free_dbf_irq;
+       }
+
+       error = input_register_device(ponkey->idev);
+       if (error) {
+               dev_err(ab8500->dev, "Can't register input device: %d\n", error);
+               goto err_free_dbr_irq;
+       }
+
+       platform_set_drvdata(pdev, ponkey);
+       return 0;
+
+err_free_dbr_irq:
+       free_irq(ponkey->irq_dbr, ponkey);
+err_free_dbf_irq:
+       free_irq(ponkey->irq_dbf, ponkey);
+err_free_mem:
+       input_free_device(input);
+       kfree(ponkey);
+
+       return error;
+}
+
+static int __devexit ab8500_ponkey_remove(struct platform_device *pdev)
+{
+       struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
+
+       free_irq(ponkey->irq_dbf, ponkey);
+       free_irq(ponkey->irq_dbr, ponkey);
+       input_unregister_device(ponkey->idev);
+       kfree(ponkey);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver ab8500_ponkey_driver = {
+       .driver         = {
+               .name   = "ab8500-poweron-key",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ab8500_ponkey_probe,
+       .remove         = __devexit_p(ab8500_ponkey_remove),
+};
+
+static int __init ab8500_ponkey_init(void)
+{
+       return platform_driver_register(&ab8500_ponkey_driver);
+}
+module_init(ab8500_ponkey_init);
+
+static void __exit ab8500_ponkey_exit(void)
+{
+       platform_driver_unregister(&ab8500_ponkey_driver);
+}
+module_exit(ab8500_ponkey_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_DESCRIPTION("ST-Ericsson AB8500 Power-ON(Pon) Key driver");
index 2325765..0b0e9be 100644 (file)
@@ -483,51 +483,88 @@ static void ati_remote2_complete_key(struct urb *urb)
 }
 
 static int ati_remote2_getkeycode(struct input_dev *idev,
-                                 unsigned int scancode, unsigned int *keycode)
+                                 struct input_keymap_entry *ke)
 {
        struct ati_remote2 *ar2 = input_get_drvdata(idev);
        unsigned int mode;
-       int index;
+       int offset;
+       unsigned int index;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+               if (index >= ATI_REMOTE2_MODES *
+                               ARRAY_SIZE(ati_remote2_key_table))
+                       return -EINVAL;
+
+               mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
+               offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
+               scancode = (mode << 8) + ati_remote2_key_table[offset].hw_code;
+       } else {
+               if (input_scancode_to_scalar(ke, &scancode))
+                       return -EINVAL;
+
+               mode = scancode >> 8;
+               if (mode > ATI_REMOTE2_PC)
+                       return -EINVAL;
+
+               offset = ati_remote2_lookup(scancode & 0xff);
+               if (offset < 0)
+                       return -EINVAL;
+
+               index = mode * ARRAY_SIZE(ati_remote2_key_table) + offset;
+       }
 
-       mode = scancode >> 8;
-       if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
-               return -EINVAL;
+       ke->keycode = ar2->keycode[mode][offset];
+       ke->len = sizeof(scancode);
+       memcpy(&ke->scancode, &scancode, sizeof(scancode));
+       ke->index = index;
 
-       index = ati_remote2_lookup(scancode & 0xFF);
-       if (index < 0)
-               return -EINVAL;
-
-       *keycode = ar2->keycode[mode][index];
        return 0;
 }
 
 static int ati_remote2_setkeycode(struct input_dev *idev,
-                                 unsigned int scancode, unsigned int keycode)
+                                 const struct input_keymap_entry *ke,
+                                 unsigned int *old_keycode)
 {
        struct ati_remote2 *ar2 = input_get_drvdata(idev);
-       unsigned int mode, old_keycode;
-       int index;
-
-       mode = scancode >> 8;
-       if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
-               return -EINVAL;
-
-       index = ati_remote2_lookup(scancode & 0xFF);
-       if (index < 0)
-               return -EINVAL;
+       unsigned int mode;
+       int offset;
+       unsigned int index;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               if (ke->index >= ATI_REMOTE2_MODES *
+                               ARRAY_SIZE(ati_remote2_key_table))
+                       return -EINVAL;
+
+               mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
+               offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
+       } else {
+               if (input_scancode_to_scalar(ke, &scancode))
+                       return -EINVAL;
+
+               mode = scancode >> 8;
+               if (mode > ATI_REMOTE2_PC)
+                       return -EINVAL;
+
+               offset = ati_remote2_lookup(scancode & 0xff);
+               if (offset < 0)
+                       return -EINVAL;
+       }
 
-       old_keycode = ar2->keycode[mode][index];
-       ar2->keycode[mode][index] = keycode;
-       __set_bit(keycode, idev->keybit);
+       *old_keycode = ar2->keycode[mode][offset];
+       ar2->keycode[mode][offset] = ke->keycode;
+       __set_bit(ke->keycode, idev->keybit);
 
        for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
                for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
-                       if (ar2->keycode[mode][index] == old_keycode)
+                       if (ar2->keycode[mode][index] == *old_keycode)
                                return 0;
                }
        }
 
-       __clear_bit(old_keycode, idev->keybit);
+       __clear_bit(*old_keycode, idev->keybit);
 
        return 0;
 }
@@ -575,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->open = ati_remote2_open;
        idev->close = ati_remote2_close;
 
-       idev->getkeycode = ati_remote2_getkeycode;
-       idev->setkeycode = ati_remote2_setkeycode;
+       idev->getkeycode_new = ati_remote2_getkeycode;
+       idev->setkeycode_new = ati_remote2_setkeycode;
 
        idev->name = ar2->name;
        idev->phys = ar2->phys;
index bf170f6..f459471 100644 (file)
@@ -280,7 +280,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
 
        pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
        if (!pm->configcr)
-               return -1;
+               return -ENOMEM;
 
        return 0;
 }
index 4f9b2af..014dd4a 100644 (file)
@@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = {
        .probe          = twl4030_vibra_probe,
        .remove         = __devexit_p(twl4030_vibra_remove),
        .driver         = {
-               .name   = "twl4030_codec_vibra",
+               .name   = "twl4030-vibra",
                .owner  = THIS_MODULE,
 #ifdef CONFIG_PM
                .pm     = &twl4030_vibra_pm_ops,
@@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void)
 }
 module_exit(twl4030_vibra_exit);
 
-MODULE_ALIAS("platform:twl4030_codec_vibra");
+MODULE_ALIAS("platform:twl4030-vibra");
 
 MODULE_DESCRIPTION("TWL4030 Vibra driver");
 MODULE_LICENSE("GPL");
index 4831120..04d9bf3 100644 (file)
@@ -699,7 +699,7 @@ int elantech_init(struct psmouse *psmouse)
 
        psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
        if (!etd)
-               return -1;
+               return -ENOMEM;
 
        etd->parity[0] = 1;
        for (i = 1; i < 256; i++)
index 73a7af2..cd9d0c9 100644 (file)
@@ -1584,10 +1584,10 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
        if (!new_dev)
                return -ENOMEM;
 
-       while (serio->child) {
+       while (!list_empty(&serio->children)) {
                if (++retry > 3) {
                        printk(KERN_WARNING
-                               "psmouse: failed to destroy child port, "
+                               "psmouse: failed to destroy children ports, "
                                "protocol change aborted.\n");
                        input_free_device(new_dev);
                        return -EIO;
index 96b70a4..2e300a4 100644 (file)
@@ -294,7 +294,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c)
        return 0;
 }
 
-static inline int synaptics_is_pt_packet(unsigned char *buf)
+static int synaptics_pt_start(struct serio *serio)
+{
+       struct psmouse *parent = serio_get_drvdata(serio->parent);
+       struct synaptics_data *priv = parent->private;
+
+       serio_pause_rx(parent->ps2dev.serio);
+       priv->pt_port = serio;
+       serio_continue_rx(parent->ps2dev.serio);
+
+       return 0;
+}
+
+static void synaptics_pt_stop(struct serio *serio)
+{
+       struct psmouse *parent = serio_get_drvdata(serio->parent);
+       struct synaptics_data *priv = parent->private;
+
+       serio_pause_rx(parent->ps2dev.serio);
+       priv->pt_port = NULL;
+       serio_continue_rx(parent->ps2dev.serio);
+}
+
+static int synaptics_is_pt_packet(unsigned char *buf)
 {
        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
 }
@@ -315,9 +337,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-       struct serio *ptport = psmouse->ps2dev.serio->child;
-       struct psmouse *child = serio_get_drvdata(ptport);
        struct synaptics_data *priv = psmouse->private;
+       struct psmouse *child = serio_get_drvdata(priv->pt_port);
 
        /* adjust the touchpad to child's choice of protocol */
        if (child) {
@@ -345,6 +366,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
        strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
        strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
        serio->write = synaptics_pt_write;
+       serio->start = synaptics_pt_start;
+       serio->stop = synaptics_pt_stop;
        serio->parent = psmouse->ps2dev.serio;
 
        psmouse->pt_activate = synaptics_pt_activate;
@@ -578,9 +601,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
                if (unlikely(priv->pkt_type == SYN_NEWABS))
                        priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-               if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
-                       if (psmouse->ps2dev.serio->child)
-                               synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
+               if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
+                   synaptics_is_pt_packet(psmouse->packet)) {
+                       if (priv->pt_port)
+                               synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
                } else
                        synaptics_process_packet(psmouse);
 
@@ -731,7 +755,7 @@ int synaptics_init(struct psmouse *psmouse)
 
        psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
        if (!priv)
-               return -1;
+               return -ENOMEM;
 
        psmouse_reset(psmouse);
 
index b6aa7d2..613a365 100644 (file)
@@ -110,6 +110,8 @@ struct synaptics_data {
        unsigned char pkt_type;                 /* packet type - old, new, etc */
        unsigned char mode;                     /* current mode byte */
        int scroll;
+
+       struct serio *pt_port;                  /* Pass-through serio port */
 };
 
 void synaptics_module_init(void);
index 0643e49..54b2fa8 100644 (file)
@@ -303,7 +303,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 
        psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
        if (!psmouse->private)
-               return -1;
+               return -ENOMEM;
 
        psmouse->vendor = "IBM";
        psmouse->name = "TrackPoint";
index 31ec726..2a00ddf 100644 (file)
@@ -867,7 +867,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        spin_lock_init(&mousedev->client_lock);
        mutex_init(&mousedev->mutex);
        lockdep_set_subclass(&mousedev->mutex,
-                            minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0);
+                            minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0);
        init_waitqueue_head(&mousedev->wait);
 
        if (minor == MOUSEDEV_MIX)
index 3bfe8fa..6256233 100644 (file)
@@ -226,4 +226,13 @@ config SERIO_AMS_DELTA
          To compile this driver as a module, choose M here;
          the module will be called ams_delta_serio.
 
+config SERIO_PS2MULT
+       tristate "TQC PS/2 multiplexer"
+       help
+         Say Y here if you have the PS/2 line multiplexer like the one
+         present on TQC boads.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ps2mult.
+
 endif
index 84c80bf..dbbe376 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIO_GSCPS2)    += gscps2.o
 obj-$(CONFIG_HP_SDC)           += hp_sdc.o
 obj-$(CONFIG_HIL_MLC)          += hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)     += pcips2.o
+obj-$(CONFIG_SERIO_PS2MULT)    += ps2mult.o
 obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)     += libps2.o
 obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
index f585131..18db5a8 100644 (file)
@@ -1063,7 +1063,7 @@ static long i8042_panic_blink(int state)
 #ifdef CONFIG_X86
 static void i8042_dritek_enable(void)
 {
-       char param = 0x90;
+       unsigned char param = 0x90;
        int error;
 
        error = i8042_command(&param, 0x1059);
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c
new file mode 100644 (file)
index 0000000..6bce22e
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * TQC PS/2 Multiplexer driver
+ *
+ * Copyright (C) 2010 Dmitry Eremin-Solenikov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+
+MODULE_AUTHOR("Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>");
+MODULE_DESCRIPTION("TQC PS/2 Multiplexer driver");
+MODULE_LICENSE("GPL");
+
+#define PS2MULT_KB_SELECTOR            0xA0
+#define PS2MULT_MS_SELECTOR            0xA1
+#define PS2MULT_ESCAPE                 0x7D
+#define PS2MULT_BSYNC                  0x7E
+#define PS2MULT_SESSION_START          0x55
+#define PS2MULT_SESSION_END            0x56
+
+struct ps2mult_port {
+       struct serio *serio;
+       unsigned char sel;
+       bool registered;
+};
+
+#define PS2MULT_NUM_PORTS      2
+#define PS2MULT_KBD_PORT       0
+#define PS2MULT_MOUSE_PORT     1
+
+struct ps2mult {
+       struct serio *mx_serio;
+       struct ps2mult_port ports[PS2MULT_NUM_PORTS];
+
+       spinlock_t lock;
+       struct ps2mult_port *in_port;
+       struct ps2mult_port *out_port;
+       bool escape;
+};
+
+/* First MUST come PS2MULT_NUM_PORTS selectors */
+static const unsigned char ps2mult_controls[] = {
+       PS2MULT_KB_SELECTOR, PS2MULT_MS_SELECTOR,
+       PS2MULT_ESCAPE, PS2MULT_BSYNC,
+       PS2MULT_SESSION_START, PS2MULT_SESSION_END,
+};
+
+static const struct serio_device_id ps2mult_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_PS2MULT,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, ps2mult_serio_ids);
+
+static void ps2mult_select_port(struct ps2mult *psm, struct ps2mult_port *port)
+{
+       struct serio *mx_serio = psm->mx_serio;
+
+       serio_write(mx_serio, port->sel);
+       psm->out_port = port;
+       dev_dbg(&mx_serio->dev, "switched to sel %02x\n", port->sel);
+}
+
+static int ps2mult_serio_write(struct serio *serio, unsigned char data)
+{
+       struct serio *mx_port = serio->parent;
+       struct ps2mult *psm = serio_get_drvdata(mx_port);
+       struct ps2mult_port *port = serio->port_data;
+       bool need_escape;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       if (psm->out_port != port)
+               ps2mult_select_port(psm, port);
+
+       need_escape = memchr(ps2mult_controls, data, sizeof(ps2mult_controls));
+
+       dev_dbg(&serio->dev,
+               "write: %s%02x\n", need_escape ? "ESC " : "", data);
+
+       if (need_escape)
+               serio_write(mx_port, PS2MULT_ESCAPE);
+
+       serio_write(mx_port, data);
+
+       spin_unlock_irqrestore(&psm->lock, flags);
+
+       return 0;
+}
+
+static int ps2mult_serio_start(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio->parent);
+       struct ps2mult_port *port = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+       port->registered = true;
+       spin_unlock_irqrestore(&psm->lock, flags);
+
+       return 0;
+}
+
+static void ps2mult_serio_stop(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio->parent);
+       struct ps2mult_port *port = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+       port->registered = false;
+       spin_unlock_irqrestore(&psm->lock, flags);
+}
+
+static int ps2mult_create_port(struct ps2mult *psm, int i)
+{
+       struct serio *mx_serio = psm->mx_serio;
+       struct serio *serio;
+
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       strlcpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name));
+       snprintf(serio->phys, sizeof(serio->phys),
+                "%s/port%d", mx_serio->phys, i);
+       serio->id.type = SERIO_8042;
+       serio->write = ps2mult_serio_write;
+       serio->start = ps2mult_serio_start;
+       serio->stop = ps2mult_serio_stop;
+       serio->parent = psm->mx_serio;
+       serio->port_data = &psm->ports[i];
+
+       psm->ports[i].serio = serio;
+
+       return 0;
+}
+
+static void ps2mult_reset(struct ps2mult *psm)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       serio_write(psm->mx_serio, PS2MULT_SESSION_END);
+       serio_write(psm->mx_serio, PS2MULT_SESSION_START);
+
+       ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]);
+
+       spin_unlock_irqrestore(&psm->lock, flags);
+}
+
+static int ps2mult_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct ps2mult *psm;
+       int i;
+       int error;
+
+       if (!serio->write)
+               return -EINVAL;
+
+       psm = kzalloc(sizeof(*psm), GFP_KERNEL);
+       if (!psm)
+               return -ENOMEM;
+
+       spin_lock_init(&psm->lock);
+       psm->mx_serio = serio;
+
+       for (i = 0; i < PS2MULT_NUM_PORTS; i++) {
+               psm->ports[i].sel = ps2mult_controls[i];
+               error = ps2mult_create_port(psm, i);
+               if (error)
+                       goto err_out;
+       }
+
+       psm->in_port = psm->out_port = &psm->ports[PS2MULT_KBD_PORT];
+
+       serio_set_drvdata(serio, psm);
+       error = serio_open(serio, drv);
+       if (error)
+               goto err_out;
+
+       ps2mult_reset(psm);
+
+       for (i = 0; i <  PS2MULT_NUM_PORTS; i++) {
+               struct serio *s = psm->ports[i].serio;
+
+               dev_info(&serio->dev, "%s port at %s\n", s->name, serio->phys);
+               serio_register_port(s);
+       }
+
+       return 0;
+
+err_out:
+       while (--i >= 0)
+               kfree(psm->ports[i].serio);
+       kfree(serio);
+       return error;
+}
+
+static void ps2mult_disconnect(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+
+       /* Note that serio core already take care of children ports */
+       serio_write(serio, PS2MULT_SESSION_END);
+       serio_close(serio);
+       kfree(psm);
+
+       serio_set_drvdata(serio, NULL);
+}
+
+static int ps2mult_reconnect(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+
+       ps2mult_reset(psm);
+
+       return 0;
+}
+
+static irqreturn_t ps2mult_interrupt(struct serio *serio,
+                                    unsigned char data, unsigned int dfl)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+       struct ps2mult_port *in_port;
+       unsigned long flags;
+
+       dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl);
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       if (psm->escape) {
+               psm->escape = false;
+               in_port = psm->in_port;
+               if (in_port->registered)
+                       serio_interrupt(in_port->serio, data, dfl);
+               goto out;
+       }
+
+       switch (data) {
+       case PS2MULT_ESCAPE:
+               dev_dbg(&serio->dev, "ESCAPE\n");
+               psm->escape = true;
+               break;
+
+       case PS2MULT_BSYNC:
+               dev_dbg(&serio->dev, "BSYNC\n");
+               psm->in_port = psm->out_port;
+               break;
+
+       case PS2MULT_SESSION_START:
+               dev_dbg(&serio->dev, "SS\n");
+               break;
+
+       case PS2MULT_SESSION_END:
+               dev_dbg(&serio->dev, "SE\n");
+               break;
+
+       case PS2MULT_KB_SELECTOR:
+               dev_dbg(&serio->dev, "KB\n");
+               psm->in_port = &psm->ports[PS2MULT_KBD_PORT];
+               break;
+
+       case PS2MULT_MS_SELECTOR:
+               dev_dbg(&serio->dev, "MS\n");
+               psm->in_port = &psm->ports[PS2MULT_MOUSE_PORT];
+               break;
+
+       default:
+               in_port = psm->in_port;
+               if (in_port->registered)
+                       serio_interrupt(in_port->serio, data, dfl);
+               break;
+       }
+
+ out:
+       spin_unlock_irqrestore(&psm->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static struct serio_driver ps2mult_drv = {
+       .driver         = {
+               .name   = "ps2mult",
+       },
+       .description    = "TQC PS/2 Multiplexer driver",
+       .id_table       = ps2mult_serio_ids,
+       .interrupt      = ps2mult_interrupt,
+       .connect        = ps2mult_connect,
+       .disconnect     = ps2mult_disconnect,
+       .reconnect      = ps2mult_reconnect,
+};
+
+static int __init ps2mult_init(void)
+{
+       return serio_register_driver(&ps2mult_drv);
+}
+
+static void __exit ps2mult_exit(void)
+{
+       serio_unregister_driver(&ps2mult_drv);
+}
+
+module_init(ps2mult_init);
+module_exit(ps2mult_exit);
index c3b626e..405bf21 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/freezer.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -56,7 +55,7 @@ static struct bus_type serio_bus;
 static void serio_add_port(struct serio *serio);
 static int serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
-static void serio_reconnect_chain(struct serio *serio);
+static void serio_reconnect_subtree(struct serio *serio);
 static void serio_attach_driver(struct serio_driver *drv);
 
 static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
@@ -152,7 +151,7 @@ static void serio_find_driver(struct serio *serio)
 enum serio_event_type {
        SERIO_RESCAN_PORT,
        SERIO_RECONNECT_PORT,
-       SERIO_RECONNECT_CHAIN,
+       SERIO_RECONNECT_SUBTREE,
        SERIO_REGISTER_PORT,
        SERIO_ATTACH_DRIVER,
 };
@@ -292,8 +291,8 @@ static void serio_handle_event(void)
                        serio_find_driver(event->object);
                        break;
 
-               case SERIO_RECONNECT_CHAIN:
-                       serio_reconnect_chain(event->object);
+               case SERIO_RECONNECT_SUBTREE:
+                       serio_reconnect_subtree(event->object);
                        break;
 
                case SERIO_ATTACH_DRIVER:
@@ -330,12 +329,10 @@ static void serio_remove_pending_events(void *object)
 }
 
 /*
- * Destroy child serio port (if any) that has not been fully registered yet.
+ * Locate child serio port (if any) that has not been fully registered yet.
  *
- * Note that we rely on the fact that port can have only one child and therefore
- * only one child registration request can be pending. Additionally, children
- * are registered by driver's connect() handler so there can't be a grandchild
- * pending registration together with a child.
+ * Children are registered by driver's connect() handler so there can't be a
+ * grandchild pending registration together with a child.
  */
 static struct serio *serio_get_pending_child(struct serio *parent)
 {
@@ -449,7 +446,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
        if (!strncmp(buf, "none", count)) {
                serio_disconnect_port(serio);
        } else if (!strncmp(buf, "reconnect", count)) {
-               serio_reconnect_chain(serio);
+               serio_reconnect_subtree(serio);
        } else if (!strncmp(buf, "rescan", count)) {
                serio_disconnect_port(serio);
                serio_find_driver(serio);
@@ -516,6 +513,8 @@ static void serio_init_port(struct serio *serio)
        __module_get(THIS_MODULE);
 
        INIT_LIST_HEAD(&serio->node);
+       INIT_LIST_HEAD(&serio->child_node);
+       INIT_LIST_HEAD(&serio->children);
        spin_lock_init(&serio->lock);
        mutex_init(&serio->drv_mutex);
        device_initialize(&serio->dev);
@@ -538,12 +537,13 @@ static void serio_init_port(struct serio *serio)
  */
 static void serio_add_port(struct serio *serio)
 {
+       struct serio *parent = serio->parent;
        int error;
 
-       if (serio->parent) {
-               serio_pause_rx(serio->parent);
-               serio->parent->child = serio;
-               serio_continue_rx(serio->parent);
+       if (parent) {
+               serio_pause_rx(parent);
+               list_add_tail(&serio->child_node, &parent->children);
+               serio_continue_rx(parent);
        }
 
        list_add_tail(&serio->node, &serio_list);
@@ -559,15 +559,14 @@ static void serio_add_port(struct serio *serio)
 }
 
 /*
- * serio_destroy_port() completes deregistration process and removes
+ * serio_destroy_port() completes unregistration process and removes
  * port from the system
  */
 static void serio_destroy_port(struct serio *serio)
 {
        struct serio *child;
 
-       child = serio_get_pending_child(serio);
-       if (child) {
+       while ((child = serio_get_pending_child(serio)) != NULL) {
                serio_remove_pending_events(child);
                put_device(&child->dev);
        }
@@ -577,7 +576,7 @@ static void serio_destroy_port(struct serio *serio)
 
        if (serio->parent) {
                serio_pause_rx(serio->parent);
-               serio->parent->child = NULL;
+               list_del_init(&serio->child_node);
                serio_continue_rx(serio->parent);
                serio->parent = NULL;
        }
@@ -609,46 +608,82 @@ static int serio_reconnect_port(struct serio *serio)
 }
 
 /*
- * Reconnect serio port and all its children (re-initialize attached devices)
+ * Reconnect serio port and all its children (re-initialize attached
+ * devices).
  */
-static void serio_reconnect_chain(struct serio *serio)
+static void serio_reconnect_subtree(struct serio *root)
 {
+       struct serio *s = root;
+       int error;
+
        do {
-               if (serio_reconnect_port(serio)) {
-                       /* Ok, old children are now gone, we are done */
-                       break;
+               error = serio_reconnect_port(s);
+               if (!error) {
+                       /*
+                        * Reconnect was successful, move on to do the
+                        * first child.
+                        */
+                       if (!list_empty(&s->children)) {
+                               s = list_first_entry(&s->children,
+                                                    struct serio, child_node);
+                               continue;
+                       }
                }
-               serio = serio->child;
-       } while (serio);
+
+               /*
+                * Either it was a leaf node or reconnect failed and it
+                * became a leaf node. Continue reconnecting starting with
+                * the next sibling of the parent node.
+                */
+               while (s != root) {
+                       struct serio *parent = s->parent;
+
+                       if (!list_is_last(&s->child_node, &parent->children)) {
+                               s = list_entry(s->child_node.next,
+                                              struct serio, child_node);
+                               break;
+                       }
+
+                       s = parent;
+               }
+       } while (s != root);
 }
 
 /*
  * serio_disconnect_port() unbinds a port from its driver. As a side effect
- * all child ports are unbound and destroyed.
+ * all children ports are unbound and destroyed.
  */
 static void serio_disconnect_port(struct serio *serio)
 {
-       struct serio *s, *parent;
+       struct serio *s = serio;
+
+       /*
+        * Children ports should be disconnected and destroyed
+        * first; we travel the tree in depth-first order.
+        */
+       while (!list_empty(&serio->children)) {
+
+               /* Locate a leaf */
+               while (!list_empty(&s->children))
+                       s = list_first_entry(&s->children,
+                                            struct serio, child_node);
 
-       if (serio->child) {
                /*
-                * Children ports should be disconnected and destroyed
-                * first, staring with the leaf one, since we don't want
-                * to do recursion
+                * Prune this leaf node unless it is the one we
+                * started with.
                 */
-               for (s = serio; s->child; s = s->child)
-                       /* empty */;
-
-               do {
-                       parent = s->parent;
+               if (s != serio) {
+                       struct serio *parent = s->parent;
 
                        device_release_driver(&s->dev);
                        serio_destroy_port(s);
-               } while ((s = parent) != serio);
+
+                       s = parent;
+               }
        }
 
        /*
-        * Ok, no children left, now disconnect this port
+        * OK, no children left, now disconnect this port.
         */
        device_release_driver(&serio->dev);
 }
@@ -661,7 +696,7 @@ EXPORT_SYMBOL(serio_rescan);
 
 void serio_reconnect(struct serio *serio)
 {
-       serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
+       serio_queue_event(serio, NULL, SERIO_RECONNECT_SUBTREE);
 }
 EXPORT_SYMBOL(serio_reconnect);
 
@@ -689,14 +724,16 @@ void serio_unregister_port(struct serio *serio)
 EXPORT_SYMBOL(serio_unregister_port);
 
 /*
- * Safely unregisters child port if one is present.
+ * Safely unregisters children ports if they are present.
  */
 void serio_unregister_child_port(struct serio *serio)
 {
+       struct serio *s, *next;
+
        mutex_lock(&serio_mutex);
-       if (serio->child) {
-               serio_disconnect_port(serio->child);
-               serio_destroy_port(serio->child);
+       list_for_each_entry_safe(s, next, &serio->children, child_node) {
+               serio_disconnect_port(s);
+               serio_destroy_port(s);
        }
        mutex_unlock(&serio_mutex);
 }
index 0142483..a29a781 100644 (file)
@@ -22,6 +22,37 @@ MODULE_DESCRIPTION("Generic support for sparse keymaps");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.1");
 
+static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
+                                               const struct key_entry *k)
+{
+       struct key_entry *key;
+       unsigned int idx = 0;
+
+       for (key = dev->keycode; key->type != KE_END; key++) {
+               if (key->type == KE_KEY) {
+                       if (key == k)
+                               break;
+                       idx++;
+               }
+       }
+
+       return idx;
+}
+
+static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
+                                                     unsigned int index)
+{
+       struct key_entry *key;
+       unsigned int key_cnt = 0;
+
+       for (key = dev->keycode; key->type != KE_END; key++)
+               if (key->type == KE_KEY)
+                       if (key_cnt++ == index)
+                               return key;
+
+       return NULL;
+}
+
 /**
  * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
  * @dev: Input device using sparse keymap
@@ -64,16 +95,36 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
 }
 EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
 
+static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
+                                       const struct input_keymap_entry *ke)
+{
+       struct key_entry *key;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               key = sparse_keymap_entry_by_index(dev, ke->index);
+       else if (input_scancode_to_scalar(ke, &scancode) == 0)
+               key = sparse_keymap_entry_from_scancode(dev, scancode);
+       else
+               key = NULL;
+
+       return key;
+}
+
 static int sparse_keymap_getkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int *keycode)
+                                   struct input_keymap_entry *ke)
 {
        const struct key_entry *key;
 
        if (dev->keycode) {
-               key = sparse_keymap_entry_from_scancode(dev, scancode);
+               key = sparse_keymap_locate(dev, ke);
                if (key && key->type == KE_KEY) {
-                       *keycode = key->keycode;
+                       ke->keycode = key->keycode;
+                       if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+                               ke->index =
+                                       sparse_keymap_get_key_index(dev, key);
+                       ke->len = sizeof(key->code);
+                       memcpy(ke->scancode, &key->code, sizeof(key->code));
                        return 0;
                }
        }
@@ -82,20 +133,19 @@ static int sparse_keymap_getkeycode(struct input_dev *dev,
 }
 
 static int sparse_keymap_setkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int keycode)
+                                   const struct input_keymap_entry *ke,
+                                   unsigned int *old_keycode)
 {
        struct key_entry *key;
-       int old_keycode;
 
        if (dev->keycode) {
-               key = sparse_keymap_entry_from_scancode(dev, scancode);
+               key = sparse_keymap_locate(dev, ke);
                if (key && key->type == KE_KEY) {
-                       old_keycode = key->keycode;
-                       key->keycode = keycode;
-                       set_bit(keycode, dev->keybit);
-                       if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
-                               clear_bit(old_keycode, dev->keybit);
+                       *old_keycode = key->keycode;
+                       key->keycode = ke->keycode;
+                       set_bit(ke->keycode, dev->keybit);
+                       if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
+                               clear_bit(*old_keycode, dev->keybit);
                        return 0;
                }
        }
@@ -159,15 +209,14 @@ int sparse_keymap_setup(struct input_dev *dev,
 
        dev->keycode = map;
        dev->keycodemax = map_size;
-       dev->getkeycode = sparse_keymap_getkeycode;
-       dev->setkeycode = sparse_keymap_setkeycode;
+       dev->getkeycode_new = sparse_keymap_getkeycode;
+       dev->setkeycode_new = sparse_keymap_setkeycode;
 
        return 0;
 
  err_out:
        kfree(map);
        return error;
-
 }
 EXPORT_SYMBOL(sparse_keymap_setup);
 
index effb49e..58a8775 100644 (file)
@@ -49,6 +49,17 @@ config TABLET_USB_GTCO
           To compile this driver as a module, choose M here: the
           module will be called gtco.
 
+config TABLET_USB_HANWANG
+       tristate "Hanwang Art Master III tablet support (USB)"
+       depends on USB_ARCH_HAS_HCD
+       select USB
+       help
+         Say Y here if you want to use the USB version of the Hanwang Art
+         Master III tablet.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hanwang.
+
 config TABLET_USB_KBTAB
        tristate "KB Gear JamStudio tablet support (USB)"
        depends on USB_ARCH_HAS_HCD
index ce8b9a9..3f6c252 100644 (file)
@@ -8,5 +8,6 @@ wacom-objs      := wacom_wac.o wacom_sys.o
 obj-$(CONFIG_TABLET_USB_ACECAD)        += acecad.o
 obj-$(CONFIG_TABLET_USB_AIPTEK)        += aiptek.o
 obj-$(CONFIG_TABLET_USB_GTCO)  += gtco.o
+obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
 obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
 obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c
new file mode 100644 (file)
index 0000000..6504b62
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ *  USB Hanwang tablet support
+ *
+ *  Copyright (c) 2010 Xing Wei <weixing@hanwang.com.cn>
+ *
+ */
+
+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+
+#define DRIVER_AUTHOR   "Xing Wei <weixing@hanwang.com.cn>"
+#define DRIVER_DESC     "USB Hanwang tablet driver"
+#define DRIVER_LICENSE  "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_HANWANG          0x0b57
+#define HANWANG_TABLET_INT_CLASS       0x0003
+#define HANWANG_TABLET_INT_SUB_CLASS   0x0001
+#define HANWANG_TABLET_INT_PROTOCOL    0x0002
+
+#define ART_MASTER_PKGLEN_MAX  10
+
+/* device IDs */
+#define STYLUS_DEVICE_ID       0x02
+#define TOUCH_DEVICE_ID                0x03
+#define CURSOR_DEVICE_ID       0x06
+#define ERASER_DEVICE_ID       0x0A
+#define PAD_DEVICE_ID          0x0F
+
+/* match vendor and interface info  */
+#define HANWANG_TABLET_DEVICE(vend, cl, sc, pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_VENDOR \
+               | USB_DEVICE_ID_MATCH_INT_INFO, \
+       .idVendor = (vend), \
+       .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), \
+       .bInterfaceProtocol = (pr)
+
+enum hanwang_tablet_type {
+       HANWANG_ART_MASTER_III,
+       HANWANG_ART_MASTER_HD,
+};
+
+struct hanwang {
+       unsigned char *data;
+       dma_addr_t data_dma;
+       struct input_dev *dev;
+       struct usb_device *usbdev;
+       struct urb *irq;
+       const struct hanwang_features *features;
+       unsigned int current_tool;
+       unsigned int current_id;
+       char name[64];
+       char phys[32];
+};
+
+struct hanwang_features {
+       unsigned short pid;
+       char *name;
+       enum hanwang_tablet_type type;
+       int pkg_len;
+       int max_x;
+       int max_y;
+       int max_tilt_x;
+       int max_tilt_y;
+       int max_pressure;
+};
+
+static const struct hanwang_features features_array[] = {
+       { 0x8528, "Hanwang Art Master III 0906", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x5757, 0x3692, 0x3f, 0x7f, 2048 },
+       { 0x8529, "Hanwang Art Master III 0604", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x3d84, 0x2672, 0x3f, 0x7f, 2048 },
+       { 0x852a, "Hanwang Art Master III 1308", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 },
+       { 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD,
+         ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 },
+};
+
+static const int hw_eventtypes[] = {
+       EV_KEY, EV_ABS, EV_MSC,
+};
+
+static const int hw_absevents[] = {
+       ABS_X, ABS_Y, ABS_TILT_X, ABS_TILT_Y, ABS_WHEEL,
+       ABS_RX, ABS_RY, ABS_PRESSURE, ABS_MISC,
+};
+
+static const int hw_btnevents[] = {
+       BTN_STYLUS, BTN_STYLUS2, BTN_TOOL_PEN, BTN_TOOL_RUBBER,
+       BTN_TOOL_MOUSE, BTN_TOOL_FINGER,
+       BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8,
+};
+
+static const int hw_mscevents[] = {
+       MSC_SERIAL,
+};
+
+static void hanwang_parse_packet(struct hanwang *hanwang)
+{
+       unsigned char *data = hanwang->data;
+       struct input_dev *input_dev = hanwang->dev;
+       struct usb_device *dev = hanwang->usbdev;
+       enum hanwang_tablet_type type = hanwang->features->type;
+       int i;
+       u16 x, y, p;
+
+       switch (data[0]) {
+       case 0x02:      /* data packet */
+               switch (data[1]) {
+               case 0x80:      /* tool prox out */
+                       hanwang->current_id = 0;
+                       input_report_key(input_dev, hanwang->current_tool, 0);
+                       break;
+
+               case 0xc2:      /* first time tool prox in */
+                       switch (data[3] & 0xf0) {
+                       case 0x20:      /* art_master III */
+                       case 0x30:      /* art_master_HD */
+                               hanwang->current_id = STYLUS_DEVICE_ID;
+                               hanwang->current_tool = BTN_TOOL_PEN;
+                               input_report_key(input_dev, BTN_TOOL_PEN, 1);
+                               break;
+                       case 0xa0:      /* art_master III */
+                       case 0xb0:      /* art_master_HD */
+                               hanwang->current_id = ERASER_DEVICE_ID;
+                               hanwang->current_tool = BTN_TOOL_RUBBER;
+                               input_report_key(input_dev, BTN_TOOL_RUBBER, 1);
+                               break;
+                       default:
+                               hanwang->current_id = 0;
+                               dev_dbg(&dev->dev,
+                                       "unknown tablet tool %02x ", data[0]);
+                               break;
+                       }
+                       break;
+
+               default:        /* tool data packet */
+                       x = (data[2] << 8) | data[3];
+                       y = (data[4] << 8) | data[5];
+
+                       switch (type) {
+                       case HANWANG_ART_MASTER_III:
+                               p = (data[6] << 3) |
+                                   ((data[7] & 0xc0) >> 5) |
+                                   (data[1] & 0x01);
+                               break;
+
+                       case HANWANG_ART_MASTER_HD:
+                               p = (data[7] >> 6) | (data[6] << 2);
+                               break;
+
+                       default:
+                               p = 0;
+                               break;
+                       }
+
+                       input_report_abs(input_dev, ABS_X,
+                                               le16_to_cpup((__le16 *)&x));
+                       input_report_abs(input_dev, ABS_Y,
+                                               le16_to_cpup((__le16 *)&y));
+                       input_report_abs(input_dev, ABS_PRESSURE,
+                                               le16_to_cpup((__le16 *)&p));
+                       input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f);
+                       input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f);
+                       input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02);
+                       input_report_key(input_dev, BTN_STYLUS2, data[1] & 0x04);
+                       break;
+               }
+               input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+               input_event(input_dev, EV_MSC, MSC_SERIAL,
+                               hanwang->features->pid);
+               break;
+
+       case 0x0c:
+               /* roll wheel */
+               hanwang->current_id = PAD_DEVICE_ID;
+
+               switch (type) {
+               case HANWANG_ART_MASTER_III:
+                       input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+                                                       data[2] || data[3]);
+                       input_report_abs(input_dev, ABS_WHEEL, data[1]);
+                       input_report_key(input_dev, BTN_0, data[2]);
+                       for (i = 0; i < 8; i++)
+                               input_report_key(input_dev,
+                                        BTN_1 + i, data[3] & (1 << i));
+                       break;
+
+               case HANWANG_ART_MASTER_HD:
+                       input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+                                       data[2] || data[3] || data[4] ||
+                                       data[5] || data[6]);
+                       input_report_abs(input_dev, ABS_RX,
+                                       ((data[1] & 0x1f) << 8) | data[2]);
+                       input_report_abs(input_dev, ABS_RY,
+                                       ((data[3] & 0x1f) << 8) | data[4]);
+                       input_report_key(input_dev, BTN_0, data[5] & 0x01);
+                       for (i = 0; i < 4; i++) {
+                               input_report_key(input_dev,
+                                        BTN_1 + i, data[5] & (1 << i));
+                               input_report_key(input_dev,
+                                        BTN_5 + i, data[6] & (1 << i));
+                       }
+                       break;
+               }
+
+               input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+               input_event(input_dev, EV_MSC, MSC_SERIAL, 0xffffffff);
+               break;
+
+       default:
+               dev_dbg(&dev->dev, "error packet  %02x ", data[0]);
+               break;
+       }
+
+       input_sync(input_dev);
+}
+
+static void hanwang_irq(struct urb *urb)
+{
+       struct hanwang *hanwang = urb->context;
+       struct usb_device *dev = hanwang->usbdev;
+       int retval;
+
+       switch (urb->status) {
+       case 0:
+               /* success */;
+               hanwang_parse_packet(hanwang);
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dev_err(&dev->dev, "%s - urb shutting down with status: %d",
+                       __func__, urb->status);
+               return;
+       default:
+               dev_err(&dev->dev, "%s - nonzero urb status received: %d",
+                       __func__, urb->status);
+               break;
+       }
+
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
+               dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d",
+                       __func__, retval);
+}
+
+static int hanwang_open(struct input_dev *dev)
+{
+       struct hanwang *hanwang = input_get_drvdata(dev);
+
+       hanwang->irq->dev = hanwang->usbdev;
+       if (usb_submit_urb(hanwang->irq, GFP_KERNEL))
+               return -EIO;
+
+       return 0;
+}
+
+static void hanwang_close(struct input_dev *dev)
+{
+       struct hanwang *hanwang = input_get_drvdata(dev);
+
+       usb_kill_urb(hanwang->irq);
+}
+
+static bool get_features(struct usb_device *dev, struct hanwang *hanwang)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(features_array); i++) {
+               if (le16_to_cpu(dev->descriptor.idProduct) ==
+                               features_array[i].pid) {
+                       hanwang->features = &features_array[i];
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct hanwang *hanwang;
+       struct input_dev *input_dev;
+       int error;
+       int i;
+
+       hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!hanwang || !input_dev) {
+               error = -ENOMEM;
+               goto fail1;
+       }
+
+       if (!get_features(dev, hanwang)) {
+               error = -ENXIO;
+               goto fail1;
+       }
+
+       hanwang->data = usb_alloc_coherent(dev, hanwang->features->pkg_len,
+                                       GFP_KERNEL, &hanwang->data_dma);
+       if (!hanwang->data) {
+               error = -ENOMEM;
+               goto fail1;
+       }
+
+       hanwang->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!hanwang->irq) {
+               error = -ENOMEM;
+               goto fail2;
+       }
+
+       hanwang->usbdev = dev;
+       hanwang->dev = input_dev;
+
+       usb_make_path(dev, hanwang->phys, sizeof(hanwang->phys));
+       strlcat(hanwang->phys, "/input0", sizeof(hanwang->phys));
+
+       strlcpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name));
+       input_dev->name = hanwang->name;
+       input_dev->phys = hanwang->phys;
+       usb_to_input_id(dev, &input_dev->id);
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, hanwang);
+
+       input_dev->open = hanwang_open;
+       input_dev->close = hanwang_close;
+
+       for (i = 0; i < ARRAY_SIZE(hw_eventtypes); ++i)
+               __set_bit(hw_eventtypes[i], input_dev->evbit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_absevents); ++i)
+               __set_bit(hw_absevents[i], input_dev->absbit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_btnevents); ++i)
+               __set_bit(hw_btnevents[i], input_dev->keybit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_mscevents); ++i)
+               __set_bit(hw_mscevents[i], input_dev->mscbit);
+
+       input_set_abs_params(input_dev, ABS_X,
+                            0, hanwang->features->max_x, 4, 0);
+       input_set_abs_params(input_dev, ABS_Y,
+                            0, hanwang->features->max_y, 4, 0);
+       input_set_abs_params(input_dev, ABS_TILT_X,
+                            0, hanwang->features->max_tilt_x, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_Y,
+                            0, hanwang->features->max_tilt_y, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE,
+                            0, hanwang->features->max_pressure, 0, 0);
+
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+       usb_fill_int_urb(hanwang->irq, dev,
+                       usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+                       hanwang->data, hanwang->features->pkg_len,
+                       hanwang_irq, hanwang, endpoint->bInterval);
+       hanwang->irq->transfer_dma = hanwang->data_dma;
+       hanwang->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       error = input_register_device(hanwang->dev);
+       if (error)
+               goto fail3;
+
+       usb_set_intfdata(intf, hanwang);
+
+       return 0;
+
+ fail3:        usb_free_urb(hanwang->irq);
+ fail2:        usb_free_coherent(dev, hanwang->features->pkg_len,
+                       hanwang->data, hanwang->data_dma);
+ fail1:        input_free_device(input_dev);
+       kfree(hanwang);
+       return error;
+
+}
+
+static void hanwang_disconnect(struct usb_interface *intf)
+{
+       struct hanwang *hanwang = usb_get_intfdata(intf);
+
+       input_unregister_device(hanwang->dev);
+       usb_free_urb(hanwang->irq);
+       usb_free_coherent(interface_to_usbdev(intf),
+                       hanwang->features->pkg_len, hanwang->data,
+                       hanwang->data_dma);
+       kfree(hanwang);
+       usb_set_intfdata(intf, NULL);
+}
+
+static const struct usb_device_id hanwang_ids[] = {
+       { HANWANG_TABLET_DEVICE(USB_VENDOR_ID_HANWANG, HANWANG_TABLET_INT_CLASS,
+               HANWANG_TABLET_INT_SUB_CLASS, HANWANG_TABLET_INT_PROTOCOL) },
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, hanwang_ids);
+
+static struct usb_driver hanwang_driver = {
+       .name           = "hanwang",
+       .probe          = hanwang_probe,
+       .disconnect     = hanwang_disconnect,
+       .id_table       = hanwang_ids,
+};
+
+static int __init hanwang_init(void)
+{
+       return usb_register(&hanwang_driver);
+}
+
+static void __exit hanwang_exit(void)
+{
+       usb_deregister(&hanwang_driver);
+}
+
+module_init(hanwang_init);
+module_exit(hanwang_exit);
index 284dfaa..de5adb1 100644 (file)
@@ -118,6 +118,7 @@ struct wacom {
 extern const struct usb_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
+void wacom_setup_device_quirks(struct wacom_features *features);
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
                                    struct wacom_wac *wacom_wac);
 #endif
index b35876e..fc38149 100644 (file)
@@ -120,14 +120,16 @@ static int wacom_open(struct input_dev *dev)
 
 out:
        mutex_unlock(&wacom->lock);
-       if (retval)
-               usb_autopm_put_interface(wacom->intf);
+       usb_autopm_put_interface(wacom->intf);
        return retval;
 }
 
 static void wacom_close(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
+       int autopm_error;
+
+       autopm_error = usb_autopm_get_interface(wacom->intf);
 
        mutex_lock(&wacom->lock);
        usb_kill_urb(wacom->irq);
@@ -135,7 +137,8 @@ static void wacom_close(struct input_dev *dev)
        wacom->intf->needs_remote_wakeup = 0;
        mutex_unlock(&wacom->lock);
 
-       usb_autopm_put_interface(wacom->intf);
+       if (!autopm_error)
+               usb_autopm_put_interface(wacom->intf);
 }
 
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
@@ -196,17 +199,30 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                        features->device_type = BTN_TOOL_TRIPLETAP;
                                                }
-                                               features->x_max =
-                                                       get_unaligned_le16(&report[i + 3]);
-                                               features->x_phy =
-                                                       get_unaligned_le16(&report[i + 6]);
-                                               features->unit = report[i + 9];
-                                               features->unitExpo = report[i + 11];
-                                               i += 12;
+                                               if (features->type == BAMBOO_PT) {
+                                                       /* need to reset back */
+                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 5]);
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       i += 15;
+                                               } else {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 6]);
+                                                       features->unit = report[i + 9];
+                                                       features->unitExpo = report[i + 11];
+                                                       i += 12;
+                                               }
                                        } else if (pen) {
                                                /* penabled only accepts exact bytes of data */
                                                if (features->type == TABLETPC2FG)
                                                        features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               if (features->type == BAMBOO_PT)
+                                                       features->pktlen = WACOM_PKGLEN_BBFUN;
                                                features->device_type = BTN_TOOL_PEN;
                                                features->x_max =
                                                        get_unaligned_le16(&report[i + 3]);
@@ -235,6 +251,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (features->type == BAMBOO_PT) {
+                                                       /* need to reset back */
+                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 6]);
+                                                       i += 12;
                                                } else {
                                                        features->y_max =
                                                                features->x_max;
@@ -246,6 +271,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                /* penabled only accepts exact bytes of data */
                                                if (features->type == TABLETPC2FG)
                                                        features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               if (features->type == BAMBOO_PT)
+                                                       features->pktlen = WACOM_PKGLEN_BBFUN;
                                                features->device_type = BTN_TOOL_PEN;
                                                features->y_max =
                                                        get_unaligned_le16(&report[i + 3]);
@@ -296,8 +323,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
        if (!rep_data)
                return error;
 
-       /* ask to report tablet data if it is 2FGT or not a Tablet PC */
-       if (features->device_type == BTN_TOOL_TRIPLETAP) {
+       /* ask to report tablet data if it is 2FGT Tablet PC or
+        * not a Tablet PC */
+       if (features->type == TABLETPC2FG) {
                do {
                        rep_data[0] = 3;
                        rep_data[1] = 4;
@@ -309,7 +337,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                                        WAC_HID_FEATURE_REPORT, report_id,
                                        rep_data, 3);
                } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
-       } else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
+       } else if (features->type != TABLETPC) {
                do {
                        rep_data[0] = 2;
                        rep_data[1] = 2;
@@ -334,11 +362,16 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        struct usb_host_interface *interface = intf->cur_altsetting;
        struct hid_descriptor *hid_desc;
 
-       /* default device to penabled */
+       /* default features */
        features->device_type = BTN_TOOL_PEN;
-
-       /* only Tablet PCs need to retrieve the info */
-       if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
+       features->x_fuzz = 4;
+       features->y_fuzz = 4;
+       features->pressure_fuzz = 0;
+       features->distance_fuzz = 0;
+
+       /* only Tablet PCs and Bamboo P&T need to retrieve the info */
+       if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
+           (features->type != BAMBOO_PT))
                goto out;
 
        if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
@@ -353,12 +386,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        if (error)
                goto out;
 
-       /* touch device found but size is not defined. use default */
-       if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
-               features->x_max = 1023;
-               features->y_max = 1023;
-       }
-
  out:
        return error;
 }
@@ -494,9 +521,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        if (error)
                goto fail2;
 
+       wacom_setup_device_quirks(features);
+
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
-       if (features->type == TABLETPC || features->type == TABLETPC2FG) {
+       if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
index 47fd7a0..b3252ef 100644 (file)
@@ -857,6 +857,134 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
        return retval;
 }
 
+static int wacom_bpt_touch(struct wacom_wac *wacom)
+{
+       struct wacom_features *features = &wacom->features;
+       struct input_dev *input = wacom->input;
+       unsigned char *data = wacom->data;
+       int sp = 0, sx = 0, sy = 0, count = 0;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               int p = data[9 * i + 2];
+               input_mt_slot(input, i);
+               /*
+                * Touch events need to be disabled while stylus is
+                * in proximity because user's hand is resting on touchpad
+                * and sending unwanted events.  User expects tablet buttons
+                * to continue working though.
+                */
+               if (p && !wacom->shared->stylus_in_proximity) {
+                       int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
+                       int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
+                       if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
+                               x <<= 5;
+                               y <<= 5;
+                       }
+                       input_report_abs(input, ABS_MT_PRESSURE, p);
+                       input_report_abs(input, ABS_MT_POSITION_X, x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, y);
+                       if (wacom->id[i] < 0)
+                               wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
+                       if (!count++)
+                               sp = p, sx = x, sy = y;
+               } else {
+                       wacom->id[i] = -1;
+               }
+               input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
+       }
+
+       input_report_key(input, BTN_TOUCH, count > 0);
+       input_report_key(input, BTN_TOOL_FINGER, count == 1);
+       input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
+
+       input_report_abs(input, ABS_PRESSURE, sp);
+       input_report_abs(input, ABS_X, sx);
+       input_report_abs(input, ABS_Y, sy);
+
+       input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+       input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+       input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+       input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+
+       input_sync(input);
+
+       return 0;
+}
+
+static int wacom_bpt_pen(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       unsigned char *data = wacom->data;
+       int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+       /*
+        * Similar to Graphire protocol, data[1] & 0x20 is proximity and
+        * data[1] & 0x18 is tool ID.  0x30 is safety check to ignore
+        * 2 unused tool ID's.
+        */
+       prox = (data[1] & 0x30) == 0x30;
+
+       /*
+        * All reports shared between PEN and RUBBER tool must be
+        * forced to a known starting value (zero) when transitioning to
+        * out-of-prox.
+        *
+        * If not reset then, to userspace, it will look like lost events
+        * if new tool comes in-prox with same values as previous tool sent.
+        *
+        * Hardware does report zero in most out-of-prox cases but not all.
+        */
+       if (prox) {
+               if (!wacom->shared->stylus_in_proximity) {
+                       if (data[1] & 0x08) {
+                               wacom->tool[0] = BTN_TOOL_RUBBER;
+                               wacom->id[0] = ERASER_DEVICE_ID;
+                       } else {
+                               wacom->tool[0] = BTN_TOOL_PEN;
+                               wacom->id[0] = STYLUS_DEVICE_ID;
+                       }
+                       wacom->shared->stylus_in_proximity = true;
+               }
+               x = le16_to_cpup((__le16 *)&data[2]);
+               y = le16_to_cpup((__le16 *)&data[4]);
+               p = le16_to_cpup((__le16 *)&data[6]);
+               d = data[8];
+               pen = data[1] & 0x01;
+               btn1 = data[1] & 0x02;
+               btn2 = data[1] & 0x04;
+       }
+
+       input_report_key(input, BTN_TOUCH, pen);
+       input_report_key(input, BTN_STYLUS, btn1);
+       input_report_key(input, BTN_STYLUS2, btn2);
+
+       input_report_abs(input, ABS_X, x);
+       input_report_abs(input, ABS_Y, y);
+       input_report_abs(input, ABS_PRESSURE, p);
+       input_report_abs(input, ABS_DISTANCE, d);
+
+       if (!prox) {
+               wacom->id[0] = 0;
+               wacom->shared->stylus_in_proximity = false;
+       }
+
+       input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
+       input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
+
+       return 1;
+}
+
+static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
+{
+       if (len == WACOM_PKGLEN_BBTOUCH)
+               return wacom_bpt_touch(wacom);
+       else if (len == WACOM_PKGLEN_BBFUN)
+               return wacom_bpt_pen(wacom);
+
+       return 0;
+}
+
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 {
        bool sync;
@@ -902,6 +1030,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_tpc_irq(wacom_wac, len);
                break;
 
+       case BAMBOO_PT:
+               sync = wacom_bpt_irq(wacom_wac, len);
+               break;
+
        default:
                sync = false;
                break;
@@ -911,26 +1043,17 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                input_sync(wacom_wac->input);
 }
 
-static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
 {
        struct input_dev *input_dev = wacom_wac->input;
 
        input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-       input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-       __set_bit(BTN_LEFT, input_dev->keybit);
-       __set_bit(BTN_RIGHT, input_dev->keybit);
-       __set_bit(BTN_MIDDLE, input_dev->keybit);
-       __set_bit(BTN_SIDE, input_dev->keybit);
-       __set_bit(BTN_EXTRA, input_dev->keybit);
 
        __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
        __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-       __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
        __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
        __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
        __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
-       __set_bit(BTN_TOOL_LENS, input_dev->keybit);
        __set_bit(BTN_STYLUS, input_dev->keybit);
        __set_bit(BTN_STYLUS2, input_dev->keybit);
 
@@ -939,10 +1062,55 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
        input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
        input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
        input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+}
+
+static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+{
+       struct input_dev *input_dev = wacom_wac->input;
+
+       input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+       wacom_setup_cintiq(wacom_wac);
+
+       __set_bit(BTN_LEFT, input_dev->keybit);
+       __set_bit(BTN_RIGHT, input_dev->keybit);
+       __set_bit(BTN_MIDDLE, input_dev->keybit);
+       __set_bit(BTN_SIDE, input_dev->keybit);
+       __set_bit(BTN_EXTRA, input_dev->keybit);
+       __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+       __set_bit(BTN_TOOL_LENS, input_dev->keybit);
+
        input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
        input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
 }
 
+void wacom_setup_device_quirks(struct wacom_features *features)
+{
+
+       /* touch device found but size is not defined. use default */
+       if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+               features->x_max = 1023;
+               features->y_max = 1023;
+       }
+
+       /* these device have multiple inputs */
+       if (features->type == TABLETPC || features->type == TABLETPC2FG ||
+           features->type == BAMBOO_PT)
+               features->quirks |= WACOM_QUIRK_MULTI_INPUT;
+
+       /* quirks for bamboo touch */
+       if (features->type == BAMBOO_PT &&
+           features->device_type == BTN_TOOL_TRIPLETAP) {
+               features->x_max <<= 5;
+               features->y_max <<= 5;
+               features->x_fuzz <<= 5;
+               features->y_fuzz <<= 5;
+               features->pressure_max = 256;
+               features->pressure_fuzz = 16;
+               features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
+       }
+}
+
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
                                    struct wacom_wac *wacom_wac)
 {
@@ -953,9 +1121,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        __set_bit(BTN_TOUCH, input_dev->keybit);
 
-       input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_X, 0, features->x_max,
+                            features->x_fuzz, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, features->y_max,
+                            features->y_fuzz, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
+                            features->pressure_fuzz, 0);
 
        __set_bit(ABS_MISC, input_dev->absbit);
 
@@ -1005,9 +1176,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(BTN_9, input_dev->keybit);
                /* fall through */
 
+       case CINTIQ:
+               for (i = 0; i < 8; i++)
+                       __set_bit(BTN_0 + i, input_dev->keybit);
+               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+
+               input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+               input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+               wacom_setup_cintiq(wacom_wac);
+               break;
+
        case INTUOS3:
        case INTUOS3L:
-       case CINTIQ:
                __set_bit(BTN_4, input_dev->keybit);
                __set_bit(BTN_5, input_dev->keybit);
                __set_bit(BTN_6, input_dev->keybit);
@@ -1078,6 +1259,38 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case PENPARTNER:
                __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
                break;
+
+       case BAMBOO_PT:
+               __clear_bit(ABS_MISC, input_dev->absbit);
+
+               if (features->device_type == BTN_TOOL_TRIPLETAP) {
+                       __set_bit(BTN_LEFT, input_dev->keybit);
+                       __set_bit(BTN_FORWARD, input_dev->keybit);
+                       __set_bit(BTN_BACK, input_dev->keybit);
+                       __set_bit(BTN_RIGHT, input_dev->keybit);
+
+                       __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+                       __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+
+                       input_mt_create_slots(input_dev, 2);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                                            0, features->x_max,
+                                            features->x_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                                            0, features->y_max,
+                                            features->y_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+                                            0, features->pressure_max,
+                                            features->pressure_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+                                            MAX_TRACKING_ID, 0, 0);
+               } else if (features->device_type == BTN_TOOL_PEN) {
+                       __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+                       __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+                       __set_bit(BTN_STYLUS, input_dev->keybit);
+                       __set_bit(BTN_STYLUS2, input_dev->keybit);
+               }
+               break;
        }
 }
 
@@ -1215,6 +1428,14 @@ static const struct wacom_features wacom_features_0xE3 =
        { "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG };
 static const struct wacom_features wacom_features_0x47 =
        { "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
+static struct wacom_features wacom_features_0xD0 =
+       { "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD1 =
+       { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD2 =
+       { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD3 =
+       { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
 
 #define USB_DEVICE_WACOM(prod)                                 \
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
@@ -1279,6 +1500,10 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xC6) },
        { USB_DEVICE_WACOM(0xC7) },
        { USB_DEVICE_WACOM(0xCE) },
+       { USB_DEVICE_WACOM(0xD0) },
+       { USB_DEVICE_WACOM(0xD1) },
+       { USB_DEVICE_WACOM(0xD2) },
+       { USB_DEVICE_WACOM(0xD3) },
        { USB_DEVICE_WACOM(0xF0) },
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
index 99e1a54..00ca015 100644 (file)
@@ -21,6 +21,7 @@
 #define WACOM_PKGLEN_INTUOS    10
 #define WACOM_PKGLEN_TPC1FG     5
 #define WACOM_PKGLEN_TPC2FG    14
+#define WACOM_PKGLEN_BBTOUCH   20
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
 #define WACOM_REPORT_TPC1FG            6
 #define WACOM_REPORT_TPC2FG            13
 
+/* device quirks */
+#define WACOM_QUIRK_MULTI_INPUT                0x0001
+#define WACOM_QUIRK_BBTOUCH_LOWRES     0x0002
+
+/* largest reported tracking id */
+#define MAX_TRACKING_ID                        0xfff
+
 enum {
        PENPARTNER = 0,
        GRAPHIRE,
@@ -44,6 +52,7 @@ enum {
        PTU,
        PL,
        DTU,
+       BAMBOO_PT,
        INTUOS,
        INTUOS3S,
        INTUOS3,
@@ -73,6 +82,11 @@ struct wacom_features {
        int y_phy;
        unsigned char unit;
        unsigned char unitExpo;
+       int x_fuzz;
+       int y_fuzz;
+       int pressure_fuzz;
+       int distance_fuzz;
+       unsigned quirks;
 };
 
 struct wacom_shared {
@@ -86,6 +100,7 @@ struct wacom_wac {
        int id[3];
        __u32 serial[2];
        int last_finger;
+       int trk_id;
        struct wacom_features features;
        struct wacom_shared *shared;
        struct input_dev *input;
index 0069d97..06ea8da 100644 (file)
@@ -98,6 +98,18 @@ config TOUCHSCREEN_BITSY
          To compile this driver as a module, choose M here: the
          module will be called h3600_ts_input.
 
+config TOUCHSCREEN_BU21013
+       tristate "BU21013 based touch panel controllers"
+       depends on I2C
+       help
+         Say Y here if you have a bu21013 touchscreen connected to
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bu21013_ts.
+
 config TOUCHSCREEN_CY8CTMG110
        tristate "cy8ctmg110 touchscreen"
        depends on I2C
@@ -214,6 +226,16 @@ config TOUCHSCREEN_WACOM_W8001
          To compile this driver as a module, choose M here: the
          module will be called wacom_w8001.
 
+config TOUCHSCREEN_LPC32XX
+       tristate "LPC32XX touchscreen controller"
+       depends on ARCH_LPC32XX
+       help
+         Say Y here if you have a LPC32XX device and want
+         to support the built-in touchscreen.
+
+         To compile this driver as a module, choose M here: the
+         module will be called lpc32xx_ts.
+
 config TOUCHSCREEN_MCS5000
        tristate "MELFAS MCS-5000 touchscreen"
        depends on I2C
@@ -250,6 +272,18 @@ config TOUCHSCREEN_INEXIO
          To compile this driver as a module, choose M here: the
          module will be called inexio.
 
+config TOUCHSCREEN_INTEL_MID
+       tristate "Intel MID platform resistive touchscreen"
+       depends on INTEL_SCU_IPC
+       help
+         Say Y here if you have a Intel MID based touchscreen in
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called intel_mid_touch.
+
 config TOUCHSCREEN_MK712
        tristate "ICS MicroClock MK712 touchscreen"
        help
@@ -328,6 +362,15 @@ config TOUCHSCREEN_MIGOR
          To compile this driver as a module, choose M here: the
          module will be called migor_ts.
 
+config TOUCHSCREEN_TNETV107X
+       tristate "TI TNETV107X touchscreen support"
+       depends on ARCH_DAVINCI_TNETV107X
+       help
+         Say Y here if you want to use the TNETV107X touchscreen.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tnetv107x-ts.
+
 config TOUCHSCREEN_TOUCHRIGHT
        tristate "Touchright serial touchscreen"
        select SERIO
index 28217e1..7cc1b4f 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)  += ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)   += cy8ctmg110_ts.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)       += da9034-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)      += dynapro.o
@@ -23,6 +24,8 @@ obj-$(CONFIG_TOUCHSCREEN_EETI)                += eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)      += fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)       += inexio.o
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)    += intel-mid-touch.o
+obj-$(CONFIG_TOUCHSCREEN_LPC32XX)      += lpc32xx_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MC13783)      += mc13783_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MCS5000)      += mcs5000_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MIGOR)                += migor_ts.o
@@ -37,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)    += penmount.o
 obj-$(CONFIG_TOUCHSCREEN_QT602240)     += qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)      += s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)                += stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_TNETV107X)    += tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)   += touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)   += touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)     += touchwin.o
index 5f0221c..a1952fc 100644 (file)
@@ -191,13 +191,12 @@ struct ad7877 {
        struct spi_message      msg;
 
        struct mutex            mutex;
-       unsigned                disabled:1;     /* P: mutex */
-       unsigned                gpio3:1;        /* P: mutex */
-       unsigned                gpio4:1;        /* P: mutex */
+       bool                    disabled;       /* P: mutex */
+       bool                    gpio3;          /* P: mutex */
+       bool                    gpio4;          /* P: mutex */
 
        spinlock_t              lock;
        struct timer_list       timer;          /* P: lock */
-       unsigned                pending:1;      /* P: lock */
 
        /*
         * DMA (thus cache coherency maintenance) requires the
@@ -206,8 +205,8 @@ struct ad7877 {
        u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
 };
 
-static int gpio3;
-module_param(gpio3, int, 0);
+static bool gpio3;
+module_param(gpio3, bool, 0);
 MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3");
 
 /*
@@ -230,6 +229,7 @@ static int ad7877_read(struct spi_device *spi, u16 reg)
                        AD7877_READADD(reg));
        req->xfer[0].tx_buf = &req->command;
        req->xfer[0].len = 2;
+       req->xfer[0].cs_change = 1;
 
        req->xfer[1].rx_buf = &req->sample;
        req->xfer[1].len = 2;
@@ -295,20 +295,25 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
 
        req->xfer[0].tx_buf = &req->reset;
        req->xfer[0].len = 2;
+       req->xfer[0].cs_change = 1;
 
        req->xfer[1].tx_buf = &req->ref_on;
        req->xfer[1].len = 2;
        req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+       req->xfer[1].cs_change = 1;
 
        req->xfer[2].tx_buf = &req->command;
        req->xfer[2].len = 2;
        req->xfer[2].delay_usecs = ts->vref_delay_usecs;
+       req->xfer[2].cs_change = 1;
 
        req->xfer[3].rx_buf = &req->sample;
        req->xfer[3].len = 2;
+       req->xfer[3].cs_change = 1;
 
        req->xfer[4].tx_buf = &ts->cmd_crtl2;   /*REF OFF*/
        req->xfer[4].len = 2;
+       req->xfer[4].cs_change = 1;
 
        req->xfer[5].tx_buf = &ts->cmd_crtl1;   /*DEFAULT*/
        req->xfer[5].len = 2;
@@ -327,7 +332,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
        return status ? : sample;
 }
 
-static void ad7877_rx(struct ad7877 *ts)
+static int ad7877_process_data(struct ad7877 *ts)
 {
        struct input_dev *input_dev = ts->input;
        unsigned Rt;
@@ -354,11 +359,25 @@ static void ad7877_rx(struct ad7877 *ts)
                Rt /= z1;
                Rt = (Rt + 2047) >> 12;
 
+               /*
+                * Sample found inconsistent, pressure is beyond
+                * the maximum. Don't report it to user space.
+                */
+               if (Rt > ts->pressure_max)
+                       return -EINVAL;
+
+               if (!timer_pending(&ts->timer))
+                       input_report_key(input_dev, BTN_TOUCH, 1);
+
                input_report_abs(input_dev, ABS_X, x);
                input_report_abs(input_dev, ABS_Y, y);
                input_report_abs(input_dev, ABS_PRESSURE, Rt);
                input_sync(input_dev);
+
+               return 0;
        }
+
+       return -EINVAL;
 }
 
 static inline void ad7877_ts_event_release(struct ad7877 *ts)
@@ -366,72 +385,56 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
        struct input_dev *input_dev = ts->input;
 
        input_report_abs(input_dev, ABS_PRESSURE, 0);
+       input_report_key(input_dev, BTN_TOUCH, 0);
        input_sync(input_dev);
 }
 
 static void ad7877_timer(unsigned long handle)
 {
        struct ad7877 *ts = (void *)handle;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ts->lock, flags);
        ad7877_ts_event_release(ts);
+       spin_unlock_irqrestore(&ts->lock, flags);
 }
 
 static irqreturn_t ad7877_irq(int irq, void *handle)
 {
        struct ad7877 *ts = handle;
        unsigned long flags;
-       int status;
+       int error;
 
-       /*
-        * The repeated conversion sequencer controlled by TMR kicked off
-        * too fast. We ignore the last and process the sample sequence
-        * currently in the queue. It can't be older than 9.4ms, and we
-        * need to avoid that ts->msg doesn't get issued twice while in work.
-        */
+       error = spi_sync(ts->spi, &ts->msg);
+       if (error) {
+               dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
+               goto out;
+       }
 
        spin_lock_irqsave(&ts->lock, flags);
-       if (!ts->pending) {
-               ts->pending = 1;
-
-               status = spi_async(ts->spi, &ts->msg);
-               if (status)
-                       dev_err(&ts->spi->dev, "spi_sync --> %d\n", status);
-       }
+       error = ad7877_process_data(ts);
+       if (!error)
+               mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
        spin_unlock_irqrestore(&ts->lock, flags);
 
+out:
        return IRQ_HANDLED;
 }
 
-static void ad7877_callback(void *_ts)
-{
-       struct ad7877 *ts = _ts;
-
-       spin_lock_irq(&ts->lock);
-
-       ad7877_rx(ts);
-       ts->pending = 0;
-       mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
-
-       spin_unlock_irq(&ts->lock);
-}
-
 static void ad7877_disable(struct ad7877 *ts)
 {
        mutex_lock(&ts->mutex);
 
        if (!ts->disabled) {
-               ts->disabled = 1;
+               ts->disabled = true;
                disable_irq(ts->spi->irq);
 
-               /* Wait for spi_async callback */
-               while (ts->pending)
-                       msleep(1);
-
                if (del_timer_sync(&ts->timer))
                        ad7877_ts_event_release(ts);
        }
 
-       /* we know the chip's in lowpower mode since we always
+       /*
+        * We know the chip's in lowpower mode since we always
         * leave it that way after every request
         */
 
@@ -443,7 +446,7 @@ static void ad7877_enable(struct ad7877 *ts)
        mutex_lock(&ts->mutex);
 
        if (ts->disabled) {
-               ts->disabled = 0;
+               ts->disabled = false;
                enable_irq(ts->spi->irq);
        }
 
@@ -453,7 +456,7 @@ static void ad7877_enable(struct ad7877 *ts)
 #define SHOW(name) static ssize_t \
 name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
-       struct ad7877   *ts = dev_get_drvdata(dev); \
+       struct ad7877 *ts = dev_get_drvdata(dev); \
        ssize_t v = ad7877_read_adc(ts->spi, \
                        AD7877_READ_CHAN(name)); \
        if (v < 0) \
@@ -473,7 +476,7 @@ SHOW(temp2)
 static ssize_t ad7877_disable_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->disabled);
 }
@@ -503,7 +506,7 @@ static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store);
 static ssize_t ad7877_dac_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->dac);
 }
@@ -533,7 +536,7 @@ static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store);
 static ssize_t ad7877_gpio3_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->gpio3);
 }
@@ -564,7 +567,7 @@ static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store);
 static ssize_t ad7877_gpio4_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->gpio4);
 }
@@ -597,16 +600,35 @@ static struct attribute *ad7877_attributes[] = {
        &dev_attr_temp2.attr,
        &dev_attr_aux1.attr,
        &dev_attr_aux2.attr,
+       &dev_attr_aux3.attr,
        &dev_attr_bat1.attr,
        &dev_attr_bat2.attr,
        &dev_attr_disable.attr,
        &dev_attr_dac.attr,
+       &dev_attr_gpio3.attr,
        &dev_attr_gpio4.attr,
        NULL
 };
 
+static mode_t ad7877_attr_is_visible(struct kobject *kobj,
+                                    struct attribute *attr, int n)
+{
+       mode_t mode = attr->mode;
+
+       if (attr == &dev_attr_aux3.attr) {
+               if (gpio3)
+                       mode = 0;
+       } else if (attr == &dev_attr_gpio3.attr) {
+               if (!gpio3)
+                       mode = 0;
+       }
+
+       return mode;
+}
+
 static const struct attribute_group ad7877_attr_group = {
-       .attrs = ad7877_attributes,
+       .is_visible     = ad7877_attr_is_visible,
+       .attrs          = ad7877_attributes,
 };
 
 static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
@@ -635,22 +657,25 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
 
        spi_message_init(m);
 
-       m->complete = ad7877_callback;
        m->context = ts;
 
        ts->xfer[0].tx_buf = &ts->cmd_crtl1;
        ts->xfer[0].len = 2;
+       ts->xfer[0].cs_change = 1;
 
        spi_message_add_tail(&ts->xfer[0], m);
 
        ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */
        ts->xfer[1].len = 2;
+       ts->xfer[1].cs_change = 1;
 
        spi_message_add_tail(&ts->xfer[1], m);
 
-       for (i = 0; i < 11; i++) {
+       for (i = 0; i < AD7877_NR_SENSE; i++) {
                ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i];
                ts->xfer[i + 2].len = 2;
+               if (i < (AD7877_NR_SENSE - 1))
+                       ts->xfer[i + 2].cs_change = 1;
                spi_message_add_tail(&ts->xfer[i + 2], m);
        }
 }
@@ -718,6 +743,8 @@ static int __devinit ad7877_probe(struct spi_device *spi)
        input_dev->phys = ts->phys;
        input_dev->dev.parent = &spi->dev;
 
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(EV_ABS, input_dev->evbit);
        __set_bit(ABS_X, input_dev->absbit);
        __set_bit(ABS_Y, input_dev->absbit);
@@ -752,8 +779,9 @@ static int __devinit ad7877_probe(struct spi_device *spi)
 
        /* Request AD7877 /DAV GPIO interrupt */
 
-       err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
-                       spi->dev.driver->name, ts);
+       err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  spi->dev.driver->name, ts);
        if (err) {
                dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
                goto err_free_mem;
@@ -763,20 +791,12 @@ static int __devinit ad7877_probe(struct spi_device *spi)
        if (err)
                goto err_free_irq;
 
-       err = device_create_file(&spi->dev,
-                                gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
-       if (err)
-               goto err_remove_attr_group;
-
        err = input_register_device(input_dev);
        if (err)
-               goto err_remove_attr;
+               goto err_remove_attr_group;
 
        return 0;
 
-err_remove_attr:
-       device_remove_file(&spi->dev,
-                          gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 err_remove_attr_group:
        sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
 err_free_irq:
@@ -790,11 +810,9 @@ err_free_mem:
 
 static int __devexit ad7877_remove(struct spi_device *spi)
 {
-       struct ad7877           *ts = dev_get_drvdata(&spi->dev);
+       struct ad7877 *ts = dev_get_drvdata(&spi->dev);
 
        sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
-       device_remove_file(&spi->dev,
-                          gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 
        ad7877_disable(ts);
        free_irq(ts->spi->irq, ts);
index 1603193..14ea54b 100644 (file)
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <linux/types.h>
 #include <linux/hwmon.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
  * files.
  */
 
-#define TS_POLL_DELAY  (1 * 1000000)   /* ns delay before the first sample */
-#define TS_POLL_PERIOD (5 * 1000000)   /* ns delay between samples */
+#define TS_POLL_DELAY  1       /* ms delay before the first sample */
+#define TS_POLL_PERIOD 5       /* ms delay between samples */
 
 /* this driver doesn't aim at the peak continuous sample rate */
 #define        SAMPLE_BITS     (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
 
 struct ts_event {
-       /* For portability, we can't read 12 bit values using SPI (which
-        * would make the controller deliver them as native byteorder u16
+       /*
+        * For portability, we can't read 12 bit values using SPI (which
+        * would make the controller deliver them as native byte order u16
         * with msbs zeroed).  Instead, we read them as two 8-bit values,
         * *** WHICH NEED BYTESWAPPING *** and range adjustment.
         */
        u16     x;
        u16     y;
        u16     z1, z2;
-       int     ignore;
+       bool    ignore;
        u8      x_buf[3];
        u8      y_buf[3];
 };
@@ -110,8 +113,11 @@ struct ads7846 {
 
        struct spi_transfer     xfer[18];
        struct spi_message      msg[5];
-       struct spi_message      *last_msg;
-       int                     msg_idx;
+       int                     msg_count;
+       wait_queue_head_t       wait;
+
+       bool                    pendown;
+
        int                     read_cnt;
        int                     read_rep;
        int                     last_read;
@@ -122,14 +128,10 @@ struct ads7846 {
 
        u16                     penirq_recheck_delay_usecs;
 
-       spinlock_t              lock;
-       struct hrtimer          timer;
-       unsigned                pendown:1;      /* P: lock */
-       unsigned                pending:1;      /* P: lock */
-// FIXME remove "irq_disabled"
-       unsigned                irq_disabled:1; /* P: lock */
-       unsigned                disabled:1;
-       unsigned                is_suspended:1;
+       struct mutex            lock;
+       bool                    stopped;        /* P: lock */
+       bool                    disabled;       /* P: lock */
+       bool                    suspended;      /* P: lock */
 
        int                     (*filter)(void *data, int data_idx, int *val);
        void                    *filter_data;
@@ -165,7 +167,7 @@ struct ads7846 {
 #define        ADS_12_BIT              (0 << 3)
 #define        ADS_SER                 (1 << 2)        /* non-differential */
 #define        ADS_DFR                 (0 << 2)        /* differential */
-#define        ADS_PD10_PDOWN          (0 << 0)        /* lowpower mode + penirq */
+#define        ADS_PD10_PDOWN          (0 << 0)        /* low power mode + penirq */
 #define        ADS_PD10_ADC_ON         (1 << 0)        /* ADC on */
 #define        ADS_PD10_REF_ON         (2 << 0)        /* vREF on + penirq */
 #define        ADS_PD10_ALL_ON         (3 << 0)        /* ADC + vREF on */
@@ -193,6 +195,78 @@ struct ads7846 {
 #define        REF_ON  (READ_12BIT_DFR(x, 1, 1))
 #define        REF_OFF (READ_12BIT_DFR(y, 0, 0))
 
+/* Must be called with ts->lock held */
+static void ads7846_stop(struct ads7846 *ts)
+{
+       if (!ts->disabled && !ts->suspended) {
+               /* Signal IRQ thread to stop polling and disable the handler. */
+               ts->stopped = true;
+               mb();
+               wake_up(&ts->wait);
+               disable_irq(ts->spi->irq);
+       }
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_restart(struct ads7846 *ts)
+{
+       if (!ts->disabled && !ts->suspended) {
+               /* Tell IRQ thread that it may poll the device. */
+               ts->stopped = false;
+               mb();
+               enable_irq(ts->spi->irq);
+       }
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_disable(struct ads7846 *ts)
+{
+       ads7846_stop(ts);
+       regulator_disable(ts->reg);
+
+       /*
+        * We know the chip's in low power mode since we always
+        * leave it that way after every request
+        */
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_enable(struct ads7846 *ts)
+{
+       regulator_enable(ts->reg);
+       ads7846_restart(ts);
+}
+
+static void ads7846_disable(struct ads7846 *ts)
+{
+       mutex_lock(&ts->lock);
+
+       if (!ts->disabled) {
+
+               if  (!ts->suspended)
+                       __ads7846_disable(ts);
+
+               ts->disabled = true;
+       }
+
+       mutex_unlock(&ts->lock);
+}
+
+static void ads7846_enable(struct ads7846 *ts)
+{
+       mutex_lock(&ts->lock);
+
+       if (ts->disabled) {
+
+               ts->disabled = false;
+
+               if (!ts->suspended)
+                       __ads7846_enable(ts);
+       }
+
+       mutex_unlock(&ts->lock);
+}
+
 /*--------------------------------------------------------------------------*/
 
 /*
@@ -219,23 +293,15 @@ struct ads7845_ser_req {
        struct spi_transfer     xfer[2];
 };
 
-static void ads7846_enable(struct ads7846 *ts);
-static void ads7846_disable(struct ads7846 *ts);
-
-static int device_suspended(struct device *dev)
-{
-       struct ads7846 *ts = dev_get_drvdata(dev);
-       return ts->is_suspended || ts->disabled;
-}
-
 static int ads7846_read12_ser(struct device *dev, unsigned command)
 {
-       struct spi_device       *spi = to_spi_device(dev);
-       struct ads7846          *ts = dev_get_drvdata(dev);
-       struct ser_req          *req = kzalloc(sizeof *req, GFP_KERNEL);
-       int                     status;
-       int                     use_internal;
+       struct spi_device *spi = to_spi_device(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
+       struct ser_req *req;
+       int status;
+       int use_internal;
 
+       req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
@@ -282,11 +348,11 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
        CS_CHANGE(req->xfer[5]);
        spi_message_add_tail(&req->xfer[5], &req->msg);
 
-       ts->irq_disabled = 1;
-       disable_irq(spi->irq);
+       mutex_lock(&ts->lock);
+       ads7846_stop(ts);
        status = spi_sync(spi, &req->msg);
-       ts->irq_disabled = 0;
-       enable_irq(spi->irq);
+       ads7846_restart(ts);
+       mutex_unlock(&ts->lock);
 
        if (status == 0) {
                /* on-wire is a must-ignore bit, a BE12 value, then padding */
@@ -301,11 +367,12 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 
 static int ads7845_read12_ser(struct device *dev, unsigned command)
 {
-       struct spi_device       *spi = to_spi_device(dev);
-       struct ads7846          *ts = dev_get_drvdata(dev);
-       struct ads7845_ser_req  *req = kzalloc(sizeof *req, GFP_KERNEL);
-       int                     status;
+       struct spi_device *spi = to_spi_device(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
+       struct ads7845_ser_req *req;
+       int status;
 
+       req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
@@ -317,11 +384,11 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
        req->xfer[0].len = 3;
        spi_message_add_tail(&req->xfer[0], &req->msg);
 
-       ts->irq_disabled = 1;
-       disable_irq(spi->irq);
+       mutex_lock(&ts->lock);
+       ads7846_stop(ts);
        status = spi_sync(spi, &req->msg);
-       ts->irq_disabled = 0;
-       enable_irq(spi->irq);
+       ads7846_restart(ts);
+       mutex_unlock(&ts->lock);
 
        if (status == 0) {
                /* BE12 value, then padding */
@@ -374,6 +441,7 @@ static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
        /* external resistors may scale vAUX into 0..vREF */
        retval *= ts->vref_mv;
        retval = retval >> 12;
+
        return retval;
 }
 
@@ -384,13 +452,13 @@ static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v)
        /* ads7846 has a resistor ladder to scale this signal down */
        if (ts->model == 7846)
                retval *= 4;
+
        return retval;
 }
 
 SHOW(in0_input, vaux, vaux_adjust)
 SHOW(in1_input, vbatt, vbatt_adjust)
 
-
 static struct attribute *ads7846_attributes[] = {
        &dev_attr_temp0.attr,
        &dev_attr_temp1.attr,
@@ -498,17 +566,12 @@ static inline void ads784x_hwmon_unregister(struct spi_device *spi,
 }
 #endif
 
-static int is_pen_down(struct device *dev)
-{
-       struct ads7846  *ts = dev_get_drvdata(dev);
-
-       return ts->pendown;
-}
-
 static ssize_t ads7846_pen_down_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%u\n", is_pen_down(dev));
+       struct ads7846 *ts = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", ts->pendown);
 }
 
 static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
@@ -516,7 +579,7 @@ static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
 static ssize_t ads7846_disable_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ads7846  *ts = dev_get_drvdata(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->disabled);
 }
@@ -531,15 +594,11 @@ static ssize_t ads7846_disable_store(struct device *dev,
        if (strict_strtoul(buf, 10, &i))
                return -EINVAL;
 
-       spin_lock_irq(&ts->lock);
-
        if (i)
                ads7846_disable(ts);
        else
                ads7846_enable(ts);
 
-       spin_unlock_irq(&ts->lock);
-
        return count;
 }
 
@@ -569,23 +628,141 @@ static void null_wait_for_sync(void)
 {
 }
 
-/*
- * PENIRQ only kicks the timer.  The timer only reissues the SPI transfer,
- * to retrieve touchscreen status.
- *
- * The SPI transfer completion callback does the real work.  It reports
- * touchscreen events and reactivates the timer (or IRQ) as appropriate.
- */
+static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
+{
+       struct ads7846 *ts = ads;
+
+       if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
+               /* Start over collecting consistent readings. */
+               ts->read_rep = 0;
+               /*
+                * Repeat it, if this was the first read or the read
+                * wasn't consistent enough.
+                */
+               if (ts->read_cnt < ts->debounce_max) {
+                       ts->last_read = *val;
+                       ts->read_cnt++;
+                       return ADS7846_FILTER_REPEAT;
+               } else {
+                       /*
+                        * Maximum number of debouncing reached and still
+                        * not enough number of consistent readings. Abort
+                        * the whole sample, repeat it in the next sampling
+                        * period.
+                        */
+                       ts->read_cnt = 0;
+                       return ADS7846_FILTER_IGNORE;
+               }
+       } else {
+               if (++ts->read_rep > ts->debounce_rep) {
+                       /*
+                        * Got a good reading for this coordinate,
+                        * go for the next one.
+                        */
+                       ts->read_cnt = 0;
+                       ts->read_rep = 0;
+                       return ADS7846_FILTER_OK;
+               } else {
+                       /* Read more values that are consistent. */
+                       ts->read_cnt++;
+                       return ADS7846_FILTER_REPEAT;
+               }
+       }
+}
+
+static int ads7846_no_filter(void *ads, int data_idx, int *val)
+{
+       return ADS7846_FILTER_OK;
+}
+
+static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
+{
+       struct spi_transfer *t =
+               list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+       if (ts->model == 7845) {
+               return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+       } else {
+               /*
+                * adjust:  on-wire is a must-ignore bit, a BE12 value, then
+                * padding; built from two 8 bit values written msb-first.
+                */
+               return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+       }
+}
+
+static void ads7846_update_value(struct spi_message *m, int val)
+{
+       struct spi_transfer *t =
+               list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+       *(u16 *)t->rx_buf = val;
+}
+
+static void ads7846_read_state(struct ads7846 *ts)
+{
+       struct ads7846_packet *packet = ts->packet;
+       struct spi_message *m;
+       int msg_idx = 0;
+       int val;
+       int action;
+       int error;
+
+       while (msg_idx < ts->msg_count) {
+
+               ts->wait_for_sync();
+
+               m = &ts->msg[msg_idx];
+               error = spi_sync(ts->spi, m);
+               if (error) {
+                       dev_err(&ts->spi->dev, "spi_async --> %d\n", error);
+                       packet->tc.ignore = true;
+                       return;
+               }
+
+               /*
+                * Last message is power down request, no need to convert
+                * or filter the value.
+                */
+               if (msg_idx < ts->msg_count - 1) {
 
-static void ads7846_rx(void *ads)
+                       val = ads7846_get_value(ts, m);
+
+                       action = ts->filter(ts->filter_data, msg_idx, &val);
+                       switch (action) {
+                       case ADS7846_FILTER_REPEAT:
+                               continue;
+
+                       case ADS7846_FILTER_IGNORE:
+                               packet->tc.ignore = true;
+                               msg_idx = ts->msg_count - 1;
+                               continue;
+
+                       case ADS7846_FILTER_OK:
+                               ads7846_update_value(m, val);
+                               packet->tc.ignore = false;
+                               msg_idx++;
+                               break;
+
+                       default:
+                               BUG();
+                       }
+               } else {
+                       msg_idx++;
+               }
+       }
+}
+
+static void ads7846_report_state(struct ads7846 *ts)
 {
-       struct ads7846          *ts = ads;
-       struct ads7846_packet   *packet = ts->packet;
-       unsigned                Rt;
-       u16                     x, y, z1, z2;
+       struct ads7846_packet *packet = ts->packet;
+       unsigned int Rt;
+       u16 x, y, z1, z2;
 
-       /* ads7846_rx_val() did in-place conversion (including byteswap) from
-        * on-the-wire format as part of debouncing to get stable readings.
+       /*
+        * ads7846_get_value() does in-place conversion (including byte swap)
+        * from on-the-wire format as part of debouncing to get stable
+        * readings.
         */
        if (ts->model == 7845) {
                x = *(u16 *)packet->tc.x_buf;
@@ -623,19 +800,19 @@ static void ads7846_rx(void *ads)
                Rt = 0;
        }
 
-       /* Sample found inconsistent by debouncing or pressure is beyond
+       /*
+        * Sample found inconsistent by debouncing or pressure is beyond
         * the maximum. Don't report it to user space, repeat at least
         * once more the measurement
         */
        if (packet->tc.ignore || Rt > ts->pressure_max) {
                dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n",
                         packet->tc.ignore, Rt);
-               hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-                             HRTIMER_MODE_REL);
                return;
        }
 
-       /* Maybe check the pendown state before reporting. This discards
+       /*
+        * Maybe check the pendown state before reporting. This discards
         * false readings when the pen is lifted.
         */
        if (ts->penirq_recheck_delay_usecs) {
@@ -644,8 +821,9 @@ static void ads7846_rx(void *ads)
                        Rt = 0;
        }
 
-       /* NOTE: We can't rely on the pressure to determine the pen down
-        * state, even this controller has a pressure sensor.  The pressure
+       /*
+        * NOTE: We can't rely on the pressure to determine the pen down
+        * state, even this controller has a pressure sensor. The pressure
         * value can fluctuate for quite a while after lifting the pen and
         * in some cases may not even settle at the expected value.
         *
@@ -655,15 +833,15 @@ static void ads7846_rx(void *ads)
        if (Rt) {
                struct input_dev *input = ts->input;
 
+               if (ts->swap_xy)
+                       swap(x, y);
+
                if (!ts->pendown) {
                        input_report_key(input, BTN_TOUCH, 1);
-                       ts->pendown = 1;
+                       ts->pendown = true;
                        dev_vdbg(&ts->spi->dev, "DOWN\n");
                }
 
-               if (ts->swap_xy)
-                       swap(x, y);
-
                input_report_abs(input, ABS_X, x);
                input_report_abs(input, ABS_Y, y);
                input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
@@ -671,246 +849,94 @@ static void ads7846_rx(void *ads)
                input_sync(input);
                dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
        }
-
-       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-                       HRTIMER_MODE_REL);
-}
-
-static int ads7846_debounce(void *ads, int data_idx, int *val)
-{
-       struct ads7846          *ts = ads;
-
-       if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
-               /* Start over collecting consistent readings. */
-               ts->read_rep = 0;
-               /* Repeat it, if this was the first read or the read
-                * wasn't consistent enough. */
-               if (ts->read_cnt < ts->debounce_max) {
-                       ts->last_read = *val;
-                       ts->read_cnt++;
-                       return ADS7846_FILTER_REPEAT;
-               } else {
-                       /* Maximum number of debouncing reached and still
-                        * not enough number of consistent readings. Abort
-                        * the whole sample, repeat it in the next sampling
-                        * period.
-                        */
-                       ts->read_cnt = 0;
-                       return ADS7846_FILTER_IGNORE;
-               }
-       } else {
-               if (++ts->read_rep > ts->debounce_rep) {
-                       /* Got a good reading for this coordinate,
-                        * go for the next one. */
-                       ts->read_cnt = 0;
-                       ts->read_rep = 0;
-                       return ADS7846_FILTER_OK;
-               } else {
-                       /* Read more values that are consistent. */
-                       ts->read_cnt++;
-                       return ADS7846_FILTER_REPEAT;
-               }
-       }
 }
 
-static int ads7846_no_filter(void *ads, int data_idx, int *val)
+static irqreturn_t ads7846_hard_irq(int irq, void *handle)
 {
-       return ADS7846_FILTER_OK;
-}
-
-static void ads7846_rx_val(void *ads)
-{
-       struct ads7846 *ts = ads;
-       struct ads7846_packet *packet = ts->packet;
-       struct spi_message *m;
-       struct spi_transfer *t;
-       int val;
-       int action;
-       int status;
-
-       m = &ts->msg[ts->msg_idx];
-       t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-
-       if (ts->model == 7845) {
-               val = be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
-       } else {
-               /* adjust:  on-wire is a must-ignore bit, a BE12 value, then
-                * padding; built from two 8 bit values written msb-first.
-                */
-               val = be16_to_cpup((__be16 *)t->rx_buf) >> 3;
-       }
+       struct ads7846 *ts = handle;
 
-       action = ts->filter(ts->filter_data, ts->msg_idx, &val);
-       switch (action) {
-       case ADS7846_FILTER_REPEAT:
-               break;
-       case ADS7846_FILTER_IGNORE:
-               packet->tc.ignore = 1;
-               /* Last message will contain ads7846_rx() as the
-                * completion function.
-                */
-               m = ts->last_msg;
-               break;
-       case ADS7846_FILTER_OK:
-               *(u16 *)t->rx_buf = val;
-               packet->tc.ignore = 0;
-               m = &ts->msg[++ts->msg_idx];
-               break;
-       default:
-               BUG();
-       }
-       ts->wait_for_sync();
-       status = spi_async(ts->spi, m);
-       if (status)
-               dev_err(&ts->spi->dev, "spi_async --> %d\n",
-                               status);
+       return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
 }
 
-static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
-{
-       struct ads7846  *ts = container_of(handle, struct ads7846, timer);
-       int             status = 0;
-
-       spin_lock(&ts->lock);
-
-       if (unlikely(!get_pendown_state(ts) ||
-                    device_suspended(&ts->spi->dev))) {
-               if (ts->pendown) {
-                       struct input_dev *input = ts->input;
-
-                       input_report_key(input, BTN_TOUCH, 0);
-                       input_report_abs(input, ABS_PRESSURE, 0);
-                       input_sync(input);
-
-                       ts->pendown = 0;
-                       dev_vdbg(&ts->spi->dev, "UP\n");
-               }
-
-               /* measurement cycle ended */
-               if (!device_suspended(&ts->spi->dev)) {
-                       ts->irq_disabled = 0;
-                       enable_irq(ts->spi->irq);
-               }
-               ts->pending = 0;
-       } else {
-               /* pen is still down, continue with the measurement */
-               ts->msg_idx = 0;
-               ts->wait_for_sync();
-               status = spi_async(ts->spi, &ts->msg[0]);
-               if (status)
-                       dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
-       }
-
-       spin_unlock(&ts->lock);
-       return HRTIMER_NORESTART;
-}
 
 static irqreturn_t ads7846_irq(int irq, void *handle)
 {
        struct ads7846 *ts = handle;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ts->lock, flags);
-       if (likely(get_pendown_state(ts))) {
-               if (!ts->irq_disabled) {
-                       /* The ARM do_simple_IRQ() dispatcher doesn't act
-                        * like the other dispatchers:  it will report IRQs
-                        * even after they've been disabled.  We work around
-                        * that here.  (The "generic irq" framework may help...)
-                        */
-                       ts->irq_disabled = 1;
-                       disable_irq_nosync(ts->spi->irq);
-                       ts->pending = 1;
-                       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
-                                       HRTIMER_MODE_REL);
-               }
-       }
-       spin_unlock_irqrestore(&ts->lock, flags);
 
-       return IRQ_HANDLED;
-}
+       /* Start with a small delay before checking pendown state */
+       msleep(TS_POLL_DELAY);
 
-/*--------------------------------------------------------------------------*/
+       while (!ts->stopped && get_pendown_state(ts)) {
 
-/* Must be called with ts->lock held */
-static void ads7846_disable(struct ads7846 *ts)
-{
-       if (ts->disabled)
-               return;
+               /* pen is down, continue with the measurement */
+               ads7846_read_state(ts);
 
-       ts->disabled = 1;
+               if (!ts->stopped)
+                       ads7846_report_state(ts);
 
-       /* are we waiting for IRQ, or polling? */
-       if (!ts->pending) {
-               ts->irq_disabled = 1;
-               disable_irq(ts->spi->irq);
-       } else {
-               /* the timer will run at least once more, and
-                * leave everything in a clean state, IRQ disabled
-                */
-               while (ts->pending) {
-                       spin_unlock_irq(&ts->lock);
-                       msleep(1);
-                       spin_lock_irq(&ts->lock);
-               }
+               wait_event_timeout(ts->wait, ts->stopped,
+                                  msecs_to_jiffies(TS_POLL_PERIOD));
        }
 
-       regulator_disable(ts->reg);
-
-       /* we know the chip's in lowpower mode since we always
-        * leave it that way after every request
-        */
-}
+       if (ts->pendown) {
+               struct input_dev *input = ts->input;
 
-/* Must be called with ts->lock held */
-static void ads7846_enable(struct ads7846 *ts)
-{
-       if (!ts->disabled)
-               return;
+               input_report_key(input, BTN_TOUCH, 0);
+               input_report_abs(input, ABS_PRESSURE, 0);
+               input_sync(input);
 
-       regulator_enable(ts->reg);
+               ts->pendown = false;
+               dev_vdbg(&ts->spi->dev, "UP\n");
+       }
 
-       ts->disabled = 0;
-       ts->irq_disabled = 0;
-       enable_irq(ts->spi->irq);
+       return IRQ_HANDLED;
 }
 
 static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
 {
        struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-       spin_lock_irq(&ts->lock);
+       mutex_lock(&ts->lock);
 
-       ts->is_suspended = 1;
-       ads7846_disable(ts);
+       if (!ts->suspended) {
 
-       spin_unlock_irq(&ts->lock);
+               if (!ts->disabled)
+                       __ads7846_disable(ts);
 
-       if (device_may_wakeup(&ts->spi->dev))
-               enable_irq_wake(ts->spi->irq);
+               if (device_may_wakeup(&ts->spi->dev))
+                       enable_irq_wake(ts->spi->irq);
 
-       return 0;
+               ts->suspended = true;
+       }
+
+       mutex_unlock(&ts->lock);
 
+       return 0;
 }
 
 static int ads7846_resume(struct spi_device *spi)
 {
        struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-       if (device_may_wakeup(&ts->spi->dev))
-               disable_irq_wake(ts->spi->irq);
+       mutex_lock(&ts->lock);
+
+       if (ts->suspended) {
 
-       spin_lock_irq(&ts->lock);
+               ts->suspended = false;
 
-       ts->is_suspended = 0;
-       ads7846_enable(ts);
+               if (device_may_wakeup(&ts->spi->dev))
+                       disable_irq_wake(ts->spi->irq);
 
-       spin_unlock_irq(&ts->lock);
+               if (!ts->disabled)
+                       __ads7846_enable(ts);
+       }
+
+       mutex_unlock(&ts->lock);
 
        return 0;
 }
 
-static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -932,146 +958,40 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
        err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
        if (err) {
                dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-                               pdata->gpio_pendown);
+                       pdata->gpio_pendown);
                return err;
        }
 
        ts->gpio_pendown = pdata->gpio_pendown;
+
        return 0;
 }
 
-static int __devinit ads7846_probe(struct spi_device *spi)
+/*
+ * Set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
+static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
+                               const struct ads7846_platform_data *pdata)
 {
-       struct ads7846 *ts;
-       struct ads7846_packet *packet;
-       struct input_dev *input_dev;
-       const struct ads7846_platform_data *pdata = spi->dev.platform_data;
-       struct spi_message *m;
-       struct spi_transfer *x;
-       unsigned long irq_flags;
-       int vref;
-       int err;
-
-       if (!spi->irq) {
-               dev_dbg(&spi->dev, "no IRQ?\n");
-               return -ENODEV;
-       }
-
-       if (!pdata) {
-               dev_dbg(&spi->dev, "no platform data?\n");
-               return -ENODEV;
-       }
-
-       /* don't exceed max specified sample rate */
-       if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
-               dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
-                               (spi->max_speed_hz/SAMPLE_BITS)/1000);
-               return -EINVAL;
-       }
-
-       /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
-        * that even if the hardware can do that, the SPI controller driver
-        * may not.  So we stick to very-portable 8 bit words, both RX and TX.
-        */
-       spi->bits_per_word = 8;
-       spi->mode = SPI_MODE_0;
-       err = spi_setup(spi);
-       if (err < 0)
-               return err;
-
-       ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
-       packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!ts || !packet || !input_dev) {
-               err = -ENOMEM;
-               goto err_free_mem;
-       }
-
-       dev_set_drvdata(&spi->dev, ts);
-
-       ts->packet = packet;
-       ts->spi = spi;
-       ts->input = input_dev;
-       ts->vref_mv = pdata->vref_mv;
-       ts->swap_xy = pdata->swap_xy;
-
-       hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       ts->timer.function = ads7846_timer;
-
-       spin_lock_init(&ts->lock);
-
-       ts->model = pdata->model ? : 7846;
-       ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
-       ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
-       ts->pressure_max = pdata->pressure_max ? : ~0;
-
-       if (pdata->filter != NULL) {
-               if (pdata->filter_init != NULL) {
-                       err = pdata->filter_init(pdata, &ts->filter_data);
-                       if (err < 0)
-                               goto err_free_mem;
-               }
-               ts->filter = pdata->filter;
-               ts->filter_cleanup = pdata->filter_cleanup;
-       } else if (pdata->debounce_max) {
-               ts->debounce_max = pdata->debounce_max;
-               if (ts->debounce_max < 2)
-                       ts->debounce_max = 2;
-               ts->debounce_tol = pdata->debounce_tol;
-               ts->debounce_rep = pdata->debounce_rep;
-               ts->filter = ads7846_debounce;
-               ts->filter_data = ts;
-       } else
-               ts->filter = ads7846_no_filter;
-
-       err = setup_pendown(spi, ts);
-       if (err)
-               goto err_cleanup_filter;
-
-       if (pdata->penirq_recheck_delay_usecs)
-               ts->penirq_recheck_delay_usecs =
-                               pdata->penirq_recheck_delay_usecs;
-
-       ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
-
-       snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
-       snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
-
-       input_dev->name = ts->name;
-       input_dev->phys = ts->phys;
-       input_dev->dev.parent = &spi->dev;
-
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-       input_set_abs_params(input_dev, ABS_X,
-                       pdata->x_min ? : 0,
-                       pdata->x_max ? : MAX_12BIT,
-                       0, 0);
-       input_set_abs_params(input_dev, ABS_Y,
-                       pdata->y_min ? : 0,
-                       pdata->y_max ? : MAX_12BIT,
-                       0, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE,
-                       pdata->pressure_min, pdata->pressure_max, 0, 0);
-
-       vref = pdata->keep_vref_on;
+       struct spi_message *m = &ts->msg[0];
+       struct spi_transfer *x = ts->xfer;
+       struct ads7846_packet *packet = ts->packet;
+       int vref = pdata->keep_vref_on;
 
        if (ts->model == 7873) {
-               /* The AD7873 is almost identical to the ADS7846
+               /*
+                * The AD7873 is almost identical to the ADS7846
                 * keep VREF off during differential/ratiometric
-                * conversion modes
+                * conversion modes.
                 */
                ts->model = 7846;
                vref = 0;
        }
 
-       /* set up the transfers to read touchscreen state; this assumes we
-        * use formula #2 for pressure, not #3.
-        */
-       m = &ts->msg[0];
-       x = ts->xfer;
-
+       ts->msg_count = 1;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                packet->read_y_cmd[0] = READ_Y(vref);
@@ -1094,7 +1014,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       /* the first sample after switching drivers can be low quality;
+       /*
+        * The first sample after switching drivers can be low quality;
         * optionally discard it, using a second one after the signals
         * have had enough time to stabilize.
         */
@@ -1112,11 +1033,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       m->complete = ads7846_rx_val;
-       m->context = ts;
-
+       ts->msg_count++;
        m++;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                x++;
@@ -1156,13 +1076,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       m->complete = ads7846_rx_val;
-       m->context = ts;
-
        /* turn y+ off, x- on; we'll use formula #2 */
        if (ts->model == 7846) {
+               ts->msg_count++;
                m++;
                spi_message_init(m);
+               m->context = ts;
 
                x++;
                packet->read_z1 = READ_Z1(vref);
@@ -1190,11 +1109,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        spi_message_add_tail(x, m);
                }
 
-               m->complete = ads7846_rx_val;
-               m->context = ts;
-
+               ts->msg_count++;
                m++;
                spi_message_init(m);
+               m->context = ts;
 
                x++;
                packet->read_z2 = READ_Z2(vref);
@@ -1221,14 +1139,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        x->len = 2;
                        spi_message_add_tail(x, m);
                }
-
-               m->complete = ads7846_rx_val;
-               m->context = ts;
        }
 
        /* power down */
+       ts->msg_count++;
        m++;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                x++;
@@ -1251,11 +1168,119 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        CS_CHANGE(*x);
        spi_message_add_tail(x, m);
+}
 
-       m->complete = ads7846_rx;
-       m->context = ts;
+static int __devinit ads7846_probe(struct spi_device *spi)
+{
+       struct ads7846 *ts;
+       struct ads7846_packet *packet;
+       struct input_dev *input_dev;
+       struct ads7846_platform_data *pdata = spi->dev.platform_data;
+       unsigned long irq_flags;
+       int err;
+
+       if (!spi->irq) {
+               dev_dbg(&spi->dev, "no IRQ?\n");
+               return -ENODEV;
+       }
+
+       if (!pdata) {
+               dev_dbg(&spi->dev, "no platform data?\n");
+               return -ENODEV;
+       }
+
+       /* don't exceed max specified sample rate */
+       if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
+               dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+                               (spi->max_speed_hz/SAMPLE_BITS)/1000);
+               return -EINVAL;
+       }
+
+       /* We'd set TX word size 8 bits and RX word size to 13 bits ... except
+        * that even if the hardware can do that, the SPI controller driver
+        * may not.  So we stick to very-portable 8 bit words, both RX and TX.
+        */
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_0;
+       err = spi_setup(spi);
+       if (err < 0)
+               return err;
 
-       ts->last_msg = m;
+       ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+       packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!ts || !packet || !input_dev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       dev_set_drvdata(&spi->dev, ts);
+
+       ts->packet = packet;
+       ts->spi = spi;
+       ts->input = input_dev;
+       ts->vref_mv = pdata->vref_mv;
+       ts->swap_xy = pdata->swap_xy;
+
+       mutex_init(&ts->lock);
+       init_waitqueue_head(&ts->wait);
+
+       ts->model = pdata->model ? : 7846;
+       ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
+       ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+       ts->pressure_max = pdata->pressure_max ? : ~0;
+
+       if (pdata->filter != NULL) {
+               if (pdata->filter_init != NULL) {
+                       err = pdata->filter_init(pdata, &ts->filter_data);
+                       if (err < 0)
+                               goto err_free_mem;
+               }
+               ts->filter = pdata->filter;
+               ts->filter_cleanup = pdata->filter_cleanup;
+       } else if (pdata->debounce_max) {
+               ts->debounce_max = pdata->debounce_max;
+               if (ts->debounce_max < 2)
+                       ts->debounce_max = 2;
+               ts->debounce_tol = pdata->debounce_tol;
+               ts->debounce_rep = pdata->debounce_rep;
+               ts->filter = ads7846_debounce_filter;
+               ts->filter_data = ts;
+       } else {
+               ts->filter = ads7846_no_filter;
+       }
+
+       err = ads7846_setup_pendown(spi, ts);
+       if (err)
+               goto err_cleanup_filter;
+
+       if (pdata->penirq_recheck_delay_usecs)
+               ts->penirq_recheck_delay_usecs =
+                               pdata->penirq_recheck_delay_usecs;
+
+       ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
+
+       snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
+       snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
+
+       input_dev->name = ts->name;
+       input_dev->phys = ts->phys;
+       input_dev->dev.parent = &spi->dev;
+
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(input_dev, ABS_X,
+                       pdata->x_min ? : 0,
+                       pdata->x_max ? : MAX_12BIT,
+                       0, 0);
+       input_set_abs_params(input_dev, ABS_Y,
+                       pdata->y_min ? : 0,
+                       pdata->y_max ? : MAX_12BIT,
+                       0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE,
+                       pdata->pressure_min, pdata->pressure_max, 0, 0);
+
+       ads7846_setup_spi_msg(ts, pdata);
 
        ts->reg = regulator_get(&spi->dev, "vcc");
        if (IS_ERR(ts->reg)) {
@@ -1271,16 +1296,17 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        }
 
        irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
+       irq_flags |= IRQF_ONESHOT;
 
-       err = request_irq(spi->irq, ads7846_irq, irq_flags,
-                         spi->dev.driver->name, ts);
-
+       err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq,
+                                  irq_flags, spi->dev.driver->name, ts);
        if (err && !pdata->irq_flags) {
                dev_info(&spi->dev,
                        "trying pin change workaround on irq %d\n", spi->irq);
-               err = request_irq(spi->irq, ads7846_irq,
-                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-                                 spi->dev.driver->name, ts);
+               irq_flags |= IRQF_TRIGGER_RISING;
+               err = request_threaded_irq(spi->irq,
+                                 ads7846_hard_irq, ads7846_irq,
+                                 irq_flags, spi->dev.driver->name, ts);
        }
 
        if (err) {
@@ -1294,7 +1320,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
-       /* take a first sample, leaving nPENIRQ active and vREF off; avoid
+       /*
+        * Take a first sample, leaving nPENIRQ active and vREF off; avoid
         * the touchscreen, in case it's not connected.
         */
        if (ts->model == 7845)
@@ -1340,20 +1367,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
 static int __devexit ads7846_remove(struct spi_device *spi)
 {
-       struct ads7846          *ts = dev_get_drvdata(&spi->dev);
+       struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
        device_init_wakeup(&spi->dev, false);
 
-       ads784x_hwmon_unregister(spi, ts);
-       input_unregister_device(ts->input);
-
-       ads7846_suspend(spi, PMSG_SUSPEND);
-
        sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
 
+       ads7846_disable(ts);
        free_irq(ts->spi->irq, ts);
-       /* suspend left the IRQ disabled */
-       enable_irq(ts->spi->irq);
+
+       input_unregister_device(ts->input);
+
+       ads784x_hwmon_unregister(spi, ts);
 
        regulator_disable(ts->reg);
        regulator_put(ts->reg);
@@ -1368,6 +1393,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
        kfree(ts);
 
        dev_dbg(&spi->dev, "unregistered touchscreen\n");
+
        return 0;
 }
 
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
new file mode 100644 (file)
index 0000000..ccde586
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+#include <linux/input/bu21013.h>
+#include <linux/slab.h>
+
+#define PEN_DOWN_INTR  0
+#define MAX_FINGERS    2
+#define RESET_DELAY    30
+#define PENUP_TIMEOUT  (10)
+#define DELTA_MIN      16
+#define MASK_BITS      0x03
+#define SHIFT_8                8
+#define SHIFT_2                2
+#define LENGTH_OF_BUFFER       11
+#define I2C_RETRY_COUNT        5
+
+#define BU21013_SENSORS_BTN_0_7_REG    0x70
+#define BU21013_SENSORS_BTN_8_15_REG   0x71
+#define BU21013_SENSORS_BTN_16_23_REG  0x72
+#define BU21013_X1_POS_MSB_REG         0x73
+#define BU21013_X1_POS_LSB_REG         0x74
+#define BU21013_Y1_POS_MSB_REG         0x75
+#define BU21013_Y1_POS_LSB_REG         0x76
+#define BU21013_X2_POS_MSB_REG         0x77
+#define BU21013_X2_POS_LSB_REG         0x78
+#define BU21013_Y2_POS_MSB_REG         0x79
+#define BU21013_Y2_POS_LSB_REG         0x7A
+#define BU21013_INT_CLR_REG            0xE8
+#define BU21013_INT_MODE_REG           0xE9
+#define BU21013_GAIN_REG               0xEA
+#define BU21013_OFFSET_MODE_REG                0xEB
+#define BU21013_XY_EDGE_REG            0xEC
+#define BU21013_RESET_REG              0xED
+#define BU21013_CALIB_REG              0xEE
+#define BU21013_DONE_REG               0xEF
+#define BU21013_SENSOR_0_7_REG         0xF0
+#define BU21013_SENSOR_8_15_REG                0xF1
+#define BU21013_SENSOR_16_23_REG       0xF2
+#define BU21013_POS_MODE1_REG          0xF3
+#define BU21013_POS_MODE2_REG          0xF4
+#define BU21013_CLK_MODE_REG           0xF5
+#define BU21013_IDLE_REG               0xFA
+#define BU21013_FILTER_REG             0xFB
+#define BU21013_TH_ON_REG              0xFC
+#define BU21013_TH_OFF_REG             0xFD
+
+
+#define BU21013_RESET_ENABLE           0x01
+
+#define BU21013_SENSORS_EN_0_7         0x3F
+#define BU21013_SENSORS_EN_8_15                0xFC
+#define BU21013_SENSORS_EN_16_23       0x1F
+
+#define BU21013_POS_MODE1_0            0x02
+#define BU21013_POS_MODE1_1            0x04
+#define BU21013_POS_MODE1_2            0x08
+
+#define BU21013_POS_MODE2_ZERO         0x01
+#define BU21013_POS_MODE2_AVG1         0x02
+#define BU21013_POS_MODE2_AVG2         0x04
+#define BU21013_POS_MODE2_EN_XY                0x08
+#define BU21013_POS_MODE2_EN_RAW       0x10
+#define BU21013_POS_MODE2_MULTI                0x80
+
+#define BU21013_CLK_MODE_DIV           0x01
+#define BU21013_CLK_MODE_EXT           0x02
+#define BU21013_CLK_MODE_CALIB         0x80
+
+#define BU21013_IDLET_0                        0x01
+#define BU21013_IDLET_1                        0x02
+#define BU21013_IDLET_2                        0x04
+#define BU21013_IDLET_3                        0x08
+#define BU21013_IDLE_INTERMIT_EN       0x10
+
+#define BU21013_DELTA_0_6      0x7F
+#define BU21013_FILTER_EN      0x80
+
+#define BU21013_INT_MODE_LEVEL 0x00
+#define BU21013_INT_MODE_EDGE  0x01
+
+#define BU21013_GAIN_0         0x01
+#define BU21013_GAIN_1         0x02
+#define BU21013_GAIN_2         0x04
+
+#define BU21013_OFFSET_MODE_DEFAULT    0x00
+#define BU21013_OFFSET_MODE_MOVE       0x01
+#define BU21013_OFFSET_MODE_DISABLE    0x02
+
+#define BU21013_TH_ON_0                0x01
+#define BU21013_TH_ON_1                0x02
+#define BU21013_TH_ON_2                0x04
+#define BU21013_TH_ON_3                0x08
+#define BU21013_TH_ON_4                0x10
+#define BU21013_TH_ON_5                0x20
+#define BU21013_TH_ON_6                0x40
+#define BU21013_TH_ON_7                0x80
+#define BU21013_TH_ON_MAX      0xFF
+
+#define BU21013_TH_OFF_0       0x01
+#define BU21013_TH_OFF_1       0x02
+#define BU21013_TH_OFF_2       0x04
+#define BU21013_TH_OFF_3       0x08
+#define BU21013_TH_OFF_4       0x10
+#define BU21013_TH_OFF_5       0x20
+#define BU21013_TH_OFF_6       0x40
+#define BU21013_TH_OFF_7       0x80
+#define BU21013_TH_OFF_MAX     0xFF
+
+#define BU21013_X_EDGE_0       0x01
+#define BU21013_X_EDGE_1       0x02
+#define BU21013_X_EDGE_2       0x04
+#define BU21013_X_EDGE_3       0x08
+#define BU21013_Y_EDGE_0       0x10
+#define BU21013_Y_EDGE_1       0x20
+#define BU21013_Y_EDGE_2       0x40
+#define BU21013_Y_EDGE_3       0x80
+
+#define BU21013_DONE   0x01
+#define BU21013_NUMBER_OF_X_SENSORS    (6)
+#define BU21013_NUMBER_OF_Y_SENSORS    (11)
+
+#define DRIVER_TP      "bu21013_tp"
+
+/**
+ * struct bu21013_ts_data - touch panel data structure
+ * @client: pointer to the i2c client
+ * @wait: variable to wait_queue_head_t structure
+ * @touch_stopped: touch stop flag
+ * @chip: pointer to the touch panel controller
+ * @in_dev: pointer to the input device structure
+ * @intr_pin: interrupt pin value
+ *
+ * Touch panel device data structure
+ */
+struct bu21013_ts_data {
+       struct i2c_client *client;
+       wait_queue_head_t wait;
+       bool touch_stopped;
+       const struct bu21013_platform_device *chip;
+       struct input_dev *in_dev;
+       unsigned int intr_pin;
+};
+
+/**
+ * bu21013_read_block_data(): read the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ * @buf: byte pointer
+ *
+ * Read the touch co-ordinates using i2c read block into buffer
+ * and returns integer.
+ */
+static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf)
+{
+       int ret, i;
+
+       for (i = 0; i < I2C_RETRY_COUNT; i++) {
+               ret = i2c_smbus_read_i2c_block_data
+                       (data->client, BU21013_SENSORS_BTN_0_7_REG,
+                               LENGTH_OF_BUFFER, buf);
+               if (ret == LENGTH_OF_BUFFER)
+                       return 0;
+       }
+       return -EINVAL;
+}
+
+/**
+ * bu21013_do_touch_report(): Get the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ *
+ * Get the touch co-ordinates from touch sensor registers and writes
+ * into device structure and returns integer.
+ */
+static int bu21013_do_touch_report(struct bu21013_ts_data *data)
+{
+       u8      buf[LENGTH_OF_BUFFER];
+       unsigned int pos_x[2], pos_y[2];
+       bool    has_x_sensors, has_y_sensors;
+       int     finger_down_count = 0;
+       int     i;
+
+       if (data == NULL)
+               return -EINVAL;
+
+       if (bu21013_read_block_data(data, buf) < 0)
+               return -EINVAL;
+
+       has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7);
+       has_y_sensors = hweight32(((buf[1] & BU21013_SENSORS_EN_8_15) |
+               ((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2);
+       if (!has_x_sensors || !has_y_sensors)
+               return 0;
+
+       for (i = 0; i < MAX_FINGERS; i++) {
+               const u8 *p = &buf[4 * i + 3];
+               unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS);
+               unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS);
+               if (x == 0 || y == 0)
+                       continue;
+               pos_x[finger_down_count] = x;
+               pos_y[finger_down_count] = y;
+               finger_down_count++;
+       }
+
+       if (finger_down_count) {
+               if (finger_down_count == 2 &&
+                   (abs(pos_x[0] - pos_x[1]) < DELTA_MIN ||
+                    abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) {
+                       return 0;
+               }
+
+               for (i = 0; i < finger_down_count; i++) {
+                       if (data->chip->x_flip)
+                               pos_x[i] = data->chip->touch_x_max - pos_x[i];
+                       if (data->chip->y_flip)
+                               pos_y[i] = data->chip->touch_y_max - pos_y[i];
+
+                       input_report_abs(data->in_dev,
+                                        ABS_MT_POSITION_X, pos_x[i]);
+                       input_report_abs(data->in_dev,
+                                        ABS_MT_POSITION_Y, pos_y[i]);
+                       input_mt_sync(data->in_dev);
+               }
+       } else
+               input_mt_sync(data->in_dev);
+
+       input_sync(data->in_dev);
+
+       return 0;
+}
+/**
+ * bu21013_gpio_irq() - gpio thread function for touch interrupt
+ * @irq: irq value
+ * @device_data: void pointer
+ *
+ * This gpio thread function for touch interrupt
+ * and returns irqreturn_t.
+ */
+static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
+{
+       struct bu21013_ts_data *data = device_data;
+       struct i2c_client *i2c = data->client;
+       int retval;
+
+       do {
+               retval = bu21013_do_touch_report(data);
+               if (retval < 0) {
+                       dev_err(&i2c->dev, "bu21013_do_touch_report failed\n");
+                       return IRQ_NONE;
+               }
+
+               data->intr_pin = data->chip->irq_read_val();
+               if (data->intr_pin == PEN_DOWN_INTR)
+                       wait_event_timeout(data->wait, data->touch_stopped,
+                                          msecs_to_jiffies(2));
+       } while (!data->intr_pin && !data->touch_stopped);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * bu21013_init_chip() - power on sequence for the bu21013 controller
+ * @data: device structure pointer
+ *
+ * This function is used to power on
+ * the bu21013 controller and returns integer.
+ */
+static int bu21013_init_chip(struct bu21013_ts_data *data)
+{
+       int retval;
+       struct i2c_client *i2c = data->client;
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET_REG,
+                                       BU21013_RESET_ENABLE);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_RESET reg write failed\n");
+               return retval;
+       }
+       msleep(RESET_DELAY);
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG,
+                                       BU21013_SENSORS_EN_0_7);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG,
+                                               BU21013_SENSORS_EN_8_15);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG,
+                                               BU21013_SENSORS_EN_16_23);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG,
+                               (BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG,
+                       (BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 |
+                       BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW |
+                       BU21013_POS_MODE2_MULTI));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n");
+               return retval;
+       }
+
+       if (data->chip->ext_clk)
+               retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+                       (BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB));
+       else
+               retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+                       (BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG,
+                               (BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG,
+                                               BU21013_INT_MODE_LEVEL);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG,
+                                               (BU21013_DELTA_0_6 |
+                                                       BU21013_FILTER_EN));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG,
+                                       BU21013_TH_ON_5);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
+                               BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG,
+                                       (BU21013_GAIN_0 | BU21013_GAIN_1));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG,
+                                       BU21013_OFFSET_MODE_DEFAULT);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG,
+                               (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 |
+                               BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG,
+                                                       BU21013_DONE);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n");
+               return retval;
+       }
+
+       return 0;
+}
+
+/**
+ * bu21013_free_irq() - frees IRQ registered for touchscreen
+ * @bu21013_data: device structure pointer
+ *
+ * This function signals interrupt thread to stop processing and
+ * frees interrupt.
+ */
+static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
+{
+       bu21013_data->touch_stopped = true;
+       wake_up(&bu21013_data->wait);
+       free_irq(bu21013_data->chip->irq, bu21013_data);
+}
+
+/**
+ * bu21013_probe() - initializes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ * @id: i2c device id pointer
+ *
+ * This function used to initializes the i2c-client touchscreen
+ * driver and returns integer.
+ */
+static int __devinit bu21013_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct bu21013_ts_data *bu21013_data;
+       struct input_dev *in_dev;
+       const struct bu21013_platform_device *pdata =
+                                       client->dev.platform_data;
+       int error;
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "i2c smbus byte data not supported\n");
+               return -EIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "platform data not defined\n");
+               return -EINVAL;
+       }
+
+       bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
+       in_dev = input_allocate_device();
+       if (!bu21013_data || !in_dev) {
+               dev_err(&client->dev, "device memory alloc failed\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       bu21013_data->in_dev = in_dev;
+       bu21013_data->chip = pdata;
+       bu21013_data->client = client;
+       bu21013_data->touch_stopped = false;
+       init_waitqueue_head(&bu21013_data->wait);
+
+       /* configure the gpio pins */
+       if (pdata->cs_en) {
+               error = pdata->cs_en(pdata->cs_pin);
+               if (error < 0) {
+                       dev_err(&client->dev, "chip init failed\n");
+                       goto err_free_mem;
+               }
+       }
+
+       /* configure the touch panel controller */
+       error = bu21013_init_chip(bu21013_data);
+       if (error) {
+               dev_err(&client->dev, "error in bu21013 config\n");
+               goto err_cs_disable;
+       }
+
+       /* register the device to input subsystem */
+       in_dev->name = DRIVER_TP;
+       in_dev->id.bustype = BUS_I2C;
+       in_dev->dev.parent = &client->dev;
+
+       __set_bit(EV_SYN, in_dev->evbit);
+       __set_bit(EV_KEY, in_dev->evbit);
+       __set_bit(EV_ABS, in_dev->evbit);
+
+       input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0,
+                                               pdata->x_max_res, 0, 0);
+       input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0,
+                                               pdata->y_max_res, 0, 0);
+       input_set_drvdata(in_dev, bu21013_data);
+
+       error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
+                                    IRQF_TRIGGER_FALLING | IRQF_SHARED,
+                                    DRIVER_TP, bu21013_data);
+       if (error) {
+               dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
+               goto err_cs_disable;
+       }
+
+       error = input_register_device(in_dev);
+       if (error) {
+               dev_err(&client->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+       device_init_wakeup(&client->dev, pdata->wakeup);
+       i2c_set_clientdata(client, bu21013_data);
+
+       return 0;
+
+err_free_irq:
+       bu21013_free_irq(bu21013_data);
+err_cs_disable:
+       pdata->cs_dis(pdata->cs_pin);
+err_free_mem:
+       input_free_device(bu21013_data->in_dev);
+       kfree(bu21013_data);
+
+       return error;
+}
+/**
+ * bu21013_remove() - removes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ *
+ * This function uses to remove the i2c-client
+ * touchscreen driver and returns integer.
+ */
+static int __devexit bu21013_remove(struct i2c_client *client)
+{
+       struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
+
+       bu21013_free_irq(bu21013_data);
+
+       bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
+
+       input_unregister_device(bu21013_data->in_dev);
+       kfree(bu21013_data);
+
+       device_init_wakeup(&client->dev, false);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ * bu21013_suspend() - suspend the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to suspend the
+ * touch panel controller and returns integer
+ */
+static int bu21013_suspend(struct device *dev)
+{
+       struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+       struct i2c_client *client = bu21013_data->client;
+
+       bu21013_data->touch_stopped = true;
+       if (device_may_wakeup(&client->dev))
+               enable_irq_wake(bu21013_data->chip->irq);
+       else
+               disable_irq(bu21013_data->chip->irq);
+
+       return 0;
+}
+
+/**
+ * bu21013_resume() - resume the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to resume the touch panel
+ * controller and returns integer.
+ */
+static int bu21013_resume(struct device *dev)
+{
+       struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+       struct i2c_client *client = bu21013_data->client;
+       int retval;
+
+       retval = bu21013_init_chip(bu21013_data);
+       if (retval < 0) {
+               dev_err(&client->dev, "bu21013 controller config failed\n");
+               return retval;
+       }
+
+       bu21013_data->touch_stopped = false;
+
+       if (device_may_wakeup(&client->dev))
+               disable_irq_wake(bu21013_data->chip->irq);
+       else
+               enable_irq(bu21013_data->chip->irq);
+
+       return 0;
+}
+
+static const struct dev_pm_ops bu21013_dev_pm_ops = {
+       .suspend = bu21013_suspend,
+       .resume  = bu21013_resume,
+};
+#endif
+
+static const struct i2c_device_id bu21013_id[] = {
+       { DRIVER_TP, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, bu21013_id);
+
+static struct i2c_driver bu21013_driver = {
+       .driver = {
+               .name   =       DRIVER_TP,
+               .owner  =       THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     =       &bu21013_dev_pm_ops,
+#endif
+       },
+       .probe          =       bu21013_probe,
+       .remove         =       __devexit_p(bu21013_remove),
+       .id_table       =       bu21013_id,
+};
+
+/**
+ * bu21013_init() - initializes the bu21013 touchscreen driver
+ *
+ * This function used to initializes the bu21013
+ * touchscreen driver and returns integer.
+ */
+static int __init bu21013_init(void)
+{
+       return i2c_add_driver(&bu21013_driver);
+}
+
+/**
+ * bu21013_exit() - de-initializes the bu21013 touchscreen driver
+ *
+ * This function uses to de-initializes the bu21013
+ * touchscreen driver and returns none.
+ */
+static void __exit bu21013_exit(void)
+{
+       i2c_del_driver(&bu21013_driver);
+}
+
+module_init(bu21013_init);
+module_exit(bu21013_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
+MODULE_DESCRIPTION("bu21013 touch screen controller driver");
index 5ec0946..d0c3a72 100644 (file)
@@ -206,9 +206,9 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
        input_set_abs_params(input_dev, ABS_X,
-                       CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 0, 0);
+                       CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
        input_set_abs_params(input_dev, ABS_Y,
-                       CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0);
+                       CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
 
        if (ts->reset_pin) {
                err = gpio_request(ts->reset_pin, NULL);
index a89700e..498bd62 100644 (file)
@@ -107,8 +107,7 @@ static int __init hp680_ts_init(void)
        return 0;
 
  fail2:        free_irq(HP680_TS_IRQ, NULL);
-       cancel_delayed_work(&work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&work);
  fail1:        input_free_device(hp680_ts_dev);
        return err;
 }
@@ -116,8 +115,7 @@ static int __init hp680_ts_init(void)
 static void __exit hp680_ts_exit(void)
 {
        free_irq(HP680_TS_IRQ, NULL);
-       cancel_delayed_work(&work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&work);
        input_unregister_device(hp680_ts_dev);
 }
 
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
new file mode 100644 (file)
index 0000000..c0307b2
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
+ * General Public License for more details.
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ *                         Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ *     review conversion of r/m/w sequences
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1           0x00 /* PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT           0x04 /* PMIC interrupt register */
+#define PMIC_REG_MINT          0x05 /* PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT                0x5F /* ADC interrupt register */
+#define PMIC_REG_MADCINT       0x60 /* ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1      0x61 /* ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0              0xA4
+#define END_OF_CHANNEL         0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H      0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10         0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11         0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12         0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13         0xD /* Touch screen Y- connection */
+
+/* Touch screen channel BIAS constants */
+#define MRST_XBIAS             0x20
+#define MRST_YBIAS             0x40
+#define MRST_ZBIAS             0x80
+
+/* Touch screen coordinates */
+#define MRST_X_MIN             10
+#define MRST_X_MAX             1024
+#define MRST_X_FUZZ            5
+#define MRST_Y_MIN             10
+#define MRST_Y_MAX             1024
+#define MRST_Y_FUZZ            5
+#define MRST_PRESSURE_MIN      0
+#define MRST_PRESSURE_NOMINAL  50
+#define MRST_PRESSURE_MAX      100
+
+#define WAIT_ADC_COMPLETION    10 /* msec */
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0                0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1                0x1 /* 4.5  ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS         0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM      1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC                2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS  32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+       struct device *dev; /* device associated with touch screen */
+       struct input_dev *input;
+       char phys[32];
+       u16 asr;                /* Address selection register */
+       int irq;
+       unsigned int vendor;    /* PMIC vendor */
+       unsigned int rev;       /* PMIC revision */
+
+       int (*read_prepare)(struct mrstouch_dev *tsdev);
+       int (*read)(struct mrstouch_dev *tsdev, u16 *x, u16 *y, u16 *z);
+       int (*read_finish)(struct mrstouch_dev *tsdev);
+};
+
+
+/*************************** NEC and Maxim Interface ************************/
+
+static int mrstouch_nec_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+       return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0, 0x20);
+}
+
+/*
+ * Enables PENDET interrupt.
+ */
+static int mrstouch_nec_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+       int err;
+
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x20, 0x20);
+       if (!err)
+               err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, 0, 0x05);
+
+       return err;
+}
+
+/*
+ * Reads PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits and
+ * converts the two readings into a single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+       int err;
+       u16 result;
+       u32 res;
+
+       result = PMIC_REG_ADCSNS0H + offset;
+
+       if (chan == MRST_TS_CHAN12)
+               result += 4;
+
+       err = intel_scu_ipc_ioread32(result, &res);
+       if (err)
+               return err;
+
+       /* Mash the bits up */
+
+       *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vp &= 0x3FF;
+
+       res >>= 16;
+
+       *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vm &= 0x3FF;
+
+       return 0;
+}
+
+/*
+ * Enables X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+       int count;
+       u16 chan, start;
+       u16 reg[4];
+       u8 data[4];
+
+       chan = PMICADDR0 + offset;
+       start = MRST_TS_CHAN10;
+
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = bias | (start + count);
+       }
+
+       return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_nec_adc_read(struct mrstouch_dev *tsdev,
+                                u16 *x, u16 *y, u16 *z)
+{
+       int err;
+       u16 xm, ym, zm;
+
+       /* configure Y bias for X channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_YBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read x+ and x- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, x, &xm);
+       if (err)
+               goto ipc_error;
+
+       /* configure x bias for y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_XBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read y+ and y- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, y, &ym);
+       if (err)
+               goto ipc_error;
+
+       /* configure z bias for x and y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_ZBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read z+ and z- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, z, &zm);
+       if (err)
+               goto ipc_error;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during adc read\n");
+       return err;
+}
+
+
+/*************************** Freescale Interface ************************/
+
+static int mrstouch_fs_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+       int err, count;
+       u16 chan;
+       u16 reg[5];
+       u8 data[5];
+
+       /* Stop the ADC */
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+       if (err)
+               goto ipc_error;
+
+       chan = PMICADDR0 + tsdev->asr;
+
+       /* Set X BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x2A;
+       }
+       reg[count] =  chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Y BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x4A;
+       }
+       reg[count] = chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Z BIAS */
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static int mrstouch_fs_adc_read(struct mrstouch_dev *tsdev,
+                               u16 *x, u16 *y, u16 *z)
+{
+       int err;
+       u16 result;
+       u16 reg[4];
+       u8 data[4];
+
+       result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+       reg[0] = result + 4;
+       reg[1] = result + 5;
+       reg[2] = result + 16;
+       reg[3] = result + 17;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       *x = data[0] << 3; /* Higher 7 bits */
+       *x |= data[1] & 0x7; /* Lower 3 bits */
+       *x &= 0x3FF;
+
+       *y = data[2] << 3; /* Higher 7 bits */
+       *y |= data[3] & 0x7; /* Lower 3 bits */
+       *y &= 0x3FF;
+
+       /* Read Z value */
+       reg[0] = result + 28;
+       reg[1] = result + 29;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       *z = data[0] << 3; /* Higher 7 bits */
+       *z |= data[1] & 0x7; /* Lower 3 bits */
+       *z &= 0x3FF;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static int mrstouch_fs_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+       int err, count;
+       u16 chan;
+       u16 reg[5];
+       u8 data[5];
+
+       /* Clear all TS channels */
+       chan = PMICADDR0 + tsdev->asr;
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+       if (err)
+               goto ipc_error;
+
+       /* Start ADC */
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+       if (err)
+               goto ipc_error;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static void mrstouch_report_event(struct input_dev *input,
+                       unsigned int x, unsigned int y, unsigned int z)
+{
+       if (z > MRST_PRESSURE_NOMINAL) {
+               /* Pen touched, report button touch and coordinates */
+               input_report_key(input, BTN_TOUCH, 1);
+               input_report_abs(input, ABS_X, x);
+               input_report_abs(input, ABS_Y, y);
+       } else {
+               input_report_key(input, BTN_TOUCH, 0);
+       }
+
+       input_report_abs(input, ABS_PRESSURE, z);
+       input_sync(input);
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t mrstouch_pendet_irq(int irq, void *dev_id)
+{
+       struct mrstouch_dev *tsdev = dev_id;
+       u16 x, y, z;
+
+       /*
+        * Should we lower thread priority? Probably not, since we are
+        * not spinning but sleeping...
+        */
+
+       if (tsdev->read_prepare(tsdev))
+               goto out;
+
+       do {
+               if (tsdev->read(tsdev, &x, &y, &z))
+                       break;
+
+               mrstouch_report_event(tsdev->input, x, y, z);
+       } while (z > MRST_PRESSURE_NOMINAL);
+
+       tsdev->read_finish(tsdev);
+
+out:
+       return IRQ_HANDLED;
+}
+
+/* Utility to read PMIC ID */
+static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
+{
+       int err;
+       u8 r;
+
+       err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+       if (err)
+               return err;
+
+       *vendor = r & 0x7;
+       *rev = (r >> 3) & 0x7;
+
+       return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+       int err, i, found;
+       u8 r8;
+
+       found = -1;
+
+       for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+               if (found >= 0)
+                       break;
+
+               err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
+               if (err)
+                       return err;
+
+               if (r8 == END_OF_CHANNEL) {
+                       found = i;
+                       break;
+               }
+       }
+       if (found < 0)
+               return 0;
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+                       return -ENOSPC;
+       } else {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+                       return -ENOSPC;
+       }
+       return found;
+}
+
+
+/*
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int __devinit mrstouch_ts_chan_set(uint offset)
+{
+       u16 chan;
+
+       int ret, count;
+
+       chan = PMICADDR0 + offset;
+       for (count = 0; count <= 3; count++) {
+               ret = intel_scu_ipc_iowrite8(chan++, MRST_TS_CHAN10 + count);
+               if (ret)
+                       return ret;
+       }
+       return intel_scu_ipc_iowrite8(chan++, END_OF_CHANNEL);
+}
+
+/* Initialize ADC */
+static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+       int err, start;
+       u8 ra, rm;
+
+       err = mrstouch_read_pmic_id(&tsdev->vendor, &tsdev->rev);
+       if (err) {
+               dev_err(tsdev->dev, "Unable to read PMIC id\n");
+               return err;
+       }
+
+       switch (tsdev->vendor) {
+       case PMIC_VENDOR_NEC:
+       case PMIC_VENDOR_MAXIM:
+               tsdev->read_prepare = mrstouch_nec_adc_read_prepare;
+               tsdev->read = mrstouch_nec_adc_read;
+               tsdev->read_finish = mrstouch_nec_adc_read_finish;
+               break;
+
+       case PMIC_VENDOR_FS:
+               tsdev->read_prepare = mrstouch_fs_adc_read_prepare;
+               tsdev->read = mrstouch_fs_adc_read;
+               tsdev->read_finish = mrstouch_fs_adc_read_finish;
+               break;
+
+       default:
+               dev_err(tsdev->dev,
+                       "Unsupported touchscreen: %d\n", tsdev->vendor);
+               return -ENXIO;
+       }
+
+       start = mrstouch_chan_parse(tsdev);
+       if (start < 0) {
+               dev_err(tsdev->dev, "Unable to parse channels\n");
+               return start;
+       }
+
+       tsdev->asr = start;
+
+       /*
+        * ADC power on, start, enable PENDET and set loop delay
+        * ADC loop delay is set to 4.5 ms approximately
+        * Loop delay more than this results in jitter in adc readings
+        * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+        * interrupt generation sometimes.
+        */
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               ra = 0xE0 | ADC_LOOP_DELAY0;
+               rm = 0x5;
+       } else {
+               /* NEC and MAXIm not consistent with loop delay 0 */
+               ra = 0xE0 | ADC_LOOP_DELAY1;
+               rm = 0x0;
+
+               /* configure touch screen channels */
+               err = mrstouch_ts_chan_set(tsdev->asr);
+               if (err)
+                       return err;
+       }
+
+       err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+       if (err)
+               return err;
+
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct platform_device *pdev)
+{
+       struct mrstouch_dev *tsdev;
+       struct input_dev *input;
+       int err;
+       int irq;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no interrupt assigned\n");
+               return -EINVAL;
+       }
+
+       tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!tsdev || !input) {
+               dev_err(&pdev->dev, "unable to allocate memory\n");
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       tsdev->dev = &pdev->dev;
+       tsdev->input = input;
+       tsdev->irq = irq;
+
+       snprintf(tsdev->phys, sizeof(tsdev->phys),
+                "%s/input0", dev_name(tsdev->dev));
+
+       err = mrstouch_adc_init(tsdev);
+       if (err) {
+               dev_err(&pdev->dev, "ADC initialization failed\n");
+               goto err_free_mem;
+       }
+
+       input->name = "mrst_touchscreen";
+       input->phys = tsdev->phys;
+       input->dev.parent = tsdev->dev;
+
+       input->id.vendor = tsdev->vendor;
+       input->id.version = tsdev->rev;
+
+       input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(tsdev->input, ABS_X,
+                            MRST_X_MIN, MRST_X_MAX, MRST_X_FUZZ, 0);
+       input_set_abs_params(tsdev->input, ABS_Y,
+                            MRST_Y_MIN, MRST_Y_MAX, MRST_Y_FUZZ, 0);
+       input_set_abs_params(tsdev->input, ABS_PRESSURE,
+                            MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0);
+
+       err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq,
+                                  0, "mrstouch", tsdev);
+       if (err) {
+               dev_err(tsdev->dev, "unable to allocate irq\n");
+               goto err_free_mem;
+       }
+
+       err = input_register_device(tsdev->input);
+       if (err) {
+               dev_err(tsdev->dev, "unable to register input device\n");
+               goto err_free_irq;
+       }
+
+       platform_set_drvdata(pdev, tsdev);
+       return 0;
+
+err_free_irq:
+       free_irq(tsdev->irq, tsdev);
+err_free_mem:
+       input_free_device(input);
+       kfree(tsdev);
+       return err;
+}
+
+static int __devexit mrstouch_remove(struct platform_device *pdev)
+{
+       struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
+
+       free_irq(tsdev->irq, tsdev);
+       input_unregister_device(tsdev->input);
+       kfree(tsdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver mrstouch_driver = {
+       .driver = {
+               .name   = "pmic_touch",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = mrstouch_probe,
+       .remove         = __devexit_p(mrstouch_remove),
+};
+
+static int __init mrstouch_init(void)
+{
+       return platform_driver_register(&mrstouch_driver);
+}
+module_init(mrstouch_init);
+
+static void __exit mrstouch_exit(void)
+{
+       platform_driver_unregister(&mrstouch_driver);
+}
+module_exit(mrstouch_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
new file mode 100644 (file)
index 0000000..dcf803f
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * LPC32xx built-in touchscreen driver
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * Touchscreen controller register offsets
+ */
+#define LPC32XX_TSC_STAT                       0x00
+#define LPC32XX_TSC_SEL                                0x04
+#define LPC32XX_TSC_CON                                0x08
+#define LPC32XX_TSC_FIFO                       0x0C
+#define LPC32XX_TSC_DTR                                0x10
+#define LPC32XX_TSC_RTR                                0x14
+#define LPC32XX_TSC_UTR                                0x18
+#define LPC32XX_TSC_TTR                                0x1C
+#define LPC32XX_TSC_DXP                                0x20
+#define LPC32XX_TSC_MIN_X                      0x24
+#define LPC32XX_TSC_MAX_X                      0x28
+#define LPC32XX_TSC_MIN_Y                      0x2C
+#define LPC32XX_TSC_MAX_Y                      0x30
+#define LPC32XX_TSC_AUX_UTR                    0x34
+#define LPC32XX_TSC_AUX_MIN                    0x38
+#define LPC32XX_TSC_AUX_MAX                    0x3C
+
+#define LPC32XX_TSC_STAT_FIFO_OVRRN            (1 << 8)
+#define LPC32XX_TSC_STAT_FIFO_EMPTY            (1 << 7)
+
+#define LPC32XX_TSC_SEL_DEFVAL                 0x0284
+
+#define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4       (0x1 << 11)
+#define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s)    ((10 - (s)) << 7)
+#define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s)    ((10 - (s)) << 4)
+#define LPC32XX_TSC_ADCCON_POWER_UP            (1 << 2)
+#define LPC32XX_TSC_ADCCON_AUTO_EN             (1 << 0)
+
+#define LPC32XX_TSC_FIFO_TS_P_LEVEL            (1 << 31)
+#define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x)    (((x) & 0x03FF0000) >> 16)
+#define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y)    ((y) & 0x000003FF)
+
+#define LPC32XX_TSC_ADCDAT_VALUE_MASK          0x000003FF
+
+#define LPC32XX_TSC_MIN_XY_VAL                 0x0
+#define LPC32XX_TSC_MAX_XY_VAL                 0x3FF
+
+#define MOD_NAME "ts-lpc32xx"
+
+#define tsc_readl(dev, reg) \
+       __raw_readl((dev)->tsc_base + (reg))
+#define tsc_writel(dev, reg, val) \
+       __raw_writel((val), (dev)->tsc_base + (reg))
+
+struct lpc32xx_tsc {
+       struct input_dev *dev;
+       void __iomem *tsc_base;
+       int irq;
+       struct clk *clk;
+};
+
+static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc)
+{
+       while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+                       LPC32XX_TSC_STAT_FIFO_EMPTY))
+               tsc_readl(tsc, LPC32XX_TSC_FIFO);
+}
+
+static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id)
+{
+       u32 tmp, rv[4], xs[4], ys[4];
+       int idx;
+       struct lpc32xx_tsc *tsc = dev_id;
+       struct input_dev *input = tsc->dev;
+
+       tmp = tsc_readl(tsc, LPC32XX_TSC_STAT);
+
+       if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) {
+               /* FIFO overflow - throw away samples */
+               lpc32xx_fifo_clear(tsc);
+               return IRQ_HANDLED;
+       }
+
+       /*
+        * Gather and normalize 4 samples. Pen-up events may have less
+        * than 4 samples, but its ok to pop 4 and let the last sample
+        * pen status check drop the samples.
+        */
+       idx = 0;
+       while (idx < 4 &&
+              !(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+                       LPC32XX_TSC_STAT_FIFO_EMPTY)) {
+               tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO);
+               xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+                       LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp);
+               ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+                       LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp);
+               rv[idx] = tmp;
+               idx++;
+       }
+
+       /* Data is only valid if pen is still down in last sample */
+       if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) {
+               /* Use average of 2nd and 3rd sample for position */
+               input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2);
+               input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2);
+               input_report_key(input, BTN_TOUCH, 1);
+       } else {
+               input_report_key(input, BTN_TOUCH, 0);
+       }
+
+       input_sync(input);
+
+       return IRQ_HANDLED;
+}
+
+static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
+{
+       /* Disable auto mode */
+       tsc_writel(tsc, LPC32XX_TSC_CON,
+                  tsc_readl(tsc, LPC32XX_TSC_CON) &
+                            ~LPC32XX_TSC_ADCCON_AUTO_EN);
+
+       clk_disable(tsc->clk);
+}
+
+static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
+{
+       u32 tmp;
+
+       clk_enable(tsc->clk);
+
+       tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
+
+       /* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */
+       tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 |
+             LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) |
+             LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10);
+       tsc_writel(tsc, LPC32XX_TSC_CON, tmp);
+
+       /* These values are all preset */
+       tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL);
+       tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL);
+
+       /* Aux support is not used */
+       tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0);
+       tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0);
+       tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0);
+
+       /*
+        * Set sample rate to about 240Hz per X/Y pair. A single measurement
+        * consists of 4 pairs which gives about a 60Hz sample rate based on
+        * a stable 32768Hz clock source. Values are in clocks.
+        * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4
+        */
+       tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2);
+       tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2);
+       tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10);
+       tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4);
+       tsc_writel(tsc, LPC32XX_TSC_UTR, 88);
+
+       lpc32xx_fifo_clear(tsc);
+
+       /* Enable automatic ts event capture */
+       tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN);
+}
+
+static int lpc32xx_ts_open(struct input_dev *dev)
+{
+       struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+       lpc32xx_setup_tsc(tsc);
+
+       return 0;
+}
+
+static void lpc32xx_ts_close(struct input_dev *dev)
+{
+       struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+       lpc32xx_stop_tsc(tsc);
+}
+
+static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
+{
+       struct lpc32xx_tsc *tsc;
+       struct input_dev *input;
+       struct resource *res;
+       resource_size_t size;
+       int irq;
+       int error;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Can't get memory resource\n");
+               return -ENOENT;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "Can't get interrupt resource\n");
+               return irq;
+       }
+
+       tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!tsc || !input) {
+               dev_err(&pdev->dev, "failed allocating memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       tsc->dev = input;
+       tsc->irq = irq;
+
+       size = resource_size(res);
+
+       if (!request_mem_region(res->start, size, pdev->name)) {
+               dev_err(&pdev->dev, "TSC registers are not free\n");
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       tsc->tsc_base = ioremap(res->start, size);
+       if (!tsc->tsc_base) {
+               dev_err(&pdev->dev, "Can't map memory\n");
+               error = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       tsc->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(tsc->clk)) {
+               dev_err(&pdev->dev, "failed getting clock\n");
+               error = PTR_ERR(tsc->clk);
+               goto err_unmap;
+       }
+
+       input->name = MOD_NAME;
+       input->phys = "lpc32xx/input0";
+       input->id.bustype = BUS_HOST;
+       input->id.vendor = 0x0001;
+       input->id.product = 0x0002;
+       input->id.version = 0x0100;
+       input->dev.parent = &pdev->dev;
+       input->open = lpc32xx_ts_open;
+       input->close = lpc32xx_ts_close;
+
+       input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(input, ABS_X, LPC32XX_TSC_MIN_XY_VAL,
+                            LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+       input_set_abs_params(input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL,
+                            LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+
+       input_set_drvdata(input, tsc);
+
+       error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
+                           IRQF_DISABLED, pdev->name, tsc);
+       if (error) {
+               dev_err(&pdev->dev, "failed requesting interrupt\n");
+               goto err_put_clock;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev, "failed registering input device\n");
+               goto err_free_irq;
+       }
+
+       platform_set_drvdata(pdev, tsc);
+       device_init_wakeup(&pdev->dev, 1);
+
+       return 0;
+
+err_free_irq:
+       free_irq(tsc->irq, tsc);
+err_put_clock:
+       clk_put(tsc->clk);
+err_unmap:
+       iounmap(tsc->tsc_base);
+err_release_mem:
+       release_mem_region(res->start, size);
+err_free_mem:
+       input_free_device(input);
+       kfree(tsc);
+
+       return error;
+}
+
+static int __devexit lpc32xx_ts_remove(struct platform_device *pdev)
+{
+       struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       device_init_wakeup(&pdev->dev, 0);
+       free_irq(tsc->irq, tsc);
+
+       input_unregister_device(tsc->dev);
+
+       clk_put(tsc->clk);
+
+       iounmap(tsc->tsc_base);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(tsc);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_ts_suspend(struct device *dev)
+{
+       struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+       struct input_dev *input = tsc->dev;
+
+       /*
+        * Suspend and resume can be called when the device hasn't been
+        * enabled. If there are no users that have the device open, then
+        * avoid calling the TSC stop and start functions as the TSC
+        * isn't yet clocked.
+        */
+       mutex_lock(&input->mutex);
+
+       if (input->users) {
+               if (device_may_wakeup(dev))
+                       enable_irq_wake(tsc->irq);
+               else
+                       lpc32xx_stop_tsc(tsc);
+       }
+
+       mutex_unlock(&input->mutex);
+
+       return 0;
+}
+
+static int lpc32xx_ts_resume(struct device *dev)
+{
+       struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+       struct input_dev *input = tsc->dev;
+
+       mutex_lock(&input->mutex);
+
+       if (input->users) {
+               if (device_may_wakeup(dev))
+                       disable_irq_wake(tsc->irq);
+               else
+                       lpc32xx_setup_tsc(tsc);
+       }
+
+       mutex_unlock(&input->mutex);
+
+       return 0;
+}
+
+static const struct dev_pm_ops lpc32xx_ts_pm_ops = {
+       .suspend        = lpc32xx_ts_suspend,
+       .resume         = lpc32xx_ts_resume,
+};
+#define LPC32XX_TS_PM_OPS (&lpc32xx_ts_pm_ops)
+#else
+#define LPC32XX_TS_PM_OPS NULL
+#endif
+
+static struct platform_driver lpc32xx_ts_driver = {
+       .probe          = lpc32xx_ts_probe,
+       .remove         = __devexit_p(lpc32xx_ts_remove),
+       .driver         = {
+               .name   = MOD_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = LPC32XX_TS_PM_OPS,
+       },
+};
+
+static int __init lpc32xx_ts_init(void)
+{
+       return platform_driver_register(&lpc32xx_ts_driver);
+}
+module_init(lpc32xx_ts_init);
+
+static void __exit lpc32xx_ts_exit(void)
+{
+       platform_driver_unregister(&lpc32xx_ts_driver);
+}
+module_exit(lpc32xx_ts_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com");
+MODULE_DESCRIPTION("LPC32XX TSC Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lpc32xx_ts");
index 6085d12..8feb7f3 100644 (file)
@@ -350,7 +350,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
  err_tcirq:
        free_irq(ts.irq_tc, ts.input);
  err_inputdev:
-       input_unregister_device(ts.input);
+       input_free_device(ts.input);
  err_iomap:
        iounmap(ts.io);
  err_clk:
index 656148e..ae88e13 100644 (file)
@@ -268,7 +268,7 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
        struct stmpe_touch *ts;
        struct input_dev *idev;
        struct stmpe_ts_platform_data *ts_pdata = NULL;
-       int ret = 0;
+       int ret;
        int ts_irq;
 
        ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
@@ -276,12 +276,16 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
                return ts_irq;
 
        ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-       if (!ts)
+       if (!ts) {
+               ret = -ENOMEM;
                goto err_out;
+       }
 
        idev = input_allocate_device();
-       if (!idev)
+       if (!idev) {
+               ret = -ENOMEM;
                goto err_free_ts;
+       }
 
        platform_set_drvdata(pdev, ts);
        ts->stmpe = stmpe;
@@ -361,7 +365,6 @@ static int __devexit stmpe_ts_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        input_unregister_device(ts->idev);
-       input_free_device(ts->idev);
 
        kfree(ts);
 
diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c
new file mode 100644 (file)
index 0000000..cf1dba2
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * Texas Instruments TNETV107X Touchscreen Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <mach/tnetv107x.h>
+
+#define TSC_PENUP_POLL         (HZ / 5)
+#define IDLE_TIMEOUT           100 /* msec */
+
+/*
+ * The first and last samples of a touch interval are usually garbage and need
+ * to be filtered out with these devices.  The following definitions control
+ * the number of samples skipped.
+ */
+#define TSC_HEAD_SKIP          1
+#define TSC_TAIL_SKIP          1
+#define TSC_SKIP               (TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
+#define TSC_SAMPLES            (TSC_SKIP + 1)
+
+/* Register Offsets */
+struct tsc_regs {
+       u32     rev;
+       u32     tscm;
+       u32     bwcm;
+       u32     swc;
+       u32     adcchnl;
+       u32     adcdata;
+       u32     chval[4];
+};
+
+/* TSC Mode Configuration Register (tscm) bits */
+#define WMODE          BIT(0)
+#define TSKIND         BIT(1)
+#define ZMEASURE_EN    BIT(2)
+#define IDLE           BIT(3)
+#define TSC_EN         BIT(4)
+#define STOP           BIT(5)
+#define ONE_SHOT       BIT(6)
+#define SINGLE         BIT(7)
+#define AVG            BIT(8)
+#define AVGNUM(x)      (((x) & 0x03) <<  9)
+#define PVSTC(x)       (((x) & 0x07) << 11)
+#define PON            BIT(14)
+#define PONBG          BIT(15)
+#define AFERST         BIT(16)
+
+/* ADC DATA Capture Register bits */
+#define DATA_VALID     BIT(16)
+
+/* Register Access Macros */
+#define tsc_read(ts, reg)              __raw_readl(&(ts)->regs->reg)
+#define tsc_write(ts, reg, val)                __raw_writel(val, &(ts)->regs->reg);
+#define tsc_set_bits(ts, reg, val)     \
+       tsc_write(ts, reg, tsc_read(ts, reg) | (val))
+#define tsc_clr_bits(ts, reg, val)     \
+       tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
+
+struct sample {
+       int x, y, p;
+};
+
+struct tsc_data {
+       struct input_dev                *input_dev;
+       struct resource                 *res;
+       struct tsc_regs __iomem         *regs;
+       struct timer_list               timer;
+       spinlock_t                      lock;
+       struct clk                      *clk;
+       struct device                   *dev;
+       int                             sample_count;
+       struct sample                   samples[TSC_SAMPLES];
+       int                             tsc_irq;
+};
+
+static int tsc_read_sample(struct tsc_data *ts, struct sample* sample)
+{
+       int     x, y, z1, z2, t, p = 0;
+       u32     val;
+
+       val = tsc_read(ts, chval[0]);
+       if (val & DATA_VALID)
+               x = val & 0xffff;
+       else
+               return -EINVAL;
+
+       y  = tsc_read(ts, chval[1]) & 0xffff;
+       z1 = tsc_read(ts, chval[2]) & 0xffff;
+       z2 = tsc_read(ts, chval[3]) & 0xffff;
+
+       if (z1) {
+               t = ((600 * x) * (z2 - z1));
+               p = t / (u32) (z1 << 12);
+               if (p < 0)
+                       p = 0;
+       }
+
+       sample->x  = x;
+       sample->y  = y;
+       sample->p  = p;
+
+       return 0;
+}
+
+static void tsc_poll(unsigned long data)
+{
+       struct tsc_data *ts = (struct tsc_data *)data;
+       unsigned long flags;
+       int i, val, x, y, p;
+
+       spin_lock_irqsave(&ts->lock, flags);
+
+       if (ts->sample_count >= TSC_SKIP) {
+               input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
+               input_report_key(ts->input_dev, BTN_TOUCH, 0);
+               input_sync(ts->input_dev);
+       } else if (ts->sample_count > 0) {
+               /*
+                * A touch event lasted less than our skip count.  Salvage and
+                * report anyway.
+                */
+               for (i = 0, val = 0; i < ts->sample_count; i++)
+                       val += ts->samples[i].x;
+               x = val / ts->sample_count;
+
+               for (i = 0, val = 0; i < ts->sample_count; i++)
+                       val += ts->samples[i].y;
+               y = val / ts->sample_count;
+
+               for (i = 0, val = 0; i < ts->sample_count; i++)
+                       val += ts->samples[i].p;
+               p = val / ts->sample_count;
+
+               input_report_abs(ts->input_dev, ABS_X, x);
+               input_report_abs(ts->input_dev, ABS_Y, y);
+               input_report_abs(ts->input_dev, ABS_PRESSURE, p);
+               input_report_key(ts->input_dev, BTN_TOUCH, 1);
+               input_sync(ts->input_dev);
+       }
+
+       ts->sample_count = 0;
+
+       spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static irqreturn_t tsc_irq(int irq, void *dev_id)
+{
+       struct tsc_data *ts = (struct tsc_data *)dev_id;
+       struct sample *sample;
+       int index;
+
+       spin_lock(&ts->lock);
+
+       index = ts->sample_count % TSC_SAMPLES;
+       sample = &ts->samples[index];
+       if (tsc_read_sample(ts, sample) < 0)
+               goto out;
+
+       if (++ts->sample_count >= TSC_SKIP) {
+               index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
+               sample = &ts->samples[index];
+
+               input_report_abs(ts->input_dev, ABS_X, sample->x);
+               input_report_abs(ts->input_dev, ABS_Y, sample->y);
+               input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p);
+               if (ts->sample_count == TSC_SKIP)
+                       input_report_key(ts->input_dev, BTN_TOUCH, 1);
+               input_sync(ts->input_dev);
+       }
+       mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
+out:
+       spin_unlock(&ts->lock);
+       return IRQ_HANDLED;
+}
+
+static int tsc_start(struct input_dev *dev)
+{
+       struct tsc_data *ts = input_get_drvdata(dev);
+       unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT);
+       u32 val;
+
+       clk_enable(ts->clk);
+
+       /* Go to idle mode, before any initialization */
+       while (time_after(timeout, jiffies)) {
+               if (tsc_read(ts, tscm) & IDLE)
+                       break;
+       }
+
+       if (time_before(timeout, jiffies)) {
+               dev_warn(ts->dev, "timeout waiting for idle\n");
+               clk_disable(ts->clk);
+               return -EIO;
+       }
+
+       /* Configure TSC Control register*/
+       val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
+       tsc_write(ts, tscm, val);
+
+       /* Bring TSC out of reset: Clear AFE reset bit */
+       val &= ~(AFERST);
+       tsc_write(ts, tscm, val);
+
+       /* Configure all pins for hardware control*/
+       tsc_write(ts, bwcm, 0);
+
+       /* Finally enable the TSC */
+       tsc_set_bits(ts, tscm, TSC_EN);
+
+       return 0;
+}
+
+static void tsc_stop(struct input_dev *dev)
+{
+       struct tsc_data *ts = input_get_drvdata(dev);
+
+       tsc_clr_bits(ts, tscm, TSC_EN);
+       synchronize_irq(ts->tsc_irq);
+       del_timer_sync(&ts->timer);
+       clk_disable(ts->clk);
+}
+
+static int __devinit tsc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct tsc_data *ts;
+       int error = 0;
+       u32 rev = 0;
+
+       ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
+       if (!ts) {
+               dev_err(dev, "cannot allocate device info\n");
+               return -ENOMEM;
+       }
+
+       ts->dev = dev;
+       spin_lock_init(&ts->lock);
+       setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
+       platform_set_drvdata(pdev, ts);
+
+       ts->tsc_irq = platform_get_irq(pdev, 0);
+       if (ts->tsc_irq < 0) {
+               dev_err(dev, "cannot determine device interrupt\n");
+               error = -ENODEV;
+               goto error_res;
+       }
+
+       ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!ts->res) {
+               dev_err(dev, "cannot determine register area\n");
+               error = -ENODEV;
+               goto error_res;
+       }
+
+       if (!request_mem_region(ts->res->start, resource_size(ts->res),
+                               pdev->name)) {
+               dev_err(dev, "cannot claim register memory\n");
+               ts->res = NULL;
+               error = -EINVAL;
+               goto error_res;
+       }
+
+       ts->regs = ioremap(ts->res->start, resource_size(ts->res));
+       if (!ts->regs) {
+               dev_err(dev, "cannot map register memory\n");
+               error = -ENOMEM;
+               goto error_map;
+       }
+
+       ts->clk = clk_get(dev, NULL);
+       if (!ts->clk) {
+               dev_err(dev, "cannot claim device clock\n");
+               error = -EINVAL;
+               goto error_clk;
+       }
+
+       error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0,
+                                    dev_name(dev), ts);
+       if (error < 0) {
+               dev_err(ts->dev, "Could not allocate ts irq\n");
+               goto error_irq;
+       }
+
+       ts->input_dev = input_allocate_device();
+       if (!ts->input_dev) {
+               dev_err(dev, "cannot allocate input device\n");
+               error = -ENOMEM;
+               goto error_input;
+       }
+       input_set_drvdata(ts->input_dev, ts);
+
+       ts->input_dev->name       = pdev->name;
+       ts->input_dev->id.bustype = BUS_HOST;
+       ts->input_dev->dev.parent = &pdev->dev;
+       ts->input_dev->open       = tsc_start;
+       ts->input_dev->close      = tsc_stop;
+
+       clk_enable(ts->clk);
+       rev = tsc_read(ts, rev);
+       ts->input_dev->id.product = ((rev >>  8) & 0x07);
+       ts->input_dev->id.version = ((rev >> 16) & 0xfff);
+       clk_disable(ts->clk);
+
+       __set_bit(EV_KEY,    ts->input_dev->evbit);
+       __set_bit(EV_ABS,    ts->input_dev->evbit);
+       __set_bit(BTN_TOUCH, ts->input_dev->keybit);
+
+       input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0);
+       input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0);
+       input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
+
+       error = input_register_device(ts->input_dev);
+       if (error < 0) {
+               dev_err(dev, "failed input device registration\n");
+               goto error_reg;
+       }
+
+       return 0;
+
+error_reg:
+       input_free_device(ts->input_dev);
+error_input:
+       free_irq(ts->tsc_irq, ts);
+error_irq:
+       clk_put(ts->clk);
+error_clk:
+       iounmap(ts->regs);
+error_map:
+       release_mem_region(ts->res->start, resource_size(ts->res));
+error_res:
+       platform_set_drvdata(pdev, NULL);
+       kfree(ts);
+
+       return error;
+}
+
+static int __devexit tsc_remove(struct platform_device *pdev)
+{
+       struct tsc_data *ts = platform_get_drvdata(pdev);
+
+       input_unregister_device(ts->input_dev);
+       free_irq(ts->tsc_irq, ts);
+       clk_put(ts->clk);
+       iounmap(ts->regs);
+       release_mem_region(ts->res->start, resource_size(ts->res));
+       platform_set_drvdata(pdev, NULL);
+       kfree(ts);
+
+       return 0;
+}
+
+static struct platform_driver tsc_driver = {
+       .probe          = tsc_probe,
+       .remove         = __devexit_p(tsc_remove),
+       .driver.name    = "tnetv107x-ts",
+       .driver.owner   = THIS_MODULE,
+};
+
+static int __init tsc_init(void)
+{
+       return platform_driver_register(&tsc_driver);
+}
+
+static void __exit tsc_exit(void)
+{
+       platform_driver_unregister(&tsc_driver);
+}
+
+module_init(tsc_init);
+module_exit(tsc_exit);
+
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
+MODULE_ALIAS("platform: tnetv107x-ts");
+MODULE_LICENSE("GPL");
index a644d18..c8c136c 100644 (file)
@@ -335,6 +335,7 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
                dev_err(tsc->dev, "schedule failed");
                goto err2;
         }
+       platform_set_drvdata(pdev, tps6507x_dev);
 
        return 0;
 
@@ -358,7 +359,7 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
        cancel_delayed_work_sync(&tsc->work);
        destroy_workqueue(tsc->wq);
 
-       input_free_device(input_dev);
+       input_unregister_device(input_dev);
 
        tps6507x_dev->ts = NULL;
        kfree(tsc);
index be23780..80467f2 100644 (file)
@@ -265,7 +265,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
                                   const struct i2c_device_id *id)
 {
        struct tsc2007 *ts;
-       struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
+       struct tsc2007_platform_data *pdata = client->dev.platform_data;
        struct input_dev *input_dev;
        int err;
 
index 56dc35c..9ae4c7b 100644 (file)
@@ -2,6 +2,7 @@
  * Wacom W8001 penabled serial touchscreen driver
  *
  * Copyright (c) 2008 Jaya Kumar
+ * Copyright (c) 2010 Red Hat, Inc.
  *
  * 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
@@ -30,11 +31,24 @@ MODULE_LICENSE("GPL");
 #define W8001_LEAD_BYTE                0x80
 #define W8001_TAB_MASK         0x40
 #define W8001_TAB_BYTE         0x40
+/* set in first byte of touch data packets */
+#define W8001_TOUCH_MASK       (0x10 | W8001_LEAD_MASK)
+#define W8001_TOUCH_BYTE       (0x10 | W8001_LEAD_BYTE)
 
 #define W8001_QUERY_PACKET     0x20
 
 #define W8001_CMD_START                '1'
 #define W8001_CMD_QUERY                '*'
+#define W8001_CMD_TOUCHQUERY   '%'
+
+/* length of data packets in bytes, depends on device. */
+#define W8001_PKTLEN_TOUCH93   5
+#define W8001_PKTLEN_TOUCH9A   7
+#define W8001_PKTLEN_TPCPEN    9
+#define W8001_PKTLEN_TPCCTL    11      /* control packet */
+#define W8001_PKTLEN_TOUCH2FG  13
+
+#define MAX_TRACKING_ID                0xFF    /* arbitrarily chosen */
 
 struct w8001_coord {
        u8 rdy;
@@ -48,6 +62,15 @@ struct w8001_coord {
        u8 tilt_y;
 };
 
+/* touch query reply packet */
+struct w8001_touch_query {
+       u8 panel_res;
+       u8 capacity_res;
+       u8 sensor_id;
+       u16 x;
+       u16 y;
+};
+
 /*
  * Per-touchscreen data.
  */
@@ -62,6 +85,9 @@ struct w8001 {
        unsigned char response[W8001_MAX_LENGTH];
        unsigned char data[W8001_MAX_LENGTH];
        char phys[32];
+       int type;
+       unsigned int pktlen;
+       int trkid[2];
 };
 
 static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -88,11 +114,98 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
        coord->tilt_y = data[8] & 0x7F;
 }
 
+static void parse_touch(struct w8001 *w8001)
+{
+       static int trkid;
+       struct input_dev *dev = w8001->dev;
+       unsigned char *data = w8001->data;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               input_mt_slot(dev, i);
+
+               if (data[0] & (1 << i)) {
+                       int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
+                       int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
+                       /* data[5,6] and [11,12] is finger capacity */
+
+                       input_report_abs(dev, ABS_MT_POSITION_X, x);
+                       input_report_abs(dev, ABS_MT_POSITION_Y, y);
+                       input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
+                       if (w8001->trkid[i] < 0)
+                               w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
+               } else {
+                       w8001->trkid[i] = -1;
+               }
+               input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
+       }
+
+       input_sync(dev);
+}
+
+static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
+{
+       memset(query, 0, sizeof(*query));
+
+       query->panel_res = data[1];
+       query->sensor_id = data[2] & 0x7;
+       query->capacity_res = data[7];
+
+       query->x = data[3] << 9;
+       query->x |= data[4] << 2;
+       query->x |= (data[2] >> 5) & 0x3;
+
+       query->y = data[5] << 9;
+       query->y |= data[6] << 2;
+       query->y |= (data[2] >> 3) & 0x3;
+}
+
+static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
+{
+       struct input_dev *dev = w8001->dev;
+
+       /*
+        * We have 1 bit for proximity (rdy) and 3 bits for tip, side,
+        * side2/eraser. If rdy && f2 are set, this can be either pen + side2,
+        * or eraser. assume
+        * - if dev is already in proximity and f2 is toggled â†’ pen + side2
+        * - if dev comes into proximity with f2 set â†’ eraser
+        * If f2 disappears after assuming eraser, fake proximity out for
+        * eraser and in for pen.
+        */
+
+       if (!w8001->type) {
+               w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+       } else if (w8001->type == BTN_TOOL_RUBBER) {
+               if (!coord->f2) {
+                       input_report_abs(dev, ABS_PRESSURE, 0);
+                       input_report_key(dev, BTN_TOUCH, 0);
+                       input_report_key(dev, BTN_STYLUS, 0);
+                       input_report_key(dev, BTN_STYLUS2, 0);
+                       input_report_key(dev, BTN_TOOL_RUBBER, 0);
+                       input_sync(dev);
+                       w8001->type = BTN_TOOL_PEN;
+               }
+       } else {
+               input_report_key(dev, BTN_STYLUS2, coord->f2);
+       }
+
+       input_report_abs(dev, ABS_X, coord->x);
+       input_report_abs(dev, ABS_Y, coord->y);
+       input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure);
+       input_report_key(dev, BTN_TOUCH, coord->tsw);
+       input_report_key(dev, BTN_STYLUS, coord->f1);
+       input_report_key(dev, w8001->type, coord->rdy);
+       input_sync(dev);
+
+       if (!coord->rdy)
+               w8001->type = 0;
+}
+
 static irqreturn_t w8001_interrupt(struct serio *serio,
                                   unsigned char data, unsigned int flags)
 {
        struct w8001 *w8001 = serio_get_drvdata(serio);
-       struct input_dev *dev = w8001->dev;
        struct w8001_coord coord;
        unsigned char tmp;
 
@@ -105,26 +218,45 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
                }
                break;
 
-       case 8:
+       case W8001_PKTLEN_TOUCH93 - 1:
+       case W8001_PKTLEN_TOUCH9A - 1:
+               /* ignore one-finger touch packet. */
+               if (w8001->pktlen == w8001->idx)
+                       w8001->idx = 0;
+               break;
+
+       /* Pen coordinates packet */
+       case W8001_PKTLEN_TPCPEN - 1:
                tmp = w8001->data[0] & W8001_TAB_MASK;
                if (unlikely(tmp == W8001_TAB_BYTE))
                        break;
 
+               tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
+               if (tmp == W8001_TOUCH_BYTE)
+                       break;
+
                w8001->idx = 0;
                parse_data(w8001->data, &coord);
-               input_report_abs(dev, ABS_X, coord.x);
-               input_report_abs(dev, ABS_Y, coord.y);
-               input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
-               input_report_key(dev, BTN_TOUCH, coord.tsw);
-               input_sync(dev);
+               report_pen_events(w8001, &coord);
                break;
 
-       case 10:
+       /* control packet */
+       case W8001_PKTLEN_TPCCTL - 1:
+               tmp = (w8001->data[0] & W8001_TOUCH_MASK);
+               if (tmp == W8001_TOUCH_BYTE)
+                       break;
+
                w8001->idx = 0;
                memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH);
                w8001->response_type = W8001_QUERY_PACKET;
                complete(&w8001->cmd_done);
                break;
+
+       /* 2 finger touch packet */
+       case W8001_PKTLEN_TOUCH2FG - 1:
+               w8001->idx = 0;
+               parse_touch(w8001);
+               break;
        }
 
        return IRQ_HANDLED;
@@ -167,6 +299,38 @@ static int w8001_setup(struct w8001 *w8001)
        input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
        input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
 
+       error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+       if (!error) {
+               struct w8001_touch_query touch;
+
+               parse_touchquery(w8001->response, &touch);
+
+               switch (touch.sensor_id) {
+               case 0:
+               case 2:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH93;
+                       break;
+               case 1:
+               case 3:
+               case 4:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH9A;
+                       break;
+               case 5:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
+
+                       input_mt_create_slots(dev, 2);
+                       input_set_abs_params(dev, ABS_MT_TRACKING_ID,
+                                               0, MAX_TRACKING_ID, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_POSITION_X,
+                                               0, touch.x, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_POSITION_Y,
+                                               0, touch.y, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
+                                               0, 0, 0, 0);
+                       break;
+               }
+       }
+
        return w8001_command(w8001, W8001_CMD_START, false);
 }
 
@@ -208,6 +372,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
        w8001->serio = serio;
        w8001->id = serio->id.id;
        w8001->dev = input_dev;
+       w8001->trkid[0] = w8001->trkid[1] = -1;
        init_completion(&w8001->cmd_done);
        snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
 
@@ -221,6 +386,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
+       input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
+       input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
+       input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
 
        serio_set_drvdata(serio, w8001);
        err = serio_open(serio, drv);
index cbfef1e..6b75c9f 100644 (file)
@@ -125,6 +125,8 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 {
        int power_adc = 0, auxval;
        u16 power = 0;
+       int rc = 0;
+       int timeout = 0;
 
        /* get codec */
        mutex_lock(&wm->codec_mutex);
@@ -143,7 +145,9 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 
        /* Turn polling mode on to read AUX ADC */
        wm->pen_probably_down = 1;
-       wm->codec->poll_sample(wm, adcsel, &auxval);
+
+       while (rc != RC_VALID && timeout++ < 5)
+               rc = wm->codec->poll_sample(wm, adcsel, &auxval);
 
        if (power_adc)
                wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
@@ -152,8 +156,15 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 
        wm->pen_probably_down = 0;
 
+       if (timeout >= 5) {
+               dev_err(wm->dev,
+                       "timeout reading auxadc %d, disabling digitiser\n",
+                       adcsel);
+               wm->codec->dig_enable(wm, false);
+       }
+
        mutex_unlock(&wm->codec_mutex);
-       return auxval & 0xfff;
+       return (rc == RC_VALID ? auxval & 0xfff : -EBUSY);
 }
 EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
 
@@ -684,8 +695,7 @@ static int wm97xx_probe(struct device *dev)
  touch_reg_err:
        platform_device_put(wm->touch_dev);
  touch_err:
-       platform_device_unregister(wm->battery_dev);
-       wm->battery_dev = NULL;
+       platform_device_del(wm->battery_dev);
  batt_reg_err:
        platform_device_put(wm->battery_dev);
  batt_err:
index 7961d59..c06b4d5 100644 (file)
 #define IR_KEYPRESS_TIMEOUT 250
 
 /**
+ * ir_create_table() - initializes a scancode table
+ * @rc_tab:    the ir_scancode_table to initialize
+ * @name:      name to assign to the table
+ * @ir_type:   ir type to assign to the new table
+ * @size:      initial size of the table
+ * @return:    zero on success or a negative error code
+ *
+ * This routine will initialize the ir_scancode_table and will allocate
+ * memory to hold at least the specified number elements.
+ */
+static int ir_create_table(struct ir_scancode_table *rc_tab,
+                          const char *name, u64 ir_type, size_t size)
+{
+       rc_tab->name = name;
+       rc_tab->ir_type = ir_type;
+       rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
+       rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
+       rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
+       if (!rc_tab->scan)
+               return -ENOMEM;
+
+       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+                  rc_tab->size, rc_tab->alloc);
+       return 0;
+}
+
+/**
+ * ir_free_table() - frees memory allocated by a scancode table
+ * @rc_tab:    the table whose mappings need to be freed
+ *
+ * This routine will free memory alloctaed for key mappings used by given
+ * scancode table.
+ */
+static void ir_free_table(struct ir_scancode_table *rc_tab)
+{
+       rc_tab->size = 0;
+       kfree(rc_tab->scan);
+       rc_tab->scan = NULL;
+}
+
+/**
  * ir_resize_table() - resizes a scancode table if necessary
  * @rc_tab:    the ir_scancode_table to resize
+ * @gfp_flags: gfp flags to use when allocating memory
  * @return:    zero on success or a negative error code
  *
  * This routine will shrink the ir_scancode_table if it has lots of
  * unused entries and grow it if it is full.
  */
-static int ir_resize_table(struct ir_scancode_table *rc_tab)
+static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
 {
        unsigned int oldalloc = rc_tab->alloc;
        unsigned int newalloc = oldalloc;
@@ -57,7 +99,7 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
        if (newalloc == oldalloc)
                return 0;
 
-       newscan = kmalloc(newalloc, GFP_ATOMIC);
+       newscan = kmalloc(newalloc, gfp_flags);
        if (!newscan) {
                IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
                return -ENOMEM;
@@ -72,26 +114,78 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
 }
 
 /**
- * ir_do_setkeycode() - internal function to set a keycode in the
- *                     scancode->keycode table
+ * ir_update_mapping() - set a keycode in the scancode->keycode table
  * @dev:       the struct input_dev device descriptor
- * @rc_tab:    the struct ir_scancode_table to set the keycode in
- * @scancode:  the scancode for the ir command
- * @keycode:   the keycode for the ir command
- * @resize:    whether the keytable may be shrunk
- * @return:    -EINVAL if the keycode could not be inserted, otherwise zero.
+ * @rc_tab:    scancode table to be adjusted
+ * @index:     index of the mapping that needs to be updated
+ * @keycode:   the desired keycode
+ * @return:    previous keycode assigned to the mapping
+ *
+ * This routine is used to update scancode->keycopde mapping at given
+ * position.
+ */
+static unsigned int ir_update_mapping(struct input_dev *dev,
+                                     struct ir_scancode_table *rc_tab,
+                                     unsigned int index,
+                                     unsigned int new_keycode)
+{
+       int old_keycode = rc_tab->scan[index].keycode;
+       int i;
+
+       /* Did the user wish to remove the mapping? */
+       if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
+               IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
+                          index, rc_tab->scan[index].scancode);
+               rc_tab->len--;
+               memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
+                       (rc_tab->len - index) * sizeof(struct ir_scancode));
+       } else {
+               IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+                          index,
+                          old_keycode == KEY_RESERVED ? "New" : "Replacing",
+                          rc_tab->scan[index].scancode, new_keycode);
+               rc_tab->scan[index].keycode = new_keycode;
+               __set_bit(new_keycode, dev->keybit);
+       }
+
+       if (old_keycode != KEY_RESERVED) {
+               /* A previous mapping was updated... */
+               __clear_bit(old_keycode, dev->keybit);
+               /* ... but another scancode might use the same keycode */
+               for (i = 0; i < rc_tab->len; i++) {
+                       if (rc_tab->scan[i].keycode == old_keycode) {
+                               __set_bit(old_keycode, dev->keybit);
+                               break;
+                       }
+               }
+
+               /* Possibly shrink the keytable, failure is not a problem */
+               ir_resize_table(rc_tab, GFP_ATOMIC);
+       }
+
+       return old_keycode;
+}
+
+/**
+ * ir_locate_scancode() - set a keycode in the scancode->keycode table
+ * @ir_dev:    the struct ir_input_dev device descriptor
+ * @rc_tab:    scancode table to be searched
+ * @scancode:  the desired scancode
+ * @resize:    controls whether we allowed to resize the table to
+ *             accomodate not yet present scancodes
+ * @return:    index of the mapping containing scancode in question
+ *             or -1U in case of failure.
  *
- * This routine is used internally to manipulate the scancode->keycode table.
- * The caller has to hold @rc_tab->lock.
+ * This routine is used to locate given scancode in ir_scancode_table.
+ * If scancode is not yet present the routine will allocate a new slot
+ * for it.
  */
-static int ir_do_setkeycode(struct input_dev *dev,
-                           struct ir_scancode_table *rc_tab,
-                           unsigned scancode, unsigned keycode,
-                           bool resize)
+static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
+                                         struct ir_scancode_table *rc_tab,
+                                         unsigned int scancode,
+                                         bool resize)
 {
        unsigned int i;
-       int old_keycode = KEY_RESERVED;
-       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 
        /*
         * Unfortunately, some hardware-based IR decoders don't provide
@@ -100,65 +194,34 @@ static int ir_do_setkeycode(struct input_dev *dev,
         * the provided IR with another one, it is needed to allow loading
         * IR tables from other remotes. So,
         */
-       if (ir_dev->props && ir_dev->props->scanmask) {
+       if (ir_dev->props && ir_dev->props->scanmask)
                scancode &= ir_dev->props->scanmask;
-       }
 
        /* First check if we already have a mapping for this ir command */
        for (i = 0; i < rc_tab->len; i++) {
+               if (rc_tab->scan[i].scancode == scancode)
+                       return i;
+
                /* Keytable is sorted from lowest to highest scancode */
-               if (rc_tab->scan[i].scancode > scancode)
+               if (rc_tab->scan[i].scancode >= scancode)
                        break;
-               else if (rc_tab->scan[i].scancode < scancode)
-                       continue;
-
-               old_keycode = rc_tab->scan[i].keycode;
-               rc_tab->scan[i].keycode = keycode;
-
-               /* Did the user wish to remove the mapping? */
-               if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) {
-                       IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
-                                  i, scancode);
-                       rc_tab->len--;
-                       memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1],
-                               (rc_tab->len - i) * sizeof(struct ir_scancode));
-               }
-
-               /* Possibly shrink the keytable, failure is not a problem */
-               ir_resize_table(rc_tab);
-               break;
        }
 
-       if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) {
-               /* No previous mapping found, we might need to grow the table */
-               if (resize && ir_resize_table(rc_tab))
-                       return -ENOMEM;
-
-               IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
-                          i, scancode, keycode);
+       /* No previous mapping found, we might need to grow the table */
+       if (rc_tab->size == rc_tab->len) {
+               if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
+                       return -1U;
+       }
 
-               /* i is the proper index to insert our new keycode */
+       /* i is the proper index to insert our new keycode */
+       if (i < rc_tab->len)
                memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
                        (rc_tab->len - i) * sizeof(struct ir_scancode));
-               rc_tab->scan[i].scancode = scancode;
-               rc_tab->scan[i].keycode = keycode;
-               rc_tab->len++;
-               set_bit(keycode, dev->keybit);
-       } else {
-               IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
-                          i, scancode, keycode);
-               /* A previous mapping was updated... */
-               clear_bit(old_keycode, dev->keybit);
-               /* ...but another scancode might use the same keycode */
-               for (i = 0; i < rc_tab->len; i++) {
-                       if (rc_tab->scan[i].keycode == old_keycode) {
-                               set_bit(old_keycode, dev->keybit);
-                               break;
-                       }
-               }
-       }
+       rc_tab->scan[i].scancode = scancode;
+       rc_tab->scan[i].keycode = KEY_RESERVED;
+       rc_tab->len++;
 
-       return 0;
+       return i;
 }
 
 /**
@@ -171,17 +234,41 @@ static int ir_do_setkeycode(struct input_dev *dev,
  * This routine is used to handle evdev EVIOCSKEY ioctl.
  */
 static int ir_setkeycode(struct input_dev *dev,
-                        unsigned int scancode, unsigned int keycode)
+                        const struct input_keymap_entry *ke,
+                        unsigned int *old_keycode)
 {
-       int rc;
-       unsigned long flags;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       unsigned int index;
+       unsigned int scancode;
+       int retval;
+       unsigned long flags;
 
        spin_lock_irqsave(&rc_tab->lock, flags);
-       rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+               if (index >= rc_tab->len) {
+                       retval = -EINVAL;
+                       goto out;
+               }
+       } else {
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
+               if (index >= rc_tab->len) {
+                       retval = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
+
+out:
        spin_unlock_irqrestore(&rc_tab->lock, flags);
-       return rc;
+       return retval;
 }
 
 /**
@@ -189,32 +276,73 @@ static int ir_setkeycode(struct input_dev *dev,
  * @dev:       the struct input_dev device descriptor
  * @to:                the struct ir_scancode_table to copy entries to
  * @from:      the struct ir_scancode_table to copy entries from
- * @return:    -EINVAL if all keycodes could not be inserted, otherwise zero.
+ * @return:    -ENOMEM if all keycodes could not be inserted, otherwise zero.
  *
  * This routine is used to handle table initialization.
  */
-static int ir_setkeytable(struct input_dev *dev,
-                         struct ir_scancode_table *to,
+static int ir_setkeytable(struct ir_input_dev *ir_dev,
                          const struct ir_scancode_table *from)
 {
-       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-       unsigned long flags;
-       unsigned int i;
-       int rc = 0;
+       unsigned int i, index;
+       int rc;
+
+       rc = ir_create_table(&ir_dev->rc_tab,
+                            from->name, from->ir_type, from->size);
+       if (rc)
+               return rc;
+
+       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+                  rc_tab->size, rc_tab->alloc);
 
-       spin_lock_irqsave(&rc_tab->lock, flags);
        for (i = 0; i < from->size; i++) {
-               rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
-                                     from->scan[i].keycode, false);
-               if (rc)
+               index = ir_establish_scancode(ir_dev, rc_tab,
+                                             from->scan[i].scancode, false);
+               if (index >= rc_tab->len) {
+                       rc = -ENOMEM;
                        break;
+               }
+
+               ir_update_mapping(ir_dev->input_dev, rc_tab, index,
+                                 from->scan[i].keycode);
        }
-       spin_unlock_irqrestore(&rc_tab->lock, flags);
+
+       if (rc)
+               ir_free_table(rc_tab);
+
        return rc;
 }
 
 /**
+ * ir_lookup_by_scancode() - locate mapping by scancode
+ * @rc_tab:    the &struct ir_scancode_table to search
+ * @scancode:  scancode to look for in the table
+ * @return:    index in the table, -1U if not found
+ *
+ * This routine performs binary search in RC keykeymap table for
+ * given scancode.
+ */
+static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
+                                         unsigned int scancode)
+{
+       unsigned int start = 0;
+       unsigned int end = rc_tab->len - 1;
+       unsigned int mid;
+
+       while (start <= end) {
+               mid = (start + end) / 2;
+               if (rc_tab->scan[mid].scancode < scancode)
+                       start = mid + 1;
+               else if (rc_tab->scan[mid].scancode > scancode)
+                       end = mid - 1;
+               else
+                       return mid;
+       }
+
+       return -1U;
+}
+
+/**
  * ir_getkeycode() - get a keycode from the scancode->keycode table
  * @dev:       the struct input_dev device descriptor
  * @scancode:  the desired scancode
@@ -224,36 +352,46 @@ static int ir_setkeytable(struct input_dev *dev,
  * This routine is used to handle evdev EVIOCGKEY ioctl.
  */
 static int ir_getkeycode(struct input_dev *dev,
-                        unsigned int scancode, unsigned int *keycode)
+                        struct input_keymap_entry *ke)
 {
-       int start, end, mid;
-       unsigned long flags;
-       int key = KEY_RESERVED;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       struct ir_scancode *entry;
+       unsigned long flags;
+       unsigned int index;
+       unsigned int scancode;
+       int retval;
 
        spin_lock_irqsave(&rc_tab->lock, flags);
-       start = 0;
-       end = rc_tab->len - 1;
-       while (start <= end) {
-               mid = (start + end) / 2;
-               if (rc_tab->scan[mid].scancode < scancode)
-                       start = mid + 1;
-               else if (rc_tab->scan[mid].scancode > scancode)
-                       end = mid - 1;
-               else {
-                       key = rc_tab->scan[mid].keycode;
-                       break;
-               }
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+       } else {
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               index = ir_lookup_by_scancode(rc_tab, scancode);
+       }
+
+       if (index >= rc_tab->len) {
+               if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+                       IR_dprintk(1, "unknown key for scancode 0x%04x\n",
+                                  scancode);
+               retval = -EINVAL;
+               goto out;
        }
-       spin_unlock_irqrestore(&rc_tab->lock, flags);
 
-       if (key == KEY_RESERVED)
-               IR_dprintk(1, "unknown key for scancode 0x%04x\n",
-                          scancode);
+       entry = &rc_tab->scan[index];
 
-       *keycode = key;
-       return 0;
+       ke->index = index;
+       ke->keycode = entry->keycode;
+       ke->len = sizeof(entry->scancode);
+       memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+
+out:
+       spin_unlock_irqrestore(&rc_tab->lock, flags);
+       return retval;
 }
 
 /**
@@ -268,12 +406,24 @@ static int ir_getkeycode(struct input_dev *dev,
  */
 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
 {
-       int keycode;
+       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+       struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       unsigned int keycode;
+       unsigned int index;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rc_tab->lock, flags);
+
+       index = ir_lookup_by_scancode(rc_tab, scancode);
+       keycode = index < rc_tab->len ?
+                       rc_tab->scan[index].keycode : KEY_RESERVED;
+
+       spin_unlock_irqrestore(&rc_tab->lock, flags);
 
-       ir_getkeycode(dev, scancode, &keycode);
        if (keycode != KEY_RESERVED)
                IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
                           dev->name, scancode, keycode);
+
        return keycode;
 }
 EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
@@ -453,8 +603,8 @@ int __ir_input_register(struct input_dev *input_dev,
                goto out_dev;
        }
 
-       input_dev->getkeycode = ir_getkeycode;
-       input_dev->setkeycode = ir_setkeycode;
+       input_dev->getkeycode_new = ir_getkeycode;
+       input_dev->setkeycode_new = ir_setkeycode;
        input_set_drvdata(input_dev, ir_dev);
        ir_dev->input_dev = input_dev;
 
@@ -462,12 +612,6 @@ int __ir_input_register(struct input_dev *input_dev,
        spin_lock_init(&ir_dev->keylock);
        setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
 
-       ir_dev->rc_tab.name = rc_tab->name;
-       ir_dev->rc_tab.ir_type = rc_tab->ir_type;
-       ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size *
-                                                 sizeof(struct ir_scancode));
-       ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
-       ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
        if (props) {
                ir_dev->props = props;
                if (props->open)
@@ -476,23 +620,14 @@ int __ir_input_register(struct input_dev *input_dev,
                        input_dev->close = ir_close;
        }
 
-       if (!ir_dev->rc_tab.scan) {
-               rc = -ENOMEM;
-               goto out_name;
-       }
-
-       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-                  ir_dev->rc_tab.size, ir_dev->rc_tab.alloc);
-
        set_bit(EV_KEY, input_dev->evbit);
        set_bit(EV_REP, input_dev->evbit);
        set_bit(EV_MSC, input_dev->evbit);
        set_bit(MSC_SCAN, input_dev->mscbit);
 
-       if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
-               rc = -ENOMEM;
-               goto out_table;
-       }
+       rc = ir_setkeytable(ir_dev, rc_tab);
+       if (rc)
+               goto out_name;
 
        rc = ir_register_class(input_dev);
        if (rc < 0)
@@ -522,7 +657,7 @@ int __ir_input_register(struct input_dev *input_dev,
 out_event:
        ir_unregister_class(input_dev);
 out_table:
-       kfree(ir_dev->rc_tab.scan);
+       ir_free_table(&ir_dev->rc_tab);
 out_name:
        kfree(ir_dev->driver_name);
 out_dev:
@@ -540,7 +675,6 @@ EXPORT_SYMBOL_GPL(__ir_input_register);
 void ir_input_unregister(struct input_dev *input_dev)
 {
        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-       struct ir_scancode_table *rc_tab;
 
        if (!ir_dev)
                return;
@@ -552,10 +686,7 @@ void ir_input_unregister(struct input_dev *input_dev)
                if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
                        ir_raw_event_unregister(input_dev);
 
-       rc_tab = &ir_dev->rc_tab;
-       rc_tab->size = 0;
-       kfree(rc_tab->scan);
-       rc_tab->scan = NULL;
+       ir_free_table(&ir_dev->rc_tab);
 
        ir_unregister_class(input_dev);
 
index defa786..b8c4b80 100644 (file)
@@ -338,6 +338,21 @@ static struct resource ab8500_rtc_resources[] = {
        },
 };
 
+static struct resource ab8500_poweronkey_db_resources[] = {
+       {
+               .name   = "ONKEY_DBF",
+               .start  = AB8500_INT_PON_KEY1DB_F,
+               .end    = AB8500_INT_PON_KEY1DB_F,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "ONKEY_DBR",
+               .start  = AB8500_INT_PON_KEY1DB_R,
+               .end    = AB8500_INT_PON_KEY1DB_R,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct mfd_cell ab8500_devs[] = {
        {
                .name = "ab8500-gpadc",
@@ -354,6 +369,11 @@ static struct mfd_cell ab8500_devs[] = {
        { .name = "ab8500-usb", },
        { .name = "ab8500-pwm", },
        { .name = "ab8500-regulator", },
+       {
+               .name = "ab8500-poweron-key",
+               .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+               .resources = ab8500_poweronkey_db_resources,
+       },
 };
 
 int __devinit ab8500_init(struct ab8500 *ab8500)
index cd16459..49b4d06 100644 (file)
@@ -65,7 +65,7 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state)
                p->set_pwr(pdev, state);
 }
 
-static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
+static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
        struct sh_mobile_sdhi *priv;
        struct tmio_mmc_data *mmc_data;
index 720e099..5d0fb60 100644 (file)
@@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
 
        if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
                sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-               child = add_child(sub_chip_id, "twl4030_codec",
+               child = add_child(sub_chip_id, "twl4030-audio",
                                pdata->codec, sizeof(*pdata->codec),
                                false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
        }
 
-       /* Phoenix*/
+       /* Phoenix codec driver is probed directly atm */
        if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
                sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
-               child = add_child(sub_chip_id, "twl6040_codec",
+               child = add_child(sub_chip_id, "twl6040-codec",
                                pdata->codec, sizeof(*pdata->codec),
                                false, 0, 0);
                if (IS_ERR(child))
index add6f67..9a4b196 100644 (file)
@@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
 
        if (pdata->audio) {
                cell = &codec->cells[childs];
-               cell->name = "twl4030_codec_audio";
+               cell->name = "twl4030-codec";
                cell->platform_data = pdata->audio;
                cell->data_size = sizeof(*pdata->audio);
                childs++;
        }
        if (pdata->vibra) {
                cell = &codec->cells[childs];
-               cell->name = "twl4030_codec_vibra";
+               cell->name = "twl4030-vibra";
                cell->platform_data = pdata->vibra;
                cell->data_size = sizeof(*pdata->vibra);
                childs++;
@@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev)
        return 0;
 }
 
-MODULE_ALIAS("platform:twl4030_codec");
+MODULE_ALIAS("platform:twl4030-audio");
 
 static struct platform_driver twl4030_codec_driver = {
        .probe          = twl4030_codec_probe,
        .remove         = __devexit_p(twl4030_codec_remove),
        .driver         = {
                .owner  = THIS_MODULE,
-               .name   = "twl4030_codec",
+               .name   = "twl4030-audio",
        },
 };
 
index 4526d27..4693e62 100644 (file)
@@ -364,6 +364,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 {
        struct regulator *reg;
        int ret = 0;
+       int ocr_value = 0;
 
        switch (host->id) {
        case OMAP_MMC1_DEVID:
@@ -396,6 +397,17 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                }
        } else {
                host->vcc = reg;
+               ocr_value = mmc_regulator_get_ocrmask(reg);
+               if (!mmc_slot(host).ocr_mask) {
+                       mmc_slot(host).ocr_mask = ocr_value;
+               } else {
+                       if (!(mmc_slot(host).ocr_mask & ocr_value)) {
+                               pr_err("MMC%d ocrmask %x is not supported\n",
+                                       host->id, mmc_slot(host).ocr_mask);
+                               mmc_slot(host).ocr_mask = 0;
+                               return -EINVAL;
+                       }
+               }
                mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg);
 
                /* Allow an aux regulator */
@@ -982,6 +994,17 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                         OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
 
+       /*
+        * OMAP4 ES2 and greater has an updated reset logic.
+        * Monitor a 0->1 transition first
+        */
+       if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
+               while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
+                                       && (i++ < limit))
+                       cpu_relax();
+       }
+       i = 0;
+
        while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
                (i++ < limit))
                cpu_relax();
@@ -2003,6 +2026,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        if (res == NULL || irq < 0)
                return -ENXIO;
 
+       res->start += pdata->reg_offset;
+       res->end += pdata->reg_offset;
        res = request_mem_region(res->start, res->end - res->start + 1,
                                                        pdev->name);
        if (res == NULL)
@@ -2116,23 +2141,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
-       switch (mmc_slot(host).wires) {
-       case 8:
-               mmc->caps |= MMC_CAP_8_BIT_DATA;
-               /* Fall through */
-       case 4:
+       mmc->caps |= mmc_slot(host).caps;
+       if (mmc->caps & MMC_CAP_8_BIT_DATA)
                mmc->caps |= MMC_CAP_4_BIT_DATA;
-               break;
-       case 1:
-               /* Nothing to crib here */
-       case 0:
-               /* Assuming nothing was given by board, Core use's 1-Bit */
-               break;
-       default:
-               /* Completely unexpected.. Core goes with 1-Bit Width */
-               dev_crit(mmc_dev(host->mmc), "Invalid width %d\n used!"
-                       "using 1 instead\n", mmc_slot(host).wires);
-       }
 
        if (mmc_slot(host).nonremovable)
                mmc->caps |= MMC_CAP_NONREMOVABLE;
index 6f512b5..ea22520 100644 (file)
@@ -924,6 +924,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
                        nr_parts = data->nr_parts;
                }
 
+#ifdef CONFIG_OF
+               if (nr_parts <= 0 && spi->dev.of_node) {
+                       nr_parts = of_mtd_parse_partitions(&spi->dev,
+                                       spi->dev.of_node, &parts);
+               }
+#endif
+
                if (nr_parts > 0) {
                        for (i = 0; i < nr_parts; i++) {
                                DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
index fe63f6b..ec3edf6 100644 (file)
@@ -294,7 +294,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
                info->list[i].map.name = dev_name(&dev->dev);
                info->list[i].map.phys = res.start;
                info->list[i].map.size = res_size;
-               info->list[i].map.bankwidth = *width;
+               info->list[i].map.bankwidth = be32_to_cpup(width);
 
                err = -ENOMEM;
                info->list[i].map.virt = ioremap(info->list[i].map.phys,
index 2ac7367..8beb0d0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 
 #include <mach/nand.h>
+#include <mach/aemif.h>
 
 #include <asm/mach-types.h>
 
@@ -74,6 +75,8 @@ struct davinci_nand_info {
        uint32_t                mask_cle;
 
        uint32_t                core_chipsel;
+
+       struct davinci_aemif_timing     *timing;
 };
 
 static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -478,36 +481,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
        return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
 }
 
-static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
-{
-       uint32_t regval, a1cr;
-
-       /*
-        * NAND FLASH timings @ PLL1 == 459 MHz
-        *  - AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz
-        *  - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
-        */
-       regval = 0
-               | (0 << 31)           /* selectStrobe */
-               | (0 << 30)           /* extWait (never with NAND) */
-               | (1 << 26)           /* writeSetup      10 ns */
-               | (3 << 20)           /* writeStrobe     40 ns */
-               | (1 << 17)           /* writeHold       10 ns */
-               | (0 << 13)           /* readSetup       10 ns */
-               | (3 << 7)            /* readStrobe      60 ns */
-               | (0 << 4)            /* readHold        10 ns */
-               | (3 << 2)            /* turnAround      ?? ns */
-               | (0 << 0)            /* asyncSize       8-bit bus */
-               ;
-       a1cr = davinci_nand_readl(info, A1CR_OFFSET);
-       if (a1cr != regval) {
-               dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
-                      "reg to 0x%08x, was 0x%08x, should be done by " \
-                      "bootloader.\n", regval, a1cr);
-               davinci_nand_writel(info, A1CR_OFFSET, regval);
-       }
-}
-
 /*----------------------------------------------------------------------*/
 
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -611,6 +584,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
        info->chip.options      = pdata->options;
        info->chip.bbt_td       = pdata->bbt_td;
        info->chip.bbt_md       = pdata->bbt_md;
+       info->timing            = pdata->timing;
 
        info->ioaddr            = (uint32_t __force) vaddr;
 
@@ -688,15 +662,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                goto err_clk_enable;
        }
 
-       /* EMIF timings should normally be set by the boot loader,
-        * especially after boot-from-NAND.  The *only* reason to
-        * have this special casing for the DM6446 EVM is to work
-        * with boot-from-NOR ... with CS0 manually re-jumpered
-        * (after startup) so it addresses the NAND flash, not NOR.
-        * Even for dev boards, that's unusually rude...
+       /*
+        * Setup Async configuration register in case we did not boot from
+        * NAND and so bootloader did not bother to set it up.
         */
-       if (machine_is_davinci_evm())
-               nand_dm6446evm_flash_init(info);
+       val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
+
+       /* Extended Wait is not valid and Select Strobe mode is not used */
+       val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
+       if (info->chip.options & NAND_BUSWIDTH_16)
+               val |= 0x1;
+
+       davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
+
+       ret = davinci_aemif_setup_timing(info->timing, info->base,
+                                                       info->core_chipsel);
+       if (ret < 0) {
+               dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
+               goto err_timing;
+       }
 
        spin_lock_irq(&davinci_nand_lock);
 
@@ -809,6 +793,7 @@ syndrome_done:
        return 0;
 
 err_scan:
+err_timing:
        clk_disable(info->clk);
 
 err_clk_enable:
index 8bf7dc6..7bd171e 100644 (file)
@@ -53,8 +53,8 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
                        continue;
                }
 
-               (*pparts)[i].offset = reg[0];
-               (*pparts)[i].size = reg[1];
+               (*pparts)[i].offset = be32_to_cpu(reg[0]);
+               (*pparts)[i].size = be32_to_cpu(reg[1]);
 
                partname = of_get_property(pp, "label", &len);
                if (!partname)
index 77c1fab..86fe67f 100644 (file)
@@ -883,14 +883,6 @@ config BFIN_RX_DESC_NUM
        help
          Set the number of buffer packets used in driver.
 
-config BFIN_MAC_RMII
-       bool "RMII PHY Interface"
-       depends on BFIN_MAC
-       default y if BFIN527_EZKIT
-       default n if BFIN537_STAMP
-       help
-         Use Reduced PHY MII Interface
-
 config BFIN_MAC_USE_HWSTAMP
        bool "Use IEEE 1588 hwstamp"
        depends on BFIN_MAC && BF518
@@ -954,6 +946,8 @@ config NET_NETX
 config TI_DAVINCI_EMAC
        tristate "TI DaVinci EMAC Support"
        depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       select TI_DAVINCI_MDIO
+       select TI_DAVINCI_CPDMA
        select PHYLIB
        help
          This driver supports TI's DaVinci Ethernet .
@@ -961,6 +955,25 @@ config TI_DAVINCI_EMAC
          To compile this driver as a module, choose M here: the module
          will be called davinci_emac_driver.  This is recommended.
 
+config TI_DAVINCI_MDIO
+       tristate "TI DaVinci MDIO Support"
+       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       select PHYLIB
+       help
+         This driver supports TI's DaVinci MDIO module.
+
+         To compile this driver as a module, choose M here: the module
+         will be called davinci_mdio.  This is recommended.
+
+config TI_DAVINCI_CPDMA
+       tristate "TI DaVinci CPDMA Support"
+       depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+       help
+         This driver supports TI's DaVinci CPDMA dma engine.
+
+         To compile this driver as a module, choose M here: the module
+         will be called davinci_cpdma.  This is recommended.
+
 config DM9000
        tristate "DM9000 support"
        depends on ARM || BLACKFIN || MIPS
index b8bf93d..652fc6b 100644 (file)
@@ -7,6 +7,8 @@ obj-$(CONFIG_MDIO) += mdio.o
 obj-$(CONFIG_PHYLIB) += phy/
 
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
+obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000E) += e1000e/
index f723319..ce1e5e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip MAC Driver
  *
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -23,7 +23,6 @@
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/mii.h>
-#include <linux/phy.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -76,12 +75,6 @@ static struct net_dma_desc_tx *current_tx_ptr;
 static struct net_dma_desc_tx *tx_desc;
 static struct net_dma_desc_rx *rx_desc;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-static u16 pin_req[] = P_RMII0;
-#else
-static u16 pin_req[] = P_MII0;
-#endif
-
 static void desc_list_free(void)
 {
        struct net_dma_desc_rx *r;
@@ -347,23 +340,23 @@ static void bfin_mac_adjust_link(struct net_device *dev)
                }
 
                if (phydev->speed != lp->old_speed) {
-#if defined(CONFIG_BFIN_MAC_RMII)
-                       u32 opmode = bfin_read_EMAC_OPMODE();
-                       switch (phydev->speed) {
-                       case 10:
-                               opmode |= RMII_10;
-                               break;
-                       case 100:
-                               opmode &= ~(RMII_10);
-                               break;
-                       default:
-                               printk(KERN_WARNING
-                                       "%s: Ack!  Speed (%d) is not 10/100!\n",
-                                       DRV_NAME, phydev->speed);
-                               break;
+                       if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+                               u32 opmode = bfin_read_EMAC_OPMODE();
+                               switch (phydev->speed) {
+                               case 10:
+                                       opmode |= RMII_10;
+                                       break;
+                               case 100:
+                                       opmode &= ~RMII_10;
+                                       break;
+                               default:
+                                       printk(KERN_WARNING
+                                               "%s: Ack!  Speed (%d) is not 10/100!\n",
+                                               DRV_NAME, phydev->speed);
+                                       break;
+                               }
+                               bfin_write_EMAC_OPMODE(opmode);
                        }
-                       bfin_write_EMAC_OPMODE(opmode);
-#endif
 
                        new_state = 1;
                        lp->old_speed = phydev->speed;
@@ -392,7 +385,7 @@ static void bfin_mac_adjust_link(struct net_device *dev)
 /* MDC  = 2.5 MHz */
 #define MDC_CLK 2500000
 
-static int mii_probe(struct net_device *dev)
+static int mii_probe(struct net_device *dev, int phy_mode)
 {
        struct bfin_mac_local *lp = netdev_priv(dev);
        struct phy_device *phydev = NULL;
@@ -411,8 +404,8 @@ static int mii_probe(struct net_device *dev)
        sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
        bfin_write_EMAC_SYSCTL(sysctl);
 
-       /* search for connect PHY device */
-       for (i = 0; i < PHY_MAX_ADDR; i++) {
+       /* search for connected PHY device */
+       for (i = 0; i < PHY_MAX_ADDR; ++i) {
                struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
 
                if (!tmp_phydev)
@@ -429,13 +422,14 @@ static int mii_probe(struct net_device *dev)
                return -ENODEV;
        }
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-                       0, PHY_INTERFACE_MODE_RMII);
-#else
+       if (phy_mode != PHY_INTERFACE_MODE_RMII &&
+               phy_mode != PHY_INTERFACE_MODE_MII) {
+               printk(KERN_INFO "%s: Invalid phy interface mode\n", dev->name);
+               return -EINVAL;
+       }
+
        phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-                       0, PHY_INTERFACE_MODE_MII);
-#endif
+                       0, phy_mode);
 
        if (IS_ERR(phydev)) {
                printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -570,6 +564,8 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
 /**************************************************************************/
 void setup_system_regs(struct net_device *dev)
 {
+       struct bfin_mac_local *lp = netdev_priv(dev);
+       int i;
        unsigned short sysctl;
 
        /*
@@ -577,6 +573,15 @@ void setup_system_regs(struct net_device *dev)
         * Configure checksum support and rcve frame word alignment
         */
        sysctl = bfin_read_EMAC_SYSCTL();
+       /*
+        * check if interrupt is requested for any PHY,
+        * enable PHY interrupt only if needed
+        */
+       for (i = 0; i < PHY_MAX_ADDR; ++i)
+               if (lp->mii_bus->irq[i] != PHY_POLL)
+                       break;
+       if (i < PHY_MAX_ADDR)
+               sysctl |= PHYIE;
        sysctl |= RXDWA;
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
        sysctl |= RXCKS;
@@ -1203,7 +1208,7 @@ static void bfin_mac_disable(void)
 /*
  * Enable Interrupts, Receive, and Transmit
  */
-static int bfin_mac_enable(void)
+static int bfin_mac_enable(struct phy_device *phydev)
 {
        int ret;
        u32 opmode;
@@ -1233,12 +1238,13 @@ static int bfin_mac_enable(void)
                opmode |= DRO | DC | PSF;
        opmode |= RE;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-       opmode |= RMII; /* For Now only 100MBit are supported */
+       if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+               opmode |= RMII; /* For Now only 100MBit are supported */
 #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
-       opmode |= TE;
-#endif
+               opmode |= TE;
 #endif
+       }
+
        /* Turn on the EMAC rx */
        bfin_write_EMAC_OPMODE(opmode);
 
@@ -1270,7 +1276,7 @@ static void bfin_mac_timeout(struct net_device *dev)
        if (netif_queue_stopped(lp->ndev))
                netif_wake_queue(lp->ndev);
 
-       bfin_mac_enable();
+       bfin_mac_enable(lp->phydev);
 
        /* We can accept TX packets again */
        dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1342,11 +1348,19 @@ static void bfin_mac_set_multicast_list(struct net_device *dev)
 
 static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
+       struct bfin_mac_local *lp = netdev_priv(netdev);
+
+       if (!netif_running(netdev))
+               return -EINVAL;
+
        switch (cmd) {
        case SIOCSHWTSTAMP:
                return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
        default:
-               return -EOPNOTSUPP;
+               if (lp->phydev)
+                       return phy_mii_ioctl(lp->phydev, ifr, cmd);
+               else
+                       return -EOPNOTSUPP;
        }
 }
 
@@ -1394,7 +1408,7 @@ static int bfin_mac_open(struct net_device *dev)
        setup_mac_addr(dev->dev_addr);
 
        bfin_mac_disable();
-       ret = bfin_mac_enable();
+       ret = bfin_mac_enable(lp->phydev);
        if (ret)
                return ret;
        pr_debug("hardware init finished\n");
@@ -1450,6 +1464,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        struct net_device *ndev;
        struct bfin_mac_local *lp;
        struct platform_device *pd;
+       struct bfin_mii_bus_platform_data *mii_bus_data;
        int rc;
 
        ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
@@ -1501,11 +1516,12 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        if (!lp->mii_bus) {
                dev_err(&pdev->dev, "Cannot get mii_bus!\n");
                rc = -ENODEV;
-               goto out_err_mii_bus_probe;
+               goto out_err_probe_mac;
        }
        lp->mii_bus->priv = ndev;
+       mii_bus_data = pd->dev.platform_data;
 
-       rc = mii_probe(ndev);
+       rc = mii_probe(ndev, mii_bus_data->phy_mode);
        if (rc) {
                dev_err(&pdev->dev, "MII Probe failed!\n");
                goto out_err_mii_probe;
@@ -1552,8 +1568,6 @@ out_err_request_irq:
 out_err_mii_probe:
        mdiobus_unregister(lp->mii_bus);
        mdiobus_free(lp->mii_bus);
-out_err_mii_bus_probe:
-       peripheral_free_list(pin_req);
 out_err_probe_mac:
        platform_set_drvdata(pdev, NULL);
        free_netdev(ndev);
@@ -1576,8 +1590,6 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev)
 
        free_netdev(ndev);
 
-       peripheral_free_list(pin_req);
-
        return 0;
 }
 
@@ -1623,12 +1635,21 @@ static int bfin_mac_resume(struct platform_device *pdev)
 static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 {
        struct mii_bus *miibus;
+       struct bfin_mii_bus_platform_data *mii_bus_pd;
+       const unsigned short *pin_req;
        int rc, i;
 
+       mii_bus_pd = dev_get_platdata(&pdev->dev);
+       if (!mii_bus_pd) {
+               dev_err(&pdev->dev, "No peripherals in platform data!\n");
+               return -EINVAL;
+       }
+
        /*
         * We are setting up a network card,
         * so set the GPIO pins to Ethernet mode
         */
+       pin_req = mii_bus_pd->mac_peripherals;
        rc = peripheral_request_list(pin_req, DRV_NAME);
        if (rc) {
                dev_err(&pdev->dev, "Requesting peripherals failed!\n");
@@ -1645,13 +1666,30 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 
        miibus->parent = &pdev->dev;
        miibus->name = "bfin_mii_bus";
+       miibus->phy_mask = mii_bus_pd->phy_mask;
+
        snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
        miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-       if (miibus->irq == NULL)
-               goto out_err_alloc;
-       for (i = 0; i < PHY_MAX_ADDR; ++i)
+       if (!miibus->irq)
+               goto out_err_irq_alloc;
+
+       for (i = rc; i < PHY_MAX_ADDR; ++i)
                miibus->irq[i] = PHY_POLL;
 
+       rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
+       if (rc != mii_bus_pd->phydev_number)
+               dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n",
+                       mii_bus_pd->phydev_number);
+       for (i = 0; i < rc; ++i) {
+               unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr;
+               if (phyaddr < PHY_MAX_ADDR)
+                       miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq;
+               else
+                       dev_err(&pdev->dev,
+                               "Invalid PHY address %i for phydev %i\n",
+                               phyaddr, i);
+       }
+
        rc = mdiobus_register(miibus);
        if (rc) {
                dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
@@ -1663,6 +1701,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 
 out_err_mdiobus_register:
        kfree(miibus->irq);
+out_err_irq_alloc:
        mdiobus_free(miibus);
 out_err_alloc:
        peripheral_free_list(pin_req);
@@ -1673,11 +1712,15 @@ out_err_alloc:
 static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
 {
        struct mii_bus *miibus = platform_get_drvdata(pdev);
+       struct bfin_mii_bus_platform_data *mii_bus_pd =
+               dev_get_platdata(&pdev->dev);
+
        platform_set_drvdata(pdev, NULL);
        mdiobus_unregister(miibus);
        kfree(miibus->irq);
        mdiobus_free(miibus);
-       peripheral_free_list(pin_req);
+       peripheral_free_list(mii_bus_pd->mac_peripherals);
+
        return 0;
 }
 
index 04e4050..aed68be 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/clocksource.h>
 #include <linux/timecompare.h>
 #include <linux/timer.h>
+#include <linux/etherdevice.h>
+#include <linux/bfin_mac.h>
 
 #define BFIN_MAC_CSUM_OFFLOAD
 
diff --git a/drivers/net/davinci_cpdma.c b/drivers/net/davinci_cpdma.c
new file mode 100644 (file)
index 0000000..e92b2b6
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include "davinci_cpdma.h"
+
+/* DMA Registers */
+#define CPDMA_TXIDVER          0x00
+#define CPDMA_TXCONTROL                0x04
+#define CPDMA_TXTEARDOWN       0x08
+#define CPDMA_RXIDVER          0x10
+#define CPDMA_RXCONTROL                0x14
+#define CPDMA_SOFTRESET                0x1c
+#define CPDMA_RXTEARDOWN       0x18
+#define CPDMA_TXINTSTATRAW     0x80
+#define CPDMA_TXINTSTATMASKED  0x84
+#define CPDMA_TXINTMASKSET     0x88
+#define CPDMA_TXINTMASKCLEAR   0x8c
+#define CPDMA_MACINVECTOR      0x90
+#define CPDMA_MACEOIVECTOR     0x94
+#define CPDMA_RXINTSTATRAW     0xa0
+#define CPDMA_RXINTSTATMASKED  0xa4
+#define CPDMA_RXINTMASKSET     0xa8
+#define CPDMA_RXINTMASKCLEAR   0xac
+#define CPDMA_DMAINTSTATRAW    0xb0
+#define CPDMA_DMAINTSTATMASKED 0xb4
+#define CPDMA_DMAINTMASKSET    0xb8
+#define CPDMA_DMAINTMASKCLEAR  0xbc
+#define CPDMA_DMAINT_HOSTERR   BIT(1)
+
+/* the following exist only if has_ext_regs is set */
+#define CPDMA_DMACONTROL       0x20
+#define CPDMA_DMASTATUS                0x24
+#define CPDMA_RXBUFFOFS                0x28
+#define CPDMA_EM_CONTROL       0x2c
+
+/* Descriptor mode bits */
+#define CPDMA_DESC_SOP         BIT(31)
+#define CPDMA_DESC_EOP         BIT(30)
+#define CPDMA_DESC_OWNER       BIT(29)
+#define CPDMA_DESC_EOQ         BIT(28)
+#define CPDMA_DESC_TD_COMPLETE BIT(27)
+#define CPDMA_DESC_PASS_CRC    BIT(26)
+
+#define CPDMA_TEARDOWN_VALUE   0xfffffffc
+
+struct cpdma_desc {
+       /* hardware fields */
+       u32                     hw_next;
+       u32                     hw_buffer;
+       u32                     hw_len;
+       u32                     hw_mode;
+       /* software fields */
+       void                    *sw_token;
+       u32                     sw_buffer;
+       u32                     sw_len;
+};
+
+struct cpdma_desc_pool {
+       u32                     phys;
+       void __iomem            *iomap;         /* ioremap map */
+       void                    *cpumap;        /* dma_alloc map */
+       int                     desc_size, mem_size;
+       int                     num_desc, used_desc;
+       unsigned long           *bitmap;
+       struct device           *dev;
+       spinlock_t              lock;
+};
+
+enum cpdma_state {
+       CPDMA_STATE_IDLE,
+       CPDMA_STATE_ACTIVE,
+       CPDMA_STATE_TEARDOWN,
+};
+
+const char *cpdma_state_str[] = { "idle", "active", "teardown" };
+
+struct cpdma_ctlr {
+       enum cpdma_state        state;
+       struct cpdma_params     params;
+       struct device           *dev;
+       struct cpdma_desc_pool  *pool;
+       spinlock_t              lock;
+       struct cpdma_chan       *channels[2 * CPDMA_MAX_CHANNELS];
+};
+
+struct cpdma_chan {
+       enum cpdma_state                state;
+       struct cpdma_ctlr               *ctlr;
+       int                             chan_num;
+       spinlock_t                      lock;
+       struct cpdma_desc __iomem       *head, *tail;
+       int                             count;
+       void __iomem                    *hdp, *cp, *rxfree;
+       u32                             mask;
+       cpdma_handler_fn                handler;
+       enum dma_data_direction         dir;
+       struct cpdma_chan_stats         stats;
+       /* offsets into dmaregs */
+       int     int_set, int_clear, td;
+};
+
+/* The following make access to common cpdma_ctlr params more readable */
+#define dmaregs                params.dmaregs
+#define num_chan       params.num_chan
+
+/* various accessors */
+#define dma_reg_read(ctlr, ofs)                __raw_readl((ctlr)->dmaregs + (ofs))
+#define chan_read(chan, fld)           __raw_readl((chan)->fld)
+#define desc_read(desc, fld)           __raw_readl(&(desc)->fld)
+#define dma_reg_write(ctlr, ofs, v)    __raw_writel(v, (ctlr)->dmaregs + (ofs))
+#define chan_write(chan, fld, v)       __raw_writel(v, (chan)->fld)
+#define desc_write(desc, fld, v)       __raw_writel((u32)(v), &(desc)->fld)
+
+/*
+ * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
+ * emac) have dedicated on-chip memory for these descriptors.  Some other
+ * devices (e.g. cpsw switches) use plain old memory.  Descriptor pools
+ * abstract out these details
+ */
+static struct cpdma_desc_pool *
+cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
+{
+       int bitmap_size;
+       struct cpdma_desc_pool *pool;
+
+       pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+       if (!pool)
+               return NULL;
+
+       spin_lock_init(&pool->lock);
+
+       pool->dev       = dev;
+       pool->mem_size  = size;
+       pool->desc_size = ALIGN(sizeof(struct cpdma_desc), align);
+       pool->num_desc  = size / pool->desc_size;
+
+       bitmap_size  = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
+       pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!pool->bitmap)
+               goto fail;
+
+       if (phys) {
+               pool->phys  = phys;
+               pool->iomap = ioremap(phys, size);
+       } else {
+               pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
+                                                 GFP_KERNEL);
+               pool->iomap = (void __force __iomem *)pool->cpumap;
+       }
+
+       if (pool->iomap)
+               return pool;
+
+fail:
+       kfree(pool->bitmap);
+       kfree(pool);
+       return NULL;
+}
+
+static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
+{
+       unsigned long flags;
+
+       if (!pool)
+               return;
+
+       spin_lock_irqsave(&pool->lock, flags);
+       WARN_ON(pool->used_desc);
+       kfree(pool->bitmap);
+       if (pool->cpumap) {
+               dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
+                                 pool->phys);
+       } else {
+               iounmap(pool->iomap);
+       }
+       spin_unlock_irqrestore(&pool->lock, flags);
+       kfree(pool);
+}
+
+static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
+                 struct cpdma_desc __iomem *desc)
+{
+       if (!desc)
+               return 0;
+       return pool->phys + (__force dma_addr_t)desc -
+                           (__force dma_addr_t)pool->iomap;
+}
+
+static inline struct cpdma_desc __iomem *
+desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
+{
+       return dma ? pool->iomap + dma - pool->phys : NULL;
+}
+
+static struct cpdma_desc __iomem *
+cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
+{
+       unsigned long flags;
+       int index;
+       struct cpdma_desc __iomem *desc = NULL;
+
+       spin_lock_irqsave(&pool->lock, flags);
+
+       index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
+                                          num_desc, 0);
+       if (index < pool->num_desc) {
+               bitmap_set(pool->bitmap, index, num_desc);
+               desc = pool->iomap + pool->desc_size * index;
+               pool->used_desc++;
+       }
+
+       spin_unlock_irqrestore(&pool->lock, flags);
+       return desc;
+}
+
+static void cpdma_desc_free(struct cpdma_desc_pool *pool,
+                           struct cpdma_desc __iomem *desc, int num_desc)
+{
+       unsigned long flags, index;
+
+       index = ((unsigned long)desc - (unsigned long)pool->iomap) /
+               pool->desc_size;
+       spin_lock_irqsave(&pool->lock, flags);
+       bitmap_clear(pool->bitmap, index, num_desc);
+       pool->used_desc--;
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
+{
+       struct cpdma_ctlr *ctlr;
+
+       ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
+       if (!ctlr)
+               return NULL;
+
+       ctlr->state = CPDMA_STATE_IDLE;
+       ctlr->params = *params;
+       ctlr->dev = params->dev;
+       spin_lock_init(&ctlr->lock);
+
+       ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
+                                           ctlr->params.desc_mem_phys,
+                                           ctlr->params.desc_mem_size,
+                                           ctlr->params.desc_align);
+       if (!ctlr->pool) {
+               kfree(ctlr);
+               return NULL;
+       }
+
+       if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
+               ctlr->num_chan = CPDMA_MAX_CHANNELS;
+       return ctlr;
+}
+
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       if (ctlr->state != CPDMA_STATE_IDLE) {
+               spin_unlock_irqrestore(&ctlr->lock, flags);
+               return -EBUSY;
+       }
+
+       if (ctlr->params.has_soft_reset) {
+               unsigned long timeout = jiffies + HZ/10;
+
+               dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
+               while (time_before(jiffies, timeout)) {
+                       if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
+                               break;
+               }
+               WARN_ON(!time_before(jiffies, timeout));
+       }
+
+       for (i = 0; i < ctlr->num_chan; i++) {
+               __raw_writel(0, ctlr->params.txhdp + 4 * i);
+               __raw_writel(0, ctlr->params.rxhdp + 4 * i);
+               __raw_writel(0, ctlr->params.txcp + 4 * i);
+               __raw_writel(0, ctlr->params.rxcp + 4 * i);
+       }
+
+       dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+       dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+       dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
+       dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
+
+       ctlr->state = CPDMA_STATE_ACTIVE;
+
+       for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+               if (ctlr->channels[i])
+                       cpdma_chan_start(ctlr->channels[i]);
+       }
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return 0;
+}
+
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       if (ctlr->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&ctlr->lock, flags);
+               return -EINVAL;
+       }
+
+       ctlr->state = CPDMA_STATE_TEARDOWN;
+
+       for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+               if (ctlr->channels[i])
+                       cpdma_chan_stop(ctlr->channels[i]);
+       }
+
+       dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+       dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+       dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
+       dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
+
+       ctlr->state = CPDMA_STATE_IDLE;
+
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return 0;
+}
+
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
+{
+       struct device *dev = ctlr->dev;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+
+       dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
+
+       dev_info(dev, "CPDMA: txidver: %x",
+                dma_reg_read(ctlr, CPDMA_TXIDVER));
+       dev_info(dev, "CPDMA: txcontrol: %x",
+                dma_reg_read(ctlr, CPDMA_TXCONTROL));
+       dev_info(dev, "CPDMA: txteardown: %x",
+                dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
+       dev_info(dev, "CPDMA: rxidver: %x",
+                dma_reg_read(ctlr, CPDMA_RXIDVER));
+       dev_info(dev, "CPDMA: rxcontrol: %x",
+                dma_reg_read(ctlr, CPDMA_RXCONTROL));
+       dev_info(dev, "CPDMA: softreset: %x",
+                dma_reg_read(ctlr, CPDMA_SOFTRESET));
+       dev_info(dev, "CPDMA: rxteardown: %x",
+                dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
+       dev_info(dev, "CPDMA: txintstatraw: %x",
+                dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
+       dev_info(dev, "CPDMA: txintstatmasked: %x",
+                dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
+       dev_info(dev, "CPDMA: txintmaskset: %x",
+                dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
+       dev_info(dev, "CPDMA: txintmaskclear: %x",
+                dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
+       dev_info(dev, "CPDMA: macinvector: %x",
+                dma_reg_read(ctlr, CPDMA_MACINVECTOR));
+       dev_info(dev, "CPDMA: maceoivector: %x",
+                dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
+       dev_info(dev, "CPDMA: rxintstatraw: %x",
+                dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
+       dev_info(dev, "CPDMA: rxintstatmasked: %x",
+                dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
+       dev_info(dev, "CPDMA: rxintmaskset: %x",
+                dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
+       dev_info(dev, "CPDMA: rxintmaskclear: %x",
+                dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
+       dev_info(dev, "CPDMA: dmaintstatraw: %x",
+                dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
+       dev_info(dev, "CPDMA: dmaintstatmasked: %x",
+                dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
+       dev_info(dev, "CPDMA: dmaintmaskset: %x",
+                dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
+       dev_info(dev, "CPDMA: dmaintmaskclear: %x",
+                dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
+
+       if (!ctlr->params.has_ext_regs) {
+               dev_info(dev, "CPDMA: dmacontrol: %x",
+                        dma_reg_read(ctlr, CPDMA_DMACONTROL));
+               dev_info(dev, "CPDMA: dmastatus: %x",
+                        dma_reg_read(ctlr, CPDMA_DMASTATUS));
+               dev_info(dev, "CPDMA: rxbuffofs: %x",
+                        dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
+       }
+
+       for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
+               if (ctlr->channels[i])
+                       cpdma_chan_dump(ctlr->channels[i]);
+
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return 0;
+}
+
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
+{
+       unsigned long flags;
+       int ret = 0, i;
+
+       if (!ctlr)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       if (ctlr->state != CPDMA_STATE_IDLE)
+               cpdma_ctlr_stop(ctlr);
+
+       for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+               if (ctlr->channels[i])
+                       cpdma_chan_destroy(ctlr->channels[i]);
+       }
+
+       cpdma_desc_pool_destroy(ctlr->pool);
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       kfree(ctlr);
+       return ret;
+}
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
+{
+       unsigned long flags;
+       int i, reg;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       if (ctlr->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&ctlr->lock, flags);
+               return -EINVAL;
+       }
+
+       reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
+       dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
+
+       for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+               if (ctlr->channels[i])
+                       cpdma_chan_int_ctrl(ctlr->channels[i], enable);
+       }
+
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return 0;
+}
+
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
+{
+       dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
+}
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+                                    cpdma_handler_fn handler)
+{
+       struct cpdma_chan *chan;
+       int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
+       unsigned long flags;
+
+       if (__chan_linear(chan_num) >= ctlr->num_chan)
+               return NULL;
+
+       ret = -ENOMEM;
+       chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+       if (!chan)
+               goto err_chan_alloc;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       ret = -EBUSY;
+       if (ctlr->channels[chan_num])
+               goto err_chan_busy;
+
+       chan->ctlr      = ctlr;
+       chan->state     = CPDMA_STATE_IDLE;
+       chan->chan_num  = chan_num;
+       chan->handler   = handler;
+
+       if (is_rx_chan(chan)) {
+               chan->hdp       = ctlr->params.rxhdp + offset;
+               chan->cp        = ctlr->params.rxcp + offset;
+               chan->rxfree    = ctlr->params.rxfree + offset;
+               chan->int_set   = CPDMA_RXINTMASKSET;
+               chan->int_clear = CPDMA_RXINTMASKCLEAR;
+               chan->td        = CPDMA_RXTEARDOWN;
+               chan->dir       = DMA_FROM_DEVICE;
+       } else {
+               chan->hdp       = ctlr->params.txhdp + offset;
+               chan->cp        = ctlr->params.txcp + offset;
+               chan->int_set   = CPDMA_TXINTMASKSET;
+               chan->int_clear = CPDMA_TXINTMASKCLEAR;
+               chan->td        = CPDMA_TXTEARDOWN;
+               chan->dir       = DMA_TO_DEVICE;
+       }
+       chan->mask = BIT(chan_linear(chan));
+
+       spin_lock_init(&chan->lock);
+
+       ctlr->channels[chan_num] = chan;
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return chan;
+
+err_chan_busy:
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       kfree(chan);
+err_chan_alloc:
+       return ERR_PTR(ret);
+}
+
+int cpdma_chan_destroy(struct cpdma_chan *chan)
+{
+       struct cpdma_ctlr *ctlr = chan->ctlr;
+       unsigned long flags;
+
+       if (!chan)
+               return -EINVAL;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+       if (chan->state != CPDMA_STATE_IDLE)
+               cpdma_chan_stop(chan);
+       ctlr->channels[chan->chan_num] = NULL;
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       kfree(chan);
+       return 0;
+}
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+                        struct cpdma_chan_stats *stats)
+{
+       unsigned long flags;
+       if (!chan)
+               return -EINVAL;
+       spin_lock_irqsave(&chan->lock, flags);
+       memcpy(stats, &chan->stats, sizeof(*stats));
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return 0;
+}
+
+int cpdma_chan_dump(struct cpdma_chan *chan)
+{
+       unsigned long flags;
+       struct device *dev = chan->ctlr->dev;
+
+       spin_lock_irqsave(&chan->lock, flags);
+
+       dev_info(dev, "channel %d (%s %d) state %s",
+                chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
+                chan_linear(chan), cpdma_state_str[chan->state]);
+       dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
+       dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
+       if (chan->rxfree) {
+               dev_info(dev, "\trxfree: %x\n",
+                        chan_read(chan, rxfree));
+       }
+
+       dev_info(dev, "\tstats head_enqueue: %d\n",
+                chan->stats.head_enqueue);
+       dev_info(dev, "\tstats tail_enqueue: %d\n",
+                chan->stats.tail_enqueue);
+       dev_info(dev, "\tstats pad_enqueue: %d\n",
+                chan->stats.pad_enqueue);
+       dev_info(dev, "\tstats misqueued: %d\n",
+                chan->stats.misqueued);
+       dev_info(dev, "\tstats desc_alloc_fail: %d\n",
+                chan->stats.desc_alloc_fail);
+       dev_info(dev, "\tstats pad_alloc_fail: %d\n",
+                chan->stats.pad_alloc_fail);
+       dev_info(dev, "\tstats runt_receive_buff: %d\n",
+                chan->stats.runt_receive_buff);
+       dev_info(dev, "\tstats runt_transmit_buff: %d\n",
+                chan->stats.runt_transmit_buff);
+       dev_info(dev, "\tstats empty_dequeue: %d\n",
+                chan->stats.empty_dequeue);
+       dev_info(dev, "\tstats busy_dequeue: %d\n",
+                chan->stats.busy_dequeue);
+       dev_info(dev, "\tstats good_dequeue: %d\n",
+                chan->stats.good_dequeue);
+       dev_info(dev, "\tstats requeue: %d\n",
+                chan->stats.requeue);
+       dev_info(dev, "\tstats teardown_dequeue: %d\n",
+                chan->stats.teardown_dequeue);
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return 0;
+}
+
+static void __cpdma_chan_submit(struct cpdma_chan *chan,
+                               struct cpdma_desc __iomem *desc)
+{
+       struct cpdma_ctlr               *ctlr = chan->ctlr;
+       struct cpdma_desc __iomem       *prev = chan->tail;
+       struct cpdma_desc_pool          *pool = ctlr->pool;
+       dma_addr_t                      desc_dma;
+       u32                             mode;
+
+       desc_dma = desc_phys(pool, desc);
+
+       /* simple case - idle channel */
+       if (!chan->head) {
+               chan->stats.head_enqueue++;
+               chan->head = desc;
+               chan->tail = desc;
+               if (chan->state == CPDMA_STATE_ACTIVE)
+                       chan_write(chan, hdp, desc_dma);
+               return;
+       }
+
+       /* first chain the descriptor at the tail of the list */
+       desc_write(prev, hw_next, desc_dma);
+       chan->tail = desc;
+       chan->stats.tail_enqueue++;
+
+       /* next check if EOQ has been triggered already */
+       mode = desc_read(prev, hw_mode);
+       if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
+           (chan->state == CPDMA_STATE_ACTIVE)) {
+               desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
+               chan_write(chan, hdp, desc_dma);
+               chan->stats.misqueued++;
+       }
+}
+
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+                     int len, gfp_t gfp_mask)
+{
+       struct cpdma_ctlr               *ctlr = chan->ctlr;
+       struct cpdma_desc __iomem       *desc;
+       dma_addr_t                      buffer;
+       unsigned long                   flags;
+       u32                             mode;
+       int                             ret = 0;
+
+       spin_lock_irqsave(&chan->lock, flags);
+
+       if (chan->state == CPDMA_STATE_TEARDOWN) {
+               ret = -EINVAL;
+               goto unlock_ret;
+       }
+
+       desc = cpdma_desc_alloc(ctlr->pool, 1);
+       if (!desc) {
+               chan->stats.desc_alloc_fail++;
+               ret = -ENOMEM;
+               goto unlock_ret;
+       }
+
+       if (len < ctlr->params.min_packet_size) {
+               len = ctlr->params.min_packet_size;
+               chan->stats.runt_transmit_buff++;
+       }
+
+       buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
+       mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+
+       desc_write(desc, hw_next,   0);
+       desc_write(desc, hw_buffer, buffer);
+       desc_write(desc, hw_len,    len);
+       desc_write(desc, hw_mode,   mode | len);
+       desc_write(desc, sw_token,  token);
+       desc_write(desc, sw_buffer, buffer);
+       desc_write(desc, sw_len,    len);
+
+       __cpdma_chan_submit(chan, desc);
+
+       if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
+               chan_write(chan, rxfree, 1);
+
+       chan->count++;
+
+unlock_ret:
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return ret;
+}
+
+static void __cpdma_chan_free(struct cpdma_chan *chan,
+                             struct cpdma_desc __iomem *desc,
+                             int outlen, int status)
+{
+       struct cpdma_ctlr               *ctlr = chan->ctlr;
+       struct cpdma_desc_pool          *pool = ctlr->pool;
+       dma_addr_t                      buff_dma;
+       int                             origlen;
+       void                            *token;
+
+       token      = (void *)desc_read(desc, sw_token);
+       buff_dma   = desc_read(desc, sw_buffer);
+       origlen    = desc_read(desc, sw_len);
+
+       dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
+       cpdma_desc_free(pool, desc, 1);
+       (*chan->handler)(token, outlen, status);
+}
+
+static int __cpdma_chan_process(struct cpdma_chan *chan)
+{
+       struct cpdma_ctlr               *ctlr = chan->ctlr;
+       struct cpdma_desc __iomem       *desc;
+       int                             status, outlen;
+       struct cpdma_desc_pool          *pool = ctlr->pool;
+       dma_addr_t                      desc_dma;
+       unsigned long                   flags;
+
+       spin_lock_irqsave(&chan->lock, flags);
+
+       desc = chan->head;
+       if (!desc) {
+               chan->stats.empty_dequeue++;
+               status = -ENOENT;
+               goto unlock_ret;
+       }
+       desc_dma = desc_phys(pool, desc);
+
+       status  = __raw_readl(&desc->hw_mode);
+       outlen  = status & 0x7ff;
+       if (status & CPDMA_DESC_OWNER) {
+               chan->stats.busy_dequeue++;
+               status = -EBUSY;
+               goto unlock_ret;
+       }
+       status  = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+
+       chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
+       chan_write(chan, cp, desc_dma);
+       chan->count--;
+       chan->stats.good_dequeue++;
+
+       if (status & CPDMA_DESC_EOQ) {
+               chan->stats.requeue++;
+               chan_write(chan, hdp, desc_phys(pool, chan->head));
+       }
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+
+       __cpdma_chan_free(chan, desc, outlen, status);
+       return status;
+
+unlock_ret:
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return status;
+}
+
+int cpdma_chan_process(struct cpdma_chan *chan, int quota)
+{
+       int used = 0, ret = 0;
+
+       if (chan->state != CPDMA_STATE_ACTIVE)
+               return -EINVAL;
+
+       while (used < quota) {
+               ret = __cpdma_chan_process(chan);
+               if (ret < 0)
+                       break;
+               used++;
+       }
+       return used;
+}
+
+int cpdma_chan_start(struct cpdma_chan *chan)
+{
+       struct cpdma_ctlr       *ctlr = chan->ctlr;
+       struct cpdma_desc_pool  *pool = ctlr->pool;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       if (chan->state != CPDMA_STATE_IDLE) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EBUSY;
+       }
+       if (ctlr->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EINVAL;
+       }
+       dma_reg_write(ctlr, chan->int_set, chan->mask);
+       chan->state = CPDMA_STATE_ACTIVE;
+       if (chan->head) {
+               chan_write(chan, hdp, desc_phys(pool, chan->head));
+               if (chan->rxfree)
+                       chan_write(chan, rxfree, chan->count);
+       }
+
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return 0;
+}
+
+int cpdma_chan_stop(struct cpdma_chan *chan)
+{
+       struct cpdma_ctlr       *ctlr = chan->ctlr;
+       struct cpdma_desc_pool  *pool = ctlr->pool;
+       unsigned long           flags;
+       int                     ret;
+       unsigned long           timeout;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       if (chan->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EINVAL;
+       }
+
+       chan->state = CPDMA_STATE_TEARDOWN;
+       dma_reg_write(ctlr, chan->int_clear, chan->mask);
+
+       /* trigger teardown */
+       dma_reg_write(ctlr, chan->td, chan->chan_num);
+
+       /* wait for teardown complete */
+       timeout = jiffies + HZ/10;      /* 100 msec */
+       while (time_before(jiffies, timeout)) {
+               u32 cp = chan_read(chan, cp);
+               if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
+                       break;
+               cpu_relax();
+       }
+       WARN_ON(!time_before(jiffies, timeout));
+       chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
+
+       /* handle completed packets */
+       do {
+               ret = __cpdma_chan_process(chan);
+               if (ret < 0)
+                       break;
+       } while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
+
+       /* remaining packets haven't been tx/rx'ed, clean them up */
+       while (chan->head) {
+               struct cpdma_desc __iomem *desc = chan->head;
+               dma_addr_t next_dma;
+
+               next_dma = desc_read(desc, hw_next);
+               chan->head = desc_from_phys(pool, next_dma);
+               chan->stats.teardown_dequeue++;
+
+               /* issue callback without locks held */
+               spin_unlock_irqrestore(&chan->lock, flags);
+               __cpdma_chan_free(chan, desc, 0, -ENOSYS);
+               spin_lock_irqsave(&chan->lock, flags);
+       }
+
+       chan->state = CPDMA_STATE_IDLE;
+       spin_unlock_irqrestore(&chan->lock, flags);
+       return 0;
+}
+
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&chan->lock, flags);
+       if (chan->state != CPDMA_STATE_ACTIVE) {
+               spin_unlock_irqrestore(&chan->lock, flags);
+               return -EINVAL;
+       }
+
+       dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
+                     chan->mask);
+       spin_unlock_irqrestore(&chan->lock, flags);
+
+       return 0;
+}
+
+struct cpdma_control_info {
+       u32             reg;
+       u32             shift, mask;
+       int             access;
+#define ACCESS_RO      BIT(0)
+#define ACCESS_WO      BIT(1)
+#define ACCESS_RW      (ACCESS_RO | ACCESS_WO)
+};
+
+struct cpdma_control_info controls[] = {
+       [CPDMA_CMD_IDLE]          = {CPDMA_DMACONTROL,  3,  1,      ACCESS_WO},
+       [CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL,  4,  1,      ACCESS_RW},
+       [CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL,  2,  1,      ACCESS_RW},
+       [CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL,  1,  1,      ACCESS_RW},
+       [CPDMA_TX_PRIO_FIXED]     = {CPDMA_DMACONTROL,  0,  1,      ACCESS_RW},
+       [CPDMA_STAT_IDLE]         = {CPDMA_DMASTATUS,   31, 1,      ACCESS_RO},
+       [CPDMA_STAT_TX_ERR_CODE]  = {CPDMA_DMASTATUS,   20, 0xf,    ACCESS_RW},
+       [CPDMA_STAT_TX_ERR_CHAN]  = {CPDMA_DMASTATUS,   16, 0x7,    ACCESS_RW},
+       [CPDMA_STAT_RX_ERR_CODE]  = {CPDMA_DMASTATUS,   12, 0xf,    ACCESS_RW},
+       [CPDMA_STAT_RX_ERR_CHAN]  = {CPDMA_DMASTATUS,   8,  0x7,    ACCESS_RW},
+       [CPDMA_RX_BUFFER_OFFSET]  = {CPDMA_RXBUFFOFS,   0,  0xffff, ACCESS_RW},
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
+{
+       unsigned long flags;
+       struct cpdma_control_info *info = &controls[control];
+       int ret;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+
+       ret = -ENOTSUPP;
+       if (!ctlr->params.has_ext_regs)
+               goto unlock_ret;
+
+       ret = -EINVAL;
+       if (ctlr->state != CPDMA_STATE_ACTIVE)
+               goto unlock_ret;
+
+       ret = -ENOENT;
+       if (control < 0 || control >= ARRAY_SIZE(controls))
+               goto unlock_ret;
+
+       ret = -EPERM;
+       if ((info->access & ACCESS_RO) != ACCESS_RO)
+               goto unlock_ret;
+
+       ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
+
+unlock_ret:
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return ret;
+}
+
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
+{
+       unsigned long flags;
+       struct cpdma_control_info *info = &controls[control];
+       int ret;
+       u32 val;
+
+       spin_lock_irqsave(&ctlr->lock, flags);
+
+       ret = -ENOTSUPP;
+       if (!ctlr->params.has_ext_regs)
+               goto unlock_ret;
+
+       ret = -EINVAL;
+       if (ctlr->state != CPDMA_STATE_ACTIVE)
+               goto unlock_ret;
+
+       ret = -ENOENT;
+       if (control < 0 || control >= ARRAY_SIZE(controls))
+               goto unlock_ret;
+
+       ret = -EPERM;
+       if ((info->access & ACCESS_WO) != ACCESS_WO)
+               goto unlock_ret;
+
+       val  = dma_reg_read(ctlr, info->reg);
+       val &= ~(info->mask << info->shift);
+       val |= (value & info->mask) << info->shift;
+       dma_reg_write(ctlr, info->reg, val);
+       ret = 0;
+
+unlock_ret:
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+       return ret;
+}
diff --git a/drivers/net/davinci_cpdma.h b/drivers/net/davinci_cpdma.h
new file mode 100644 (file)
index 0000000..868e50e
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DAVINCI_CPDMA_H__
+#define __DAVINCI_CPDMA_H__
+
+#define CPDMA_MAX_CHANNELS     BITS_PER_LONG
+
+#define tx_chan_num(chan)      (chan)
+#define rx_chan_num(chan)      ((chan) + CPDMA_MAX_CHANNELS)
+#define is_rx_chan(chan)       ((chan)->chan_num >= CPDMA_MAX_CHANNELS)
+#define is_tx_chan(chan)       (!is_rx_chan(chan))
+#define __chan_linear(chan_num)        ((chan_num) & (CPDMA_MAX_CHANNELS - 1))
+#define chan_linear(chan)      __chan_linear((chan)->chan_num)
+
+struct cpdma_params {
+       struct device           *dev;
+       void __iomem            *dmaregs;
+       void __iomem            *txhdp, *rxhdp, *txcp, *rxcp;
+       void __iomem            *rxthresh, *rxfree;
+       int                     num_chan;
+       bool                    has_soft_reset;
+       int                     min_packet_size;
+       u32                     desc_mem_phys;
+       int                     desc_mem_size;
+       int                     desc_align;
+
+       /*
+        * Some instances of embedded cpdma controllers have extra control and
+        * status registers.  The following flag enables access to these
+        * "extended" registers.
+        */
+       bool                    has_ext_regs;
+};
+
+struct cpdma_chan_stats {
+       u32                     head_enqueue;
+       u32                     tail_enqueue;
+       u32                     pad_enqueue;
+       u32                     misqueued;
+       u32                     desc_alloc_fail;
+       u32                     pad_alloc_fail;
+       u32                     runt_receive_buff;
+       u32                     runt_transmit_buff;
+       u32                     empty_dequeue;
+       u32                     busy_dequeue;
+       u32                     good_dequeue;
+       u32                     requeue;
+       u32                     teardown_dequeue;
+};
+
+struct cpdma_ctlr;
+struct cpdma_chan;
+
+typedef void (*cpdma_handler_fn)(void *token, int len, int status);
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+                                    cpdma_handler_fn handler);
+int cpdma_chan_destroy(struct cpdma_chan *chan);
+int cpdma_chan_start(struct cpdma_chan *chan);
+int cpdma_chan_stop(struct cpdma_chan *chan);
+int cpdma_chan_dump(struct cpdma_chan *chan);
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+                        struct cpdma_chan_stats *stats);
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+                     int len, gfp_t gfp_mask);
+int cpdma_chan_process(struct cpdma_chan *chan, int quota);
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
+
+enum cpdma_control {
+       CPDMA_CMD_IDLE,                 /* write-only */
+       CPDMA_COPY_ERROR_FRAMES,        /* read-write */
+       CPDMA_RX_OFF_LEN_UPDATE,        /* read-write */
+       CPDMA_RX_OWNERSHIP_FLIP,        /* read-write */
+       CPDMA_TX_PRIO_FIXED,            /* read-write */
+       CPDMA_STAT_IDLE,                /* read-only */
+       CPDMA_STAT_TX_ERR_CHAN,         /* read-only */
+       CPDMA_STAT_TX_ERR_CODE,         /* read-only */
+       CPDMA_STAT_RX_ERR_CHAN,         /* read-only */
+       CPDMA_STAT_RX_ERR_CODE,         /* read-only */
+       CPDMA_RX_BUFFER_OFFSET,         /* read-write */
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control);
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value);
+
+#endif
index 7fbd052..2a628d1 100644 (file)
@@ -63,6 +63,8 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 
+#include "davinci_cpdma.h"
+
 static int debug_level;
 module_param(debug_level, int, 0);
 MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
@@ -113,7 +115,7 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_FRAME_SIZE                (1500 + 14 + 4 + 4)
 #define EMAC_DEF_TX_CH                 (0) /* Default 0th channel */
 #define EMAC_DEF_RX_CH                 (0) /* Default 0th channel */
-#define EMAC_DEF_MDIO_TICK_MS          (10) /* typically 1 tick=1 ms) */
+#define EMAC_DEF_RX_NUM_DESC           (128)
 #define EMAC_DEF_MAX_TX_CH             (1) /* Max TX channels configured */
 #define EMAC_DEF_MAX_RX_CH             (1) /* Max RX channels configured */
 #define EMAC_POLL_WEIGHT               (64) /* Default NAPI poll weight */
@@ -125,7 +127,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC register related defines */
 #define EMAC_ALL_MULTI_REG_VALUE       (0xFFFFFFFF)
 #define EMAC_NUM_MULTICAST_BITS                (64)
-#define EMAC_TEARDOWN_VALUE            (0xFFFFFFFC)
 #define EMAC_TX_CONTROL_TX_ENABLE_VAL  (0x1)
 #define EMAC_RX_CONTROL_RX_ENABLE_VAL  (0x1)
 #define EMAC_MAC_HOST_ERR_INTMASK_VAL  (0x2)
@@ -212,24 +213,10 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DEF_MAX_MULTICAST_ADDRESSES (64) /* Max mcast addr's */
 
 /* EMAC Peripheral Device Register Memory Layout structure */
-#define EMAC_TXIDVER           0x0
-#define EMAC_TXCONTROL         0x4
-#define EMAC_TXTEARDOWN                0x8
-#define EMAC_RXIDVER           0x10
-#define EMAC_RXCONTROL         0x14
-#define EMAC_RXTEARDOWN                0x18
-#define EMAC_TXINTSTATRAW      0x80
-#define EMAC_TXINTSTATMASKED   0x84
-#define EMAC_TXINTMASKSET      0x88
-#define EMAC_TXINTMASKCLEAR    0x8C
 #define EMAC_MACINVECTOR       0x90
 
 #define EMAC_DM646X_MACEOIVECTOR       0x94
 
-#define EMAC_RXINTSTATRAW      0xA0
-#define EMAC_RXINTSTATMASKED   0xA4
-#define EMAC_RXINTMASKSET      0xA8
-#define EMAC_RXINTMASKCLEAR    0xAC
 #define EMAC_MACINTSTATRAW     0xB0
 #define EMAC_MACINTSTATMASKED  0xB4
 #define EMAC_MACINTMASKSET     0xB8
@@ -256,12 +243,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_MACADDRHI         0x504
 #define EMAC_MACINDEX          0x508
 
-/* EMAC HDP and Completion registors */
-#define EMAC_TXHDP(ch)         (0x600 + (ch * 4))
-#define EMAC_RXHDP(ch)         (0x620 + (ch * 4))
-#define EMAC_TXCP(ch)          (0x640 + (ch * 4))
-#define EMAC_RXCP(ch)          (0x660 + (ch * 4))
-
 /* EMAC statistics registers */
 #define EMAC_RXGOODFRAMES      0x200
 #define EMAC_RXBCASTFRAMES     0x204
@@ -303,25 +284,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 #define EMAC_DM644X_INTMIN_INTVL       0x1
 #define EMAC_DM644X_INTMAX_INTVL       (EMAC_DM644X_EWINTCNT_MASK)
 
-/* EMAC MDIO related */
-/* Mask & Control defines */
-#define MDIO_CONTROL_CLKDIV    (0xFF)
-#define MDIO_CONTROL_ENABLE    BIT(30)
-#define MDIO_USERACCESS_GO     BIT(31)
-#define MDIO_USERACCESS_WRITE  BIT(30)
-#define MDIO_USERACCESS_READ   (0)
-#define MDIO_USERACCESS_REGADR (0x1F << 21)
-#define MDIO_USERACCESS_PHYADR (0x1F << 16)
-#define MDIO_USERACCESS_DATA   (0xFFFF)
-#define MDIO_USERPHYSEL_LINKSEL        BIT(7)
-#define MDIO_VER_MODID         (0xFFFF << 16)
-#define MDIO_VER_REVMAJ                (0xFF   << 8)
-#define MDIO_VER_REVMIN                (0xFF)
-
-#define MDIO_USERACCESS(inst)  (0x80 + (inst * 8))
-#define MDIO_USERPHYSEL(inst)  (0x84 + (inst * 8))
-#define MDIO_CONTROL           (0x04)
-
 /* EMAC DM646X control module registers */
 #define EMAC_DM646X_CMINTCTRL  0x0C
 #define EMAC_DM646X_CMRXINTEN  0x14
@@ -345,120 +307,6 @@ static const char emac_version_string[] = "TI DaVinci EMAC Linux v6.1";
 /* EMAC Stats Clear Mask */
 #define EMAC_STATS_CLR_MASK    (0xFFFFFFFF)
 
-/** net_buf_obj: EMAC network bufferdata structure
- *
- * EMAC network buffer data structure
- */
-struct emac_netbufobj {
-       void *buf_token;
-       char *data_ptr;
-       int length;
-};
-
-/** net_pkt_obj: EMAC network packet data structure
- *
- * EMAC network packet data structure - supports buffer list (for future)
- */
-struct emac_netpktobj {
-       void *pkt_token; /* data token may hold tx/rx chan id */
-       struct emac_netbufobj *buf_list; /* array of network buffer objects */
-       int num_bufs;
-       int pkt_length;
-};
-
-/** emac_tx_bd: EMAC TX Buffer descriptor data structure
- *
- * EMAC TX Buffer descriptor data structure
- */
-struct emac_tx_bd {
-       int h_next;
-       int buff_ptr;
-       int off_b_len;
-       int mode; /* SOP, EOP, ownership, EOQ, teardown,Qstarv, length */
-       struct emac_tx_bd __iomem *next;
-       void *buf_token;
-};
-
-/** emac_txch: EMAC TX Channel data structure
- *
- * EMAC TX Channel data structure
- */
-struct emac_txch {
-       /* Config related */
-       u32 num_bd;
-       u32 service_max;
-
-       /* CPPI specific */
-       u32 alloc_size;
-       void __iomem *bd_mem;
-       struct emac_tx_bd __iomem *bd_pool_head;
-       struct emac_tx_bd __iomem *active_queue_head;
-       struct emac_tx_bd __iomem *active_queue_tail;
-       struct emac_tx_bd __iomem *last_hw_bdprocessed;
-       u32 queue_active;
-       u32 teardown_pending;
-       u32 *tx_complete;
-
-       /** statistics */
-       u32 proc_count;     /* TX: # of times emac_tx_bdproc is called */
-       u32 mis_queued_packets;
-       u32 queue_reinit;
-       u32 end_of_queue_add;
-       u32 out_of_tx_bd;
-       u32 no_active_pkts; /* IRQ when there were no packets to process */
-       u32 active_queue_count;
-};
-
-/** emac_rx_bd: EMAC RX Buffer descriptor data structure
- *
- * EMAC RX Buffer descriptor data structure
- */
-struct emac_rx_bd {
-       int h_next;
-       int buff_ptr;
-       int off_b_len;
-       int mode;
-       struct emac_rx_bd __iomem *next;
-       void *data_ptr;
-       void *buf_token;
-};
-
-/** emac_rxch: EMAC RX Channel data structure
- *
- * EMAC RX Channel data structure
- */
-struct emac_rxch {
-       /* configuration info */
-       u32 num_bd;
-       u32 service_max;
-       u32 buf_size;
-       char mac_addr[6];
-
-       /** CPPI specific */
-       u32 alloc_size;
-       void __iomem *bd_mem;
-       struct emac_rx_bd __iomem *bd_pool_head;
-       struct emac_rx_bd __iomem *active_queue_head;
-       struct emac_rx_bd __iomem *active_queue_tail;
-       u32 queue_active;
-       u32 teardown_pending;
-
-       /* packet and buffer objects */
-       struct emac_netpktobj pkt_queue;
-       struct emac_netbufobj buf_queue;
-
-       /** statistics */
-       u32 proc_count; /* number of times emac_rx_bdproc is called */
-       u32 processed_bd;
-       u32 recycled_bd;
-       u32 out_of_rx_bd;
-       u32 out_of_rx_buffers;
-       u32 queue_reinit;
-       u32 end_of_queue_add;
-       u32 end_of_queue;
-       u32 mis_queued_packets;
-};
-
 /* emac_priv: EMAC private data structure
  *
  * EMAC adapter private data structure
@@ -469,17 +317,13 @@ struct emac_priv {
        struct platform_device *pdev;
        struct napi_struct napi;
        char mac_addr[6];
-       spinlock_t tx_lock;
-       spinlock_t rx_lock;
        void __iomem *remap_addr;
        u32 emac_base_phys;
        void __iomem *emac_base;
        void __iomem *ctrl_base;
-       void __iomem *emac_ctrl_ram;
-       u32 ctrl_ram_size;
-       u32 hw_ram_addr;
-       struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
-       struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
+       struct cpdma_ctlr *dma;
+       struct cpdma_chan *txchan;
+       struct cpdma_chan *rxchan;
        u32 link; /* 1=link on, 0=link off */
        u32 speed; /* 0=Auto Neg, 1=No PHY, 10,100, 1000 - mbps */
        u32 duplex; /* Link duplex: 0=Half, 1=Full */
@@ -493,13 +337,7 @@ struct emac_priv {
        u32 mac_hash2;
        u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
        u32 rx_addr_type;
-       /* periodic timer required for MDIO polling */
-       struct timer_list periodic_timer;
-       u32 periodic_ticks;
-       u32 timer_active;
-       u32 phy_mask;
-       /* mii_bus,phy members */
-       struct mii_bus *mii_bus;
+       const char *phy_id;
        struct phy_device *phydev;
        spinlock_t lock;
        /*platform specific members*/
@@ -510,19 +348,6 @@ struct emac_priv {
 /* clock frequency for EMAC */
 static struct clk *emac_clk;
 static unsigned long emac_bus_frequency;
-static unsigned long mdio_max_freq;
-
-#define emac_virt_to_phys(addr, priv) \
-       (((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
-       + priv->hw_ram_addr)
-
-/* Cache macros - Packet buffers would be from skb pool which is cached */
-#define EMAC_VIRT_NOCACHE(addr) (addr)
-
-/* DM644x does not have BD's in cached memory - so no cache functions */
-#define BD_CACHE_INVALIDATE(addr, size)
-#define BD_CACHE_WRITEBACK(addr, size)
-#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size)
 
 /* EMAC TX Host Error description strings */
 static char *emac_txhost_errcodes[16] = {
@@ -548,9 +373,6 @@ static char *emac_rxhost_errcodes[16] = {
 #define emac_ctrl_read(reg)      ioread32((priv->ctrl_base + (reg)))
 #define emac_ctrl_write(reg, val) iowrite32(val, (priv->ctrl_base + (reg)))
 
-#define emac_mdio_read(reg)      ioread32(bus->priv + (reg))
-#define emac_mdio_write(reg, val) iowrite32(val, (bus->priv + (reg)))
-
 /**
  * emac_dump_regs: Dump important EMAC registers to debug terminal
  * @priv: The DaVinci EMAC private adapter structure
@@ -569,20 +391,6 @@ static void emac_dump_regs(struct emac_priv *priv)
                        emac_ctrl_read(EMAC_CTRL_EWCTL),
                        emac_ctrl_read(EMAC_CTRL_EWINTTCNT));
        }
-       dev_info(emac_dev, "EMAC: TXID: %08X %s, RXID: %08X %s\n",
-               emac_read(EMAC_TXIDVER),
-               ((emac_read(EMAC_TXCONTROL)) ? "enabled" : "disabled"),
-               emac_read(EMAC_RXIDVER),
-               ((emac_read(EMAC_RXCONTROL)) ? "enabled" : "disabled"));
-       dev_info(emac_dev, "EMAC: TXIntRaw:%08X, TxIntMasked: %08X, "\
-               "TxIntMasSet: %08X\n", emac_read(EMAC_TXINTSTATRAW),
-               emac_read(EMAC_TXINTSTATMASKED), emac_read(EMAC_TXINTMASKSET));
-       dev_info(emac_dev, "EMAC: RXIntRaw:%08X, RxIntMasked: %08X, "\
-               "RxIntMasSet: %08X\n", emac_read(EMAC_RXINTSTATRAW),
-               emac_read(EMAC_RXINTSTATMASKED), emac_read(EMAC_RXINTMASKSET));
-       dev_info(emac_dev, "EMAC: MacIntRaw:%08X, MacIntMasked: %08X, "\
-               "MacInVector=%08X\n", emac_read(EMAC_MACINTSTATRAW),
-               emac_read(EMAC_MACINTSTATMASKED), emac_read(EMAC_MACINVECTOR));
        dev_info(emac_dev, "EMAC: EmuControl:%08X, FifoControl: %08X\n",
                emac_read(EMAC_EMCONTROL), emac_read(EMAC_FIFOCONTROL));
        dev_info(emac_dev, "EMAC: MBPEnable:%08X, RXUnicastSet: %08X, "\
@@ -591,8 +399,6 @@ static void emac_dump_regs(struct emac_priv *priv)
        dev_info(emac_dev, "EMAC: MacControl:%08X, MacStatus: %08X, "\
                "MacConfig=%08X\n", emac_read(EMAC_MACCONTROL),
                emac_read(EMAC_MACSTATUS), emac_read(EMAC_MACCONFIG));
-       dev_info(emac_dev, "EMAC: TXHDP[0]:%08X, RXHDP[0]: %08X\n",
-               emac_read(EMAC_TXHDP(0)), emac_read(EMAC_RXHDP(0)));
        dev_info(emac_dev, "EMAC Statistics\n");
        dev_info(emac_dev, "EMAC: rx_good_frames:%d\n",
                emac_read(EMAC_RXGOODFRAMES));
@@ -654,11 +460,10 @@ static void emac_dump_regs(struct emac_priv *priv)
                emac_read(EMAC_RXMOFOVERRUNS));
        dev_info(emac_dev, "EMAC: rx_dma_overruns:%d\n",
                emac_read(EMAC_RXDMAOVERRUNS));
+
+       cpdma_ctlr_dump(priv->dma);
 }
 
-/*************************************************************************
- *  EMAC MDIO/Phy Functionality
- *************************************************************************/
 /**
  * emac_get_drvinfo: Get EMAC driver information
  * @ndev: The DaVinci EMAC network adapter
@@ -686,7 +491,7 @@ static int emac_get_settings(struct net_device *ndev,
                             struct ethtool_cmd *ecmd)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       if (priv->phy_mask)
+       if (priv->phydev)
                return phy_ethtool_gset(priv->phydev, ecmd);
        else
                return -EOPNOTSUPP;
@@ -704,7 +509,7 @@ static int emac_get_settings(struct net_device *ndev,
 static int emac_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       if (priv->phy_mask)
+       if (priv->phydev)
                return phy_ethtool_sset(priv->phydev, ecmd);
        else
                return -EOPNOTSUPP;
@@ -841,7 +646,7 @@ static void emac_update_phystatus(struct emac_priv *priv)
        mac_control = emac_read(EMAC_MACCONTROL);
        cur_duplex = (mac_control & EMAC_MACCONTROL_FULLDUPLEXEN) ?
                        DUPLEX_FULL : DUPLEX_HALF;
-       if (priv->phy_mask)
+       if (priv->phydev)
                new_duplex = priv->phydev->duplex;
        else
                new_duplex = DUPLEX_FULL;
@@ -1184,371 +989,68 @@ static irqreturn_t emac_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/** EMAC on-chip buffer descriptor memory
- *
- * WARNING: Please note that the on chip memory is used for both TX and RX
- * buffer descriptor queues and is equally divided between TX and RX desc's
- * If the number of TX or RX descriptors change this memory pointers need
- * to be adjusted. If external memory is allocated then these pointers can
- * pointer to the memory
- *
- */
-#define EMAC_TX_BD_MEM(priv)   ((priv)->emac_ctrl_ram)
-#define EMAC_RX_BD_MEM(priv)   ((priv)->emac_ctrl_ram + \
-                               (((priv)->ctrl_ram_size) >> 1))
-
-/**
- * emac_init_txch: TX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device init to setup a TX channel (allocate buffer desc
- * create free pool and keep ready for transmission
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_txch(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 cnt, bd_size;
-       void __iomem *mem;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch = NULL;
-
-       txch = kzalloc(sizeof(struct emac_txch), GFP_KERNEL);
-       if (NULL == txch) {
-               dev_err(emac_dev, "DaVinci EMAC: TX Ch mem alloc failed");
-               return -ENOMEM;
-       }
-       priv->txch[ch] = txch;
-       txch->service_max = EMAC_DEF_TX_MAX_SERVICE;
-       txch->active_queue_head = NULL;
-       txch->active_queue_tail = NULL;
-       txch->queue_active = 0;
-       txch->teardown_pending = 0;
-
-       /* allocate memory for TX CPPI channel on a 4 byte boundry */
-       txch->tx_complete = kzalloc(txch->service_max * sizeof(u32),
-                                   GFP_KERNEL);
-       if (NULL == txch->tx_complete) {
-               dev_err(emac_dev, "DaVinci EMAC: Tx service mem alloc failed");
-               kfree(txch);
-               return -ENOMEM;
-       }
-
-       /* allocate buffer descriptor pool align every BD on four word
-        * boundry for future requirements */
-       bd_size = (sizeof(struct emac_tx_bd) + 0xF) & ~0xF;
-       txch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-       txch->alloc_size = (((bd_size * txch->num_bd) + 0xF) & ~0xF);
-
-       /* alloc TX BD memory */
-       txch->bd_mem = EMAC_TX_BD_MEM(priv);
-       __memzero((void __force *)txch->bd_mem, txch->alloc_size);
-
-       /* initialize the BD linked list */
-       mem = (void __force __iomem *)
-                       (((u32 __force) txch->bd_mem + 0xF) & ~0xF);
-       txch->bd_pool_head = NULL;
-       for (cnt = 0; cnt < txch->num_bd; cnt++) {
-               curr_bd = mem + (cnt * bd_size);
-               curr_bd->next = txch->bd_pool_head;
-               txch->bd_pool_head = curr_bd;
-       }
-
-       /* reset statistics counters */
-       txch->out_of_tx_bd = 0;
-       txch->no_active_pkts = 0;
-       txch->active_queue_count = 0;
-
-       return 0;
-}
-
-/**
- * emac_cleanup_txch: Book-keep function to clean TX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to clean up TX channel resources
- *
- */
-static void emac_cleanup_txch(struct emac_priv *priv, u32 ch)
+static struct sk_buff *emac_rx_alloc(struct emac_priv *priv)
 {
-       struct emac_txch *txch = priv->txch[ch];
-
-       if (txch) {
-               if (txch->bd_mem)
-                       txch->bd_mem = NULL;
-               kfree(txch->tx_complete);
-               kfree(txch);
-               priv->txch[ch] = NULL;
-       }
+       struct sk_buff *skb = dev_alloc_skb(priv->rx_buf_size);
+       if (WARN_ON(!skb))
+               return NULL;
+       skb->dev = priv->ndev;
+       skb_reserve(skb, NET_IP_ALIGN);
+       return skb;
 }
 
-/**
- * emac_net_tx_complete: TX packet completion function
- * @priv: The DaVinci EMAC private adapter structure
- * @net_data_tokens: packet token - skb pointer
- * @num_tokens: number of skb's to free
- * @ch: TX channel number
- *
- * Frees the skb once packet is transmitted
- *
- */
-static int emac_net_tx_complete(struct emac_priv *priv,
-                               void **net_data_tokens,
-                               int num_tokens, u32 ch)
+static void emac_rx_handler(void *token, int len, int status)
 {
-       struct net_device *ndev = priv->ndev;
-       u32 cnt;
-
-       if (unlikely(num_tokens && netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
-       for (cnt = 0; cnt < num_tokens; cnt++) {
-               struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt];
-               if (skb == NULL)
-                       continue;
-               ndev->stats.tx_packets++;
-               ndev->stats.tx_bytes += skb->len;
+       struct sk_buff          *skb = token;
+       struct net_device       *ndev = skb->dev;
+       struct emac_priv        *priv = netdev_priv(ndev);
+       struct device           *emac_dev = &ndev->dev;
+       int                     ret;
+
+       /* free and bail if we are shutting down */
+       if (unlikely(!netif_running(ndev))) {
                dev_kfree_skb_any(skb);
+               return;
        }
-       return 0;
-}
-
-/**
- * emac_txch_teardown: TX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to teardown TX channel
- *
- */
-static void emac_txch_teardown(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-       struct emac_txch *txch = priv->txch[ch];
-       struct emac_tx_bd __iomem *curr_bd;
-
-       while ((emac_read(EMAC_TXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-              EMAC_TEARDOWN_VALUE) {
-               /* wait till tx teardown complete */
-               cpu_relax(); /* TODO: check if this helps ... */
-               --teardown_cnt;
-               if (0 == teardown_cnt) {
-                       dev_err(emac_dev, "EMAC: TX teardown aborted\n");
-                       break;
-               }
-       }
-       emac_write(EMAC_TXCP(ch), EMAC_TEARDOWN_VALUE);
-
-       /* process sent packets and return skb's to upper layer */
-       if (1 == txch->queue_active) {
-               curr_bd = txch->active_queue_head;
-               while (curr_bd != NULL) {
-                       dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_TO_DEVICE);
-
-                       emac_net_tx_complete(priv, (void __force *)
-                                       &curr_bd->buf_token, 1, ch);
-                       if (curr_bd != txch->active_queue_tail)
-                               curr_bd = curr_bd->next;
-                       else
-                               break;
-               }
-               txch->bd_pool_head = txch->active_queue_head;
-               txch->active_queue_head =
-               txch->active_queue_tail = NULL;
-       }
-}
 
-/**
- * emac_stop_txch: Stop TX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number
- *
- * Called to stop TX channel operation
- *
- */
-static void emac_stop_txch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_txch *txch = priv->txch[ch];
-
-       if (txch) {
-               txch->teardown_pending = 1;
-               emac_write(EMAC_TXTEARDOWN, 0);
-               emac_txch_teardown(priv, ch);
-               txch->teardown_pending = 0;
-               emac_write(EMAC_TXINTMASKCLEAR, BIT(ch));
+       /* recycle on recieve error */
+       if (status < 0) {
+               ndev->stats.rx_errors++;
+               goto recycle;
        }
-}
 
-/**
- * emac_tx_bdproc: TX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: TX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes TX buffer descriptors after packets are transmitted - checks
- * ownership bit on the TX * descriptor and requeues it to free pool & frees
- * the SKB buffer. Only "budget" number of packets are processed and
- * indication of pending packets provided to the caller
- *
- * Returns number of packets processed
- */
-static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       unsigned long flags;
-       u32 frame_status;
-       u32 pkts_processed = 0;
-       u32 tx_complete_cnt = 0;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch = priv->txch[ch];
-       u32 *tx_complete_ptr = txch->tx_complete;
-
-       if (unlikely(1 == txch->teardown_pending)) {
-               if (netif_msg_tx_err(priv) && net_ratelimit()) {
-                       dev_err(emac_dev, "DaVinci EMAC:emac_tx_bdproc: "\
-                               "teardown pending\n");
-               }
-               return 0;  /* dont handle any pkt completions */
-       }
+       /* feed received packet up the stack */
+       skb_put(skb, len);
+       skb->protocol = eth_type_trans(skb, ndev);
+       netif_receive_skb(skb);
+       ndev->stats.rx_bytes += len;
+       ndev->stats.rx_packets++;
 
-       ++txch->proc_count;
-       spin_lock_irqsave(&priv->tx_lock, flags);
-       curr_bd = txch->active_queue_head;
-       if (NULL == curr_bd) {
-               emac_write(EMAC_TXCP(ch),
-                          emac_virt_to_phys(txch->last_hw_bdprocessed, priv));
-               txch->no_active_pkts++;
-               spin_unlock_irqrestore(&priv->tx_lock, flags);
-               return 0;
+       /* alloc a new packet for receive */
+       skb = emac_rx_alloc(priv);
+       if (!skb) {
+               if (netif_msg_rx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "failed rx buffer alloc\n");
+               return;
        }
-       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       frame_status = curr_bd->mode;
-       while ((curr_bd) &&
-             ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-             (pkts_processed < budget)) {
-               emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv));
-               txch->active_queue_head = curr_bd->next;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       if (curr_bd->next) {    /* misqueued packet */
-                               emac_write(EMAC_TXHDP(ch), curr_bd->h_next);
-                               ++txch->mis_queued_packets;
-                       } else {
-                               txch->queue_active = 0; /* end of queue */
-                       }
-               }
 
-               dma_unmap_single(emac_dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_TO_DEVICE);
-
-               *tx_complete_ptr = (u32) curr_bd->buf_token;
-               ++tx_complete_ptr;
-               ++tx_complete_cnt;
-               curr_bd->next = txch->bd_pool_head;
-               txch->bd_pool_head = curr_bd;
-               --txch->active_queue_count;
-               pkts_processed++;
-               txch->last_hw_bdprocessed = curr_bd;
-               curr_bd = txch->active_queue_head;
-               if (curr_bd) {
-                       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-                       frame_status = curr_bd->mode;
-               }
-       } /* end of pkt processing loop */
-
-       emac_net_tx_complete(priv,
-                            (void *)&txch->tx_complete[0],
-                            tx_complete_cnt, ch);
-       spin_unlock_irqrestore(&priv->tx_lock, flags);
-       return pkts_processed;
+recycle:
+       ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+                       skb_tailroom(skb), GFP_KERNEL);
+       if (WARN_ON(ret < 0))
+               dev_kfree_skb_any(skb);
 }
 
-#define EMAC_ERR_TX_OUT_OF_BD -1
-
-/**
- * emac_send: EMAC Transmit function (internal)
- * @priv: The DaVinci EMAC private adapter structure
- * @pkt: packet pointer (contains skb ptr)
- * @ch: TX channel number
- *
- * Called by the transmit function to queue the packet in EMAC hardware queue
- *
- * Returns success(0) or error code (typically out of desc's)
- */
-static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
+static void emac_tx_handler(void *token, int len, int status)
 {
-       unsigned long flags;
-       struct emac_tx_bd __iomem *curr_bd;
-       struct emac_txch *txch;
-       struct emac_netbufobj *buf_list;
-
-       txch = priv->txch[ch];
-       buf_list = pkt->buf_list;   /* get handle to the buffer array */
-
-       /* check packet size and pad if short */
-       if (pkt->pkt_length < EMAC_DEF_MIN_ETHPKTSIZE) {
-               buf_list->length += (EMAC_DEF_MIN_ETHPKTSIZE - pkt->pkt_length);
-               pkt->pkt_length = EMAC_DEF_MIN_ETHPKTSIZE;
-       }
+       struct sk_buff          *skb = token;
+       struct net_device       *ndev = skb->dev;
 
-       spin_lock_irqsave(&priv->tx_lock, flags);
-       curr_bd = txch->bd_pool_head;
-       if (curr_bd == NULL) {
-               txch->out_of_tx_bd++;
-               spin_unlock_irqrestore(&priv->tx_lock, flags);
-               return EMAC_ERR_TX_OUT_OF_BD;
-       }
-
-       txch->bd_pool_head = curr_bd->next;
-       curr_bd->buf_token = buf_list->buf_token;
-       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr,
-                       buf_list->length, DMA_TO_DEVICE);
-       curr_bd->off_b_len = buf_list->length;
-       curr_bd->h_next = 0;
-       curr_bd->next = NULL;
-       curr_bd->mode = (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT |
-                        EMAC_CPPI_EOP_BIT | pkt->pkt_length);
-
-       /* flush the packet from cache if write back cache is present */
-       BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-
-       /* send the packet */
-       if (txch->active_queue_head == NULL) {
-               txch->active_queue_head = curr_bd;
-               txch->active_queue_tail = curr_bd;
-               if (1 != txch->queue_active) {
-                       emac_write(EMAC_TXHDP(ch),
-                                       emac_virt_to_phys(curr_bd, priv));
-                       txch->queue_active = 1;
-               }
-               ++txch->queue_reinit;
-       } else {
-               register struct emac_tx_bd __iomem *tail_bd;
-               register u32 frame_status;
-
-               tail_bd = txch->active_queue_tail;
-               tail_bd->next = curr_bd;
-               txch->active_queue_tail = curr_bd;
-               tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-               tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv);
-               frame_status = tail_bd->mode;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       emac_write(EMAC_TXHDP(ch),
-                               emac_virt_to_phys(curr_bd, priv));
-                       frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-                       tail_bd->mode = frame_status;
-                       ++txch->end_of_queue_add;
-               }
-       }
-       txch->active_queue_count++;
-       spin_unlock_irqrestore(&priv->tx_lock, flags);
-       return 0;
+       if (unlikely(netif_queue_stopped(ndev)))
+               netif_start_queue(ndev);
+       ndev->stats.tx_packets++;
+       ndev->stats.tx_bytes += len;
+       dev_kfree_skb_any(skb);
 }
 
 /**
@@ -1565,42 +1067,36 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        struct device *emac_dev = &ndev->dev;
        int ret_code;
-       struct emac_netbufobj tx_buf; /* buffer obj-only single frame support */
-       struct emac_netpktobj tx_packet;  /* packet object */
        struct emac_priv *priv = netdev_priv(ndev);
 
        /* If no link, return */
        if (unlikely(!priv->link)) {
                if (netif_msg_tx_err(priv) && net_ratelimit())
                        dev_err(emac_dev, "DaVinci EMAC: No link to transmit");
-               return NETDEV_TX_BUSY;
+               goto fail_tx;
+       }
+
+       ret_code = skb_padto(skb, EMAC_DEF_MIN_ETHPKTSIZE);
+       if (unlikely(ret_code < 0)) {
+               if (netif_msg_tx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "DaVinci EMAC: packet pad failed");
+               goto fail_tx;
        }
 
-       /* Build the buffer and packet objects - Since only single fragment is
-        * supported, need not set length and token in both packet & object.
-        * Doing so for completeness sake & to show that this needs to be done
-        * in multifragment case
-        */
-       tx_packet.buf_list = &tx_buf;
-       tx_packet.num_bufs = 1; /* only single fragment supported */
-       tx_packet.pkt_length = skb->len;
-       tx_packet.pkt_token = (void *)skb;
-       tx_buf.length = skb->len;
-       tx_buf.buf_token = (void *)skb;
-       tx_buf.data_ptr = skb->data;
-       ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH);
+       ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
+                                    GFP_KERNEL);
        if (unlikely(ret_code != 0)) {
-               if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
-                       if (netif_msg_tx_err(priv) && net_ratelimit())
-                               dev_err(emac_dev, "DaVinci EMAC: xmit() fatal"\
-                                       " err. Out of TX BD's");
-                       netif_stop_queue(priv->ndev);
-               }
-               ndev->stats.tx_dropped++;
-               return NETDEV_TX_BUSY;
+               if (netif_msg_tx_err(priv) && net_ratelimit())
+                       dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
+               goto fail_tx;
        }
 
        return NETDEV_TX_OK;
+
+fail_tx:
+       ndev->stats.tx_dropped++;
+       netif_stop_queue(ndev);
+       return NETDEV_TX_BUSY;
 }
 
 /**
@@ -1621,218 +1117,16 @@ static void emac_dev_tx_timeout(struct net_device *ndev)
        if (netif_msg_tx_err(priv))
                dev_err(emac_dev, "DaVinci EMAC: xmit timeout, restarting TX");
 
+       emac_dump_regs(priv);
+
        ndev->stats.tx_errors++;
        emac_int_disable(priv);
-       emac_stop_txch(priv, EMAC_DEF_TX_CH);
-       emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-       emac_init_txch(priv, EMAC_DEF_TX_CH);
-       emac_write(EMAC_TXHDP(0), 0);
-       emac_write(EMAC_TXINTMASKSET, BIT(EMAC_DEF_TX_CH));
+       cpdma_chan_stop(priv->txchan);
+       cpdma_chan_start(priv->txchan);
        emac_int_enable(priv);
 }
 
 /**
- * emac_net_alloc_rx_buf: Allocate a skb for RX
- * @priv: The DaVinci EMAC private adapter structure
- * @buf_size: size of SKB data buffer to allocate
- * @data_token: data token returned (skb handle for storing in buffer desc)
- * @ch: RX channel number
- *
- * Called during RX channel setup - allocates skb buffer of required size
- * and provides the skb handle and allocated buffer data pointer to caller
- *
- * Returns skb data pointer or 0 on failure to alloc skb
- */
-static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size,
-               void **data_token, u32 ch)
-{
-       struct net_device *ndev = priv->ndev;
-       struct device *emac_dev = &ndev->dev;
-       struct sk_buff *p_skb;
-
-       p_skb = dev_alloc_skb(buf_size);
-       if (unlikely(NULL == p_skb)) {
-               if (netif_msg_rx_err(priv) && net_ratelimit())
-                       dev_err(emac_dev, "DaVinci EMAC: failed to alloc skb");
-               return NULL;
-       }
-
-       /* set device pointer in skb and reserve space for extra bytes */
-       p_skb->dev = ndev;
-       skb_reserve(p_skb, NET_IP_ALIGN);
-       *data_token = (void *) p_skb;
-       return p_skb->data;
-}
-
-/**
- * emac_init_rxch: RX channel initialization
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- * @param: mac address for RX channel
- *
- * Called during device init to setup a RX channel (allocate buffers and
- * buffer descriptors, create queue and keep ready for reception
- *
- * Returns success(0) or mem alloc failures error code
- */
-static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 cnt, bd_size;
-       void __iomem *mem;
-       struct emac_rx_bd __iomem *curr_bd;
-       struct emac_rxch *rxch = NULL;
-
-       rxch = kzalloc(sizeof(struct emac_rxch), GFP_KERNEL);
-       if (NULL == rxch) {
-               dev_err(emac_dev, "DaVinci EMAC: RX Ch mem alloc failed");
-               return -ENOMEM;
-       }
-       priv->rxch[ch] = rxch;
-       rxch->buf_size = priv->rx_buf_size;
-       rxch->service_max = EMAC_DEF_RX_MAX_SERVICE;
-       rxch->queue_active = 0;
-       rxch->teardown_pending = 0;
-
-       /* save mac address */
-       for (cnt = 0; cnt < 6; cnt++)
-               rxch->mac_addr[cnt] = param[cnt];
-
-       /* allocate buffer descriptor pool align every BD on four word
-        * boundry for future requirements */
-       bd_size = (sizeof(struct emac_rx_bd) + 0xF) & ~0xF;
-       rxch->num_bd = (priv->ctrl_ram_size >> 1) / bd_size;
-       rxch->alloc_size = (((bd_size * rxch->num_bd) + 0xF) & ~0xF);
-       rxch->bd_mem = EMAC_RX_BD_MEM(priv);
-       __memzero((void __force *)rxch->bd_mem, rxch->alloc_size);
-       rxch->pkt_queue.buf_list = &rxch->buf_queue;
-
-       /* allocate RX buffer and initialize the BD linked list */
-       mem = (void __force __iomem *)
-                       (((u32 __force) rxch->bd_mem + 0xF) & ~0xF);
-       rxch->active_queue_head = NULL;
-       rxch->active_queue_tail = mem;
-       for (cnt = 0; cnt < rxch->num_bd; cnt++) {
-               curr_bd = mem + (cnt * bd_size);
-               /* for future use the last parameter contains the BD ptr */
-               curr_bd->data_ptr = emac_net_alloc_rx_buf(priv,
-                                   rxch->buf_size,
-                                   (void __force **)&curr_bd->buf_token,
-                                   EMAC_DEF_RX_CH);
-               if (curr_bd->data_ptr == NULL) {
-                       dev_err(emac_dev, "DaVinci EMAC: RX buf mem alloc " \
-                               "failed for ch %d\n", ch);
-                       kfree(rxch);
-                       return -ENOMEM;
-               }
-
-               /* populate the hardware descriptor */
-               curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
-                               priv);
-               curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr,
-                               rxch->buf_size, DMA_FROM_DEVICE);
-               curr_bd->off_b_len = rxch->buf_size;
-               curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-
-               /* write back to hardware memory */
-               BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd,
-                                             EMAC_BD_LENGTH_FOR_CACHE);
-               curr_bd->next = rxch->active_queue_head;
-               rxch->active_queue_head = curr_bd;
-       }
-
-       /* At this point rxCppi->activeQueueHead points to the first
-          RX BD ready to be given to RX HDP and rxch->active_queue_tail
-          points to the last RX BD
-        */
-       return 0;
-}
-
-/**
- * emac_rxch_teardown: RX channel teardown
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to teardown RX channel
- *
- */
-static void emac_rxch_teardown(struct emac_priv *priv, u32 ch)
-{
-       struct device *emac_dev = &priv->ndev->dev;
-       u32 teardown_cnt = 0xFFFFFFF0; /* Some high value */
-
-       while ((emac_read(EMAC_RXCP(ch)) & EMAC_TEARDOWN_VALUE) !=
-              EMAC_TEARDOWN_VALUE) {
-               /* wait till tx teardown complete */
-               cpu_relax(); /* TODO: check if this helps ... */
-               --teardown_cnt;
-               if (0 == teardown_cnt) {
-                       dev_err(emac_dev, "EMAC: RX teardown aborted\n");
-                       break;
-               }
-       }
-       emac_write(EMAC_RXCP(ch), EMAC_TEARDOWN_VALUE);
-}
-
-/**
- * emac_stop_rxch: Stop RX channel operation
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to stop RX channel operation
- *
- */
-static void emac_stop_rxch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       if (rxch) {
-               rxch->teardown_pending = 1;
-               emac_write(EMAC_RXTEARDOWN, ch);
-               /* wait for teardown complete */
-               emac_rxch_teardown(priv, ch);
-               rxch->teardown_pending = 0;
-               emac_write(EMAC_RXINTMASKCLEAR, BIT(ch));
-       }
-}
-
-/**
- * emac_cleanup_rxch: Book-keep function to clean RX channel resources
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number
- *
- * Called during device stop to clean up RX channel resources
- *
- */
-static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-       struct emac_rx_bd __iomem *curr_bd;
-
-       if (rxch) {
-               /* free the receive buffers previously allocated */
-               curr_bd = rxch->active_queue_head;
-               while (curr_bd) {
-                       if (curr_bd->buf_token) {
-                               dma_unmap_single(&priv->ndev->dev,
-                                       curr_bd->buff_ptr,
-                                       curr_bd->off_b_len
-                                               & EMAC_RX_BD_BUF_SIZE,
-                                       DMA_FROM_DEVICE);
-
-                               dev_kfree_skb_any((struct sk_buff *)\
-                                                 curr_bd->buf_token);
-                       }
-                       curr_bd = curr_bd->next;
-               }
-               if (rxch->bd_mem)
-                       rxch->bd_mem = NULL;
-               kfree(rxch);
-               priv->rxch[ch] = NULL;
-       }
-}
-
-/**
  * emac_set_type0addr: Set EMAC Type0 mac address
  * @priv: The DaVinci EMAC private adapter structure
  * @ch: RX channel number
@@ -1948,7 +1242,6 @@ static void emac_setmac(struct emac_priv *priv, u32 ch, char *mac_addr)
 static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 {
        struct emac_priv *priv = netdev_priv(ndev);
-       struct emac_rxch *rxch = priv->rxch[EMAC_DEF_RX_CH];
        struct device *emac_dev = &priv->ndev->dev;
        struct sockaddr *sa = addr;
 
@@ -1959,11 +1252,10 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
        memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
        memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
 
-       /* If the interface is down - rxch is NULL. */
        /* MAC address is configured only after the interface is enabled. */
        if (netif_running(ndev)) {
-               memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
-               emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+               memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
+               emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
        }
 
        if (netif_msg_drv(priv))
@@ -1974,194 +1266,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 }
 
 /**
- * emac_addbd_to_rx_queue: Recycle RX buffer descriptor
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @curr_bd: current buffer descriptor
- * @buffer: buffer pointer for descriptor
- * @buf_token: buffer token (stores skb information)
- *
- * Prepares the recycled buffer descriptor and addes it to hardware
- * receive queue - if queue empty this descriptor becomes the head
- * else addes the descriptor to end of queue
- *
- */
-static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
-               struct emac_rx_bd __iomem *curr_bd,
-               char *buffer, void *buf_token)
-{
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       /* populate the hardware descriptor */
-       curr_bd->h_next = 0;
-       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer,
-                               rxch->buf_size, DMA_FROM_DEVICE);
-       curr_bd->off_b_len = rxch->buf_size;
-       curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
-       curr_bd->next = NULL;
-       curr_bd->data_ptr = buffer;
-       curr_bd->buf_token = buf_token;
-
-       /* write back  */
-       BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       if (rxch->active_queue_head == NULL) {
-               rxch->active_queue_head = curr_bd;
-               rxch->active_queue_tail = curr_bd;
-               if (0 != rxch->queue_active) {
-                       emac_write(EMAC_RXHDP(ch),
-                          emac_virt_to_phys(rxch->active_queue_head, priv));
-                       rxch->queue_active = 1;
-               }
-       } else {
-               struct emac_rx_bd __iomem *tail_bd;
-               u32 frame_status;
-
-               tail_bd = rxch->active_queue_tail;
-               rxch->active_queue_tail = curr_bd;
-               tail_bd->next = curr_bd;
-               tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-               tail_bd->h_next = emac_virt_to_phys(curr_bd, priv);
-               frame_status = tail_bd->mode;
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       emac_write(EMAC_RXHDP(ch),
-                                       emac_virt_to_phys(curr_bd, priv));
-                       frame_status &= ~(EMAC_CPPI_EOQ_BIT);
-                       tail_bd->mode = frame_status;
-                       ++rxch->end_of_queue_add;
-               }
-       }
-       ++rxch->recycled_bd;
-}
-
-/**
- * emac_net_rx_cb: Prepares packet and sends to upper layer
- * @priv: The DaVinci EMAC private adapter structure
- * @net_pkt_list: Network packet list (received packets)
- *
- * Invalidates packet buffer memory and sends the received packet to upper
- * layer
- *
- * Returns success or appropriate error code (none as of now)
- */
-static int emac_net_rx_cb(struct emac_priv *priv,
-                         struct emac_netpktobj *net_pkt_list)
-{
-       struct net_device *ndev = priv->ndev;
-       struct sk_buff *p_skb = net_pkt_list->pkt_token;
-       /* set length of packet */
-       skb_put(p_skb, net_pkt_list->pkt_length);
-       p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
-       netif_receive_skb(p_skb);
-       ndev->stats.rx_bytes += net_pkt_list->pkt_length;
-       ndev->stats.rx_packets++;
-       return 0;
-}
-
-/**
- * emac_rx_bdproc: RX buffer descriptor (packet) processing
- * @priv: The DaVinci EMAC private adapter structure
- * @ch: RX channel number to process buffer descriptors for
- * @budget: number of packets allowed to process
- * @pending: indication to caller that packets are pending to process
- *
- * Processes RX buffer descriptors - checks ownership bit on the RX buffer
- * descriptor, sends the receive packet to upper layer, allocates a new SKB
- * and recycles the buffer descriptor (requeues it in hardware RX queue).
- * Only "budget" number of packets are processed and indication of pending
- * packets provided to the caller.
- *
- * Returns number of packets processed (and indication of pending packets)
- */
-static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
-{
-       unsigned long flags;
-       u32 frame_status;
-       u32 pkts_processed = 0;
-       char *new_buffer;
-       struct emac_rx_bd __iomem *curr_bd;
-       struct emac_rx_bd __iomem *last_bd;
-       struct emac_netpktobj *curr_pkt, pkt_obj;
-       struct emac_netbufobj buf_obj;
-       struct emac_netbufobj *rx_buf_obj;
-       void *new_buf_token;
-       struct emac_rxch *rxch = priv->rxch[ch];
-
-       if (unlikely(1 == rxch->teardown_pending))
-               return 0;
-       ++rxch->proc_count;
-       spin_lock_irqsave(&priv->rx_lock, flags);
-       pkt_obj.buf_list = &buf_obj;
-       curr_pkt = &pkt_obj;
-       curr_bd = rxch->active_queue_head;
-       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-       frame_status = curr_bd->mode;
-
-       while ((curr_bd) &&
-              ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
-              (pkts_processed < budget)) {
-
-               new_buffer = emac_net_alloc_rx_buf(priv, rxch->buf_size,
-                                       &new_buf_token, EMAC_DEF_RX_CH);
-               if (unlikely(NULL == new_buffer)) {
-                       ++rxch->out_of_rx_buffers;
-                       goto end_emac_rx_bdproc;
-               }
-
-               /* populate received packet data structure */
-               rx_buf_obj = &curr_pkt->buf_list[0];
-               rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
-               rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
-               rx_buf_obj->buf_token = curr_bd->buf_token;
-
-               dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr,
-                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
-                               DMA_FROM_DEVICE);
-
-               curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
-               curr_pkt->num_bufs = 1;
-               curr_pkt->pkt_length =
-                       (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
-               emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv));
-               ++rxch->processed_bd;
-               last_bd = curr_bd;
-               curr_bd = last_bd->next;
-               rxch->active_queue_head = curr_bd;
-
-               /* check if end of RX queue ? */
-               if (frame_status & EMAC_CPPI_EOQ_BIT) {
-                       if (curr_bd) {
-                               ++rxch->mis_queued_packets;
-                               emac_write(EMAC_RXHDP(ch),
-                                          emac_virt_to_phys(curr_bd, priv));
-                       } else {
-                               ++rxch->end_of_queue;
-                               rxch->queue_active = 0;
-                       }
-               }
-
-               /* recycle BD */
-               emac_addbd_to_rx_queue(priv, ch, last_bd, new_buffer,
-                                      new_buf_token);
-
-               /* return the packet to the user - BD ptr passed in
-                * last parameter for potential *future* use */
-               spin_unlock_irqrestore(&priv->rx_lock, flags);
-               emac_net_rx_cb(priv, curr_pkt);
-               spin_lock_irqsave(&priv->rx_lock, flags);
-               curr_bd = rxch->active_queue_head;
-               if (curr_bd) {
-                       BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
-                       frame_status = curr_bd->mode;
-               }
-               ++pkts_processed;
-       }
-
-end_emac_rx_bdproc:
-       spin_unlock_irqrestore(&priv->rx_lock, flags);
-       return pkts_processed;
-}
-
-/**
  * emac_hw_enable: Enable EMAC hardware for packet transmission/reception
  * @priv: The DaVinci EMAC private adapter structure
  *
@@ -2172,7 +1276,7 @@ end_emac_rx_bdproc:
  */
 static int emac_hw_enable(struct emac_priv *priv)
 {
-       u32 ch, val, mbp_enable, mac_control;
+       u32 val, mbp_enable, mac_control;
 
        /* Soft reset */
        emac_write(EMAC_SOFTRESET, 1);
@@ -2215,26 +1319,9 @@ static int emac_hw_enable(struct emac_priv *priv)
        emac_write(EMAC_RXUNICASTCLEAR, EMAC_RX_UNICAST_CLEAR_ALL);
        priv->rx_addr_type = (emac_read(EMAC_MACCONFIG) >> 8) & 0xFF;
 
-       val = emac_read(EMAC_TXCONTROL);
-       val |= EMAC_TX_CONTROL_TX_ENABLE_VAL;
-       emac_write(EMAC_TXCONTROL, val);
-       val = emac_read(EMAC_RXCONTROL);
-       val |= EMAC_RX_CONTROL_RX_ENABLE_VAL;
-       emac_write(EMAC_RXCONTROL, val);
        emac_write(EMAC_MACINTMASKSET, EMAC_MAC_HOST_ERR_INTMASK_VAL);
 
-       for (ch = 0; ch < EMAC_DEF_MAX_TX_CH; ch++) {
-               emac_write(EMAC_TXHDP(ch), 0);
-               emac_write(EMAC_TXINTMASKSET, BIT(ch));
-       }
-       for (ch = 0; ch < EMAC_DEF_MAX_RX_CH; ch++) {
-               struct emac_rxch *rxch = priv->rxch[ch];
-               emac_setmac(priv, ch, rxch->mac_addr);
-               emac_write(EMAC_RXINTMASKSET, BIT(ch));
-               rxch->queue_active = 1;
-               emac_write(EMAC_RXHDP(ch),
-                          emac_virt_to_phys(rxch->active_queue_head, priv));
-       }
+       emac_setmac(priv, EMAC_DEF_RX_CH, priv->mac_addr);
 
        /* Enable MII */
        val = emac_read(EMAC_MACCONTROL);
@@ -2279,8 +1366,8 @@ static int emac_poll(struct napi_struct *napi, int budget)
                mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
 
        if (status & mask) {
-               num_tx_pkts = emac_tx_bdproc(priv, EMAC_DEF_TX_CH,
-                                         EMAC_DEF_TX_MAX_SERVICE);
+               num_tx_pkts = cpdma_chan_process(priv->txchan,
+                                             EMAC_DEF_TX_MAX_SERVICE);
        } /* TX processing */
 
        mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
@@ -2289,7 +1376,7 @@ static int emac_poll(struct napi_struct *napi, int budget)
                mask = EMAC_DM646X_MAC_IN_VECTOR_RX_INT_VEC;
 
        if (status & mask) {
-               num_rx_pkts = emac_rx_bdproc(priv, EMAC_DEF_RX_CH, budget);
+               num_rx_pkts = cpdma_chan_process(priv->rxchan, budget);
        } /* RX processing */
 
        mask = EMAC_DM644X_MAC_IN_VECTOR_HOST_INT;
@@ -2348,79 +1435,6 @@ void emac_poll_controller(struct net_device *ndev)
 }
 #endif
 
-/* PHY/MII bus related */
-
-/* Wait until mdio is ready for next command */
-#define MDIO_WAIT_FOR_USER_ACCESS\
-               while ((emac_mdio_read((MDIO_USERACCESS(0))) &\
-                       MDIO_USERACCESS_GO) != 0)
-
-static int emac_mii_read(struct mii_bus *bus, int phy_id, int phy_reg)
-{
-       unsigned int phy_data = 0;
-       unsigned int phy_control;
-
-       /* Wait until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       phy_control = (MDIO_USERACCESS_GO |
-                      MDIO_USERACCESS_READ |
-                      ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-                      ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-                      (phy_data & MDIO_USERACCESS_DATA));
-       emac_mdio_write(MDIO_USERACCESS(0), phy_control);
-
-       /* Wait until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       return emac_mdio_read(MDIO_USERACCESS(0)) & MDIO_USERACCESS_DATA;
-
-}
-
-static int emac_mii_write(struct mii_bus *bus, int phy_id,
-                         int phy_reg, u16 phy_data)
-{
-
-       unsigned int control;
-
-       /*  until mdio is ready for next command */
-       MDIO_WAIT_FOR_USER_ACCESS;
-
-       control = (MDIO_USERACCESS_GO |
-                  MDIO_USERACCESS_WRITE |
-                  ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
-                  ((phy_id << 16) & MDIO_USERACCESS_PHYADR) |
-                  (phy_data & MDIO_USERACCESS_DATA));
-       emac_mdio_write(MDIO_USERACCESS(0), control);
-
-       return 0;
-}
-
-static int emac_mii_reset(struct mii_bus *bus)
-{
-       unsigned int clk_div;
-       int mdio_bus_freq = emac_bus_frequency;
-
-       if (mdio_max_freq && mdio_bus_freq)
-               clk_div = ((mdio_bus_freq / mdio_max_freq) - 1);
-       else
-               clk_div = 0xFF;
-
-       clk_div &= MDIO_CONTROL_CLKDIV;
-
-       /* Set enable and clock divider in MDIOControl */
-       emac_mdio_write(MDIO_CONTROL, (clk_div | MDIO_CONTROL_ENABLE));
-
-       return 0;
-
-}
-
-static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, PHY_POLL };
-
-/* emac_driver: EMAC MII bus structure */
-
-static struct mii_bus *emac_mii;
-
 static void emac_adjust_link(struct net_device *ndev)
 {
        struct emac_priv *priv = netdev_priv(ndev);
@@ -2485,6 +1499,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
        return -EOPNOTSUPP;
 }
 
+static int match_first_device(struct device *dev, void *data)
+{
+       return 1;
+}
+
 /**
  * emac_dev_open: EMAC device open
  * @ndev: The DaVinci EMAC network adapter
@@ -2498,10 +1517,9 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
 static int emac_dev_open(struct net_device *ndev)
 {
        struct device *emac_dev = &ndev->dev;
-       u32 rc, cnt, ch;
-       int phy_addr;
+       u32 cnt;
        struct resource *res;
-       int q, m;
+       int q, m, ret;
        int i = 0;
        int k = 0;
        struct emac_priv *priv = netdev_priv(ndev);
@@ -2513,29 +1531,21 @@ static int emac_dev_open(struct net_device *ndev)
        /* Configuration items */
        priv->rx_buf_size = EMAC_DEF_MAX_FRAME_SIZE + NET_IP_ALIGN;
 
-       /* Clear basic hardware */
-       for (ch = 0; ch < EMAC_MAX_TXRX_CHANNELS; ch++) {
-               emac_write(EMAC_TXHDP(ch), 0);
-               emac_write(EMAC_RXHDP(ch), 0);
-               emac_write(EMAC_RXHDP(ch), 0);
-               emac_write(EMAC_RXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-               emac_write(EMAC_TXINTMASKCLEAR, EMAC_INT_MASK_CLEAR);
-       }
        priv->mac_hash1 = 0;
        priv->mac_hash2 = 0;
        emac_write(EMAC_MACHASH1, 0);
        emac_write(EMAC_MACHASH2, 0);
 
-       /* multi ch not supported - open 1 TX, 1RX ch by default */
-       rc = emac_init_txch(priv, EMAC_DEF_TX_CH);
-       if (0 != rc) {
-               dev_err(emac_dev, "DaVinci EMAC: emac_init_txch() failed");
-               return rc;
-       }
-       rc = emac_init_rxch(priv, EMAC_DEF_RX_CH, priv->mac_addr);
-       if (0 != rc) {
-               dev_err(emac_dev, "DaVinci EMAC: emac_init_rxch() failed");
-               return rc;
+       for (i = 0; i < EMAC_DEF_RX_NUM_DESC; i++) {
+               struct sk_buff *skb = emac_rx_alloc(priv);
+
+               if (!skb)
+                       break;
+
+               ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
+                                       skb_tailroom(skb), GFP_KERNEL);
+               if (WARN_ON(ret < 0))
+                       break;
        }
 
        /* Request IRQ */
@@ -2560,28 +1570,28 @@ static int emac_dev_open(struct net_device *ndev)
                emac_set_coalesce(ndev, &coal);
        }
 
-       /* find the first phy */
+       cpdma_ctlr_start(priv->dma);
+
        priv->phydev = NULL;
-       if (priv->phy_mask) {
-               emac_mii_reset(priv->mii_bus);
-               for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-                       if (priv->mii_bus->phy_map[phy_addr]) {
-                               priv->phydev = priv->mii_bus->phy_map[phy_addr];
-                               break;
-                       }
-               }
+       /* use the first phy on the bus if pdata did not give us a phy id */
+       if (!priv->phy_id) {
+               struct device *phy;
 
-               if (!priv->phydev) {
-                       printk(KERN_ERR "%s: no PHY found\n", ndev->name);
-                       return -1;
-               }
+               phy = bus_find_device(&mdio_bus_type, NULL, NULL,
+                                     match_first_device);
+               if (phy)
+                       priv->phy_id = dev_name(phy);
+       }
 
-               priv->phydev = phy_connect(ndev, dev_name(&priv->phydev->dev),
-                               &emac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+       if (priv->phy_id && *priv->phy_id) {
+               priv->phydev = phy_connect(ndev, priv->phy_id,
+                                          &emac_adjust_link, 0,
+                                          PHY_INTERFACE_MODE_MII);
 
                if (IS_ERR(priv->phydev)) {
-                       printk(KERN_ERR "%s: Could not attach to PHY\n",
-                                                               ndev->name);
+                       dev_err(emac_dev, "could not connect to phy %s\n",
+                               priv->phy_id);
+                       priv->phydev = NULL;
                        return PTR_ERR(priv->phydev);
                }
 
@@ -2589,12 +1599,13 @@ static int emac_dev_open(struct net_device *ndev)
                priv->speed = 0;
                priv->duplex = ~0;
 
-               printk(KERN_INFO "%s: attached PHY driver [%s] "
-                       "(mii_bus:phy_addr=%s, id=%x)\n", ndev->name,
+               dev_info(emac_dev, "attached PHY driver [%s] "
+                       "(mii_bus:phy_addr=%s, id=%x)\n",
                        priv->phydev->drv->name, dev_name(&priv->phydev->dev),
                        priv->phydev->phy_id);
-       } else{
+       } else {
                /* No PHY , fix the link, speed and duplex settings */
+               dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
                priv->link = 1;
                priv->speed = SPEED_100;
                priv->duplex = DUPLEX_FULL;
@@ -2607,7 +1618,7 @@ static int emac_dev_open(struct net_device *ndev)
        if (netif_msg_drv(priv))
                dev_notice(emac_dev, "DaVinci EMAC: Opened %s\n", ndev->name);
 
-       if (priv->phy_mask)
+       if (priv->phydev)
                phy_start(priv->phydev);
 
        return 0;
@@ -2648,10 +1659,7 @@ static int emac_dev_stop(struct net_device *ndev)
 
        netif_carrier_off(ndev);
        emac_int_disable(priv);
-       emac_stop_txch(priv, EMAC_DEF_TX_CH);
-       emac_stop_rxch(priv, EMAC_DEF_RX_CH);
-       emac_cleanup_txch(priv, EMAC_DEF_TX_CH);
-       emac_cleanup_rxch(priv, EMAC_DEF_RX_CH);
+       cpdma_ctlr_stop(priv->dma);
        emac_write(EMAC_SOFTRESET, 1);
 
        if (priv->phydev)
@@ -2756,9 +1764,10 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        struct resource *res;
        struct net_device *ndev;
        struct emac_priv *priv;
-       unsigned long size;
+       unsigned long size, hw_ram_addr;
        struct emac_platform_data *pdata;
        struct device *emac_dev;
+       struct cpdma_params dma_params;
 
        /* obtain emac clock from kernel */
        emac_clk = clk_get(&pdev->dev, NULL);
@@ -2782,8 +1791,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        priv->ndev = ndev;
        priv->msg_enable = netif_msg_init(debug_level, DAVINCI_EMAC_DEBUG);
 
-       spin_lock_init(&priv->tx_lock);
-       spin_lock_init(&priv->rx_lock);
        spin_lock_init(&priv->lock);
 
        pdata = pdev->dev.platform_data;
@@ -2794,7 +1801,7 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 
        /* MAC addr and PHY mask , RMII enable info from platform_data */
        memcpy(priv->mac_addr, pdata->mac_addr, 6);
-       priv->phy_mask = pdata->phy_mask;
+       priv->phy_id = pdata->phy_id;
        priv->rmii_en = pdata->rmii_en;
        priv->version = pdata->version;
        priv->int_enable = pdata->interrupt_enable;
@@ -2831,14 +1838,41 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        ndev->base_addr = (unsigned long)priv->remap_addr;
 
        priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-       priv->ctrl_ram_size = pdata->ctrl_ram_size;
-       priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
 
-       if (pdata->hw_ram_addr)
-               priv->hw_ram_addr = pdata->hw_ram_addr;
-       else
-               priv->hw_ram_addr = (u32 __force)res->start +
-                                       pdata->ctrl_ram_offset;
+       hw_ram_addr = pdata->hw_ram_addr;
+       if (!hw_ram_addr)
+               hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
+
+       memset(&dma_params, 0, sizeof(dma_params));
+       dma_params.dev                  = emac_dev;
+       dma_params.dmaregs              = priv->emac_base;
+       dma_params.rxthresh             = priv->emac_base + 0x120;
+       dma_params.rxfree               = priv->emac_base + 0x140;
+       dma_params.txhdp                = priv->emac_base + 0x600;
+       dma_params.rxhdp                = priv->emac_base + 0x620;
+       dma_params.txcp                 = priv->emac_base + 0x640;
+       dma_params.rxcp                 = priv->emac_base + 0x660;
+       dma_params.num_chan             = EMAC_MAX_TXRX_CHANNELS;
+       dma_params.min_packet_size      = EMAC_DEF_MIN_ETHPKTSIZE;
+       dma_params.desc_mem_phys        = hw_ram_addr;
+       dma_params.desc_mem_size        = pdata->ctrl_ram_size;
+       dma_params.desc_align           = 16;
+
+       priv->dma = cpdma_ctlr_create(&dma_params);
+       if (!priv->dma) {
+               dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n");
+               rc = -ENOMEM;
+               goto no_dma;
+       }
+
+       priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH),
+                                      emac_tx_handler);
+       priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH),
+                                      emac_rx_handler);
+       if (WARN_ON(!priv->txchan || !priv->rxchan)) {
+               rc = -ENOMEM;
+               goto no_irq_res;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
@@ -2871,32 +1905,6 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        }
 
 
-       /* MII/Phy intialisation, mdio bus registration */
-       emac_mii = mdiobus_alloc();
-       if (emac_mii == NULL) {
-               dev_err(emac_dev, "DaVinci EMAC: Error allocating mii_bus\n");
-               rc = -ENOMEM;
-               goto mdio_alloc_err;
-       }
-
-       priv->mii_bus = emac_mii;
-       emac_mii->name  = "emac-mii",
-       emac_mii->read  = emac_mii_read,
-       emac_mii->write = emac_mii_write,
-       emac_mii->reset = emac_mii_reset,
-       emac_mii->irq   = mii_irqs,
-       emac_mii->phy_mask = ~(priv->phy_mask);
-       emac_mii->parent = &pdev->dev;
-       emac_mii->priv = priv->remap_addr + pdata->mdio_reg_offset;
-       snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", priv->pdev->id);
-       mdio_max_freq = pdata->mdio_max_freq;
-       emac_mii->reset(emac_mii);
-
-       /* Register the MII bus */
-       rc = mdiobus_register(emac_mii);
-       if (rc)
-               goto mdiobus_quit;
-
        if (netif_msg_probe(priv)) {
                dev_notice(emac_dev, "DaVinci EMAC Probe found device "\
                           "(regs: %p, irq: %d)\n",
@@ -2904,13 +1912,15 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
        }
        return 0;
 
-mdiobus_quit:
-       mdiobus_free(emac_mii);
-
 netdev_reg_err:
-mdio_alloc_err:
        clk_disable(emac_clk);
 no_irq_res:
+       if (priv->txchan)
+               cpdma_chan_destroy(priv->txchan);
+       if (priv->rxchan)
+               cpdma_chan_destroy(priv->rxchan);
+       cpdma_ctlr_destroy(priv->dma);
+no_dma:
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
        iounmap(priv->remap_addr);
@@ -2938,8 +1948,12 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mdiobus_unregister(priv->mii_bus);
-       mdiobus_free(priv->mii_bus);
+
+       if (priv->txchan)
+               cpdma_chan_destroy(priv->txchan);
+       if (priv->rxchan)
+               cpdma_chan_destroy(priv->rxchan);
+       cpdma_ctlr_destroy(priv->dma);
 
        release_mem_region(res->start, res->end - res->start + 1);
 
diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
new file mode 100644 (file)
index 0000000..7615040
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * DaVinci MDIO Module driver
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Shamelessly ripped out of davinci_emac.c, original copyrights follow:
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ---------------------------------------------------------------------------
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/davinci_emac.h>
+
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define MDIO_TIMEOUT           100 /* msecs */
+
+#define PHY_REG_MASK           0x1f
+#define PHY_ID_MASK            0x1f
+
+#define DEF_OUT_FREQ           2200000         /* 2.2 MHz */
+
+struct davinci_mdio_regs {
+       u32     version;
+       u32     control;
+#define CONTROL_IDLE           BIT(31)
+#define CONTROL_ENABLE         BIT(30)
+#define CONTROL_MAX_DIV                (0xff)
+
+       u32     alive;
+       u32     link;
+       u32     linkintraw;
+       u32     linkintmasked;
+       u32     __reserved_0[2];
+       u32     userintraw;
+       u32     userintmasked;
+       u32     userintmaskset;
+       u32     userintmaskclr;
+       u32     __reserved_1[20];
+
+       struct {
+               u32     access;
+#define USERACCESS_GO          BIT(31)
+#define USERACCESS_WRITE       BIT(30)
+#define USERACCESS_ACK         BIT(29)
+#define USERACCESS_READ                (0)
+#define USERACCESS_DATA                (0xffff)
+
+               u32     physel;
+       }       user[0];
+};
+
+struct mdio_platform_data default_pdata = {
+       .bus_freq = DEF_OUT_FREQ,
+};
+
+struct davinci_mdio_data {
+       struct mdio_platform_data pdata;
+       struct davinci_mdio_regs __iomem *regs;
+       spinlock_t      lock;
+       struct clk      *clk;
+       struct device   *dev;
+       struct mii_bus  *bus;
+       bool            suspended;
+       unsigned long   access_time; /* jiffies */
+};
+
+static void __davinci_mdio_reset(struct davinci_mdio_data *data)
+{
+       u32 mdio_in, div, mdio_out_khz, access_time;
+
+       mdio_in = clk_get_rate(data->clk);
+       div = (mdio_in / data->pdata.bus_freq) - 1;
+       if (div > CONTROL_MAX_DIV)
+               div = CONTROL_MAX_DIV;
+
+       /* set enable and clock divider */
+       __raw_writel(div | CONTROL_ENABLE, &data->regs->control);
+
+       /*
+        * One mdio transaction consists of:
+        *      32 bits of preamble
+        *      32 bits of transferred data
+        *      24 bits of bus yield (not needed unless shared?)
+        */
+       mdio_out_khz = mdio_in / (1000 * (div + 1));
+       access_time  = (88 * 1000) / mdio_out_khz;
+
+       /*
+        * In the worst case, we could be kicking off a user-access immediately
+        * after the mdio bus scan state-machine triggered its own read.  If
+        * so, our request could get deferred by one access cycle.  We
+        * defensively allow for 4 access cycles.
+        */
+       data->access_time = usecs_to_jiffies(access_time * 4);
+       if (!data->access_time)
+               data->access_time = 1;
+}
+
+static int davinci_mdio_reset(struct mii_bus *bus)
+{
+       struct davinci_mdio_data *data = bus->priv;
+       u32 phy_mask, ver;
+
+       __davinci_mdio_reset(data);
+
+       /* wait for scan logic to settle */
+       msleep(PHY_MAX_ADDR * data->access_time);
+
+       /* dump hardware version info */
+       ver = __raw_readl(&data->regs->version);
+       dev_info(data->dev, "davinci mdio revision %d.%d\n",
+                (ver >> 8) & 0xff, ver & 0xff);
+
+       /* get phy mask from the alive register */
+       phy_mask = __raw_readl(&data->regs->alive);
+       if (phy_mask) {
+               /* restrict mdio bus to live phys only */
+               dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
+               phy_mask = ~phy_mask;
+       } else {
+               /* desperately scan all phys */
+               dev_warn(data->dev, "no live phy, scanning all\n");
+               phy_mask = 0;
+       }
+       data->bus->phy_mask = phy_mask;
+
+       return 0;
+}
+
+/* wait until hardware is ready for another user access */
+static inline int wait_for_user_access(struct davinci_mdio_data *data)
+{
+       struct davinci_mdio_regs __iomem *regs = data->regs;
+       unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+       u32 reg;
+
+       while (time_after(timeout, jiffies)) {
+               reg = __raw_readl(&regs->user[0].access);
+               if ((reg & USERACCESS_GO) == 0)
+                       return 0;
+
+               reg = __raw_readl(&regs->control);
+               if ((reg & CONTROL_IDLE) == 0)
+                       continue;
+
+               /*
+                * An emac soft_reset may have clobbered the mdio controller's
+                * state machine.  We need to reset and retry the current
+                * operation
+                */
+               dev_warn(data->dev, "resetting idled controller\n");
+               __davinci_mdio_reset(data);
+               return -EAGAIN;
+       }
+       dev_err(data->dev, "timed out waiting for user access\n");
+       return -ETIMEDOUT;
+}
+
+/* wait until hardware state machine is idle */
+static inline int wait_for_idle(struct davinci_mdio_data *data)
+{
+       struct davinci_mdio_regs __iomem *regs = data->regs;
+       unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+
+       while (time_after(timeout, jiffies)) {
+               if (__raw_readl(&regs->control) & CONTROL_IDLE)
+                       return 0;
+       }
+       dev_err(data->dev, "timed out waiting for idle\n");
+       return -ETIMEDOUT;
+}
+
+static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
+{
+       struct davinci_mdio_data *data = bus->priv;
+       u32 reg;
+       int ret;
+
+       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+               return -EINVAL;
+
+       spin_lock(&data->lock);
+
+       if (data->suspended) {
+               spin_unlock(&data->lock);
+               return -ENODEV;
+       }
+
+       reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
+              (phy_id << 16));
+
+       while (1) {
+               ret = wait_for_user_access(data);
+               if (ret == -EAGAIN)
+                       continue;
+               if (ret < 0)
+                       break;
+
+               __raw_writel(reg, &data->regs->user[0].access);
+
+               ret = wait_for_user_access(data);
+               if (ret == -EAGAIN)
+                       continue;
+               if (ret < 0)
+                       break;
+
+               reg = __raw_readl(&data->regs->user[0].access);
+               ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
+               break;
+       }
+
+       spin_unlock(&data->lock);
+
+       return ret;
+}
+
+static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
+                             int phy_reg, u16 phy_data)
+{
+       struct davinci_mdio_data *data = bus->priv;
+       u32 reg;
+       int ret;
+
+       if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+               return -EINVAL;
+
+       spin_lock(&data->lock);
+
+       if (data->suspended) {
+               spin_unlock(&data->lock);
+               return -ENODEV;
+       }
+
+       reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
+                  (phy_id << 16) | (phy_data & USERACCESS_DATA));
+
+       while (1) {
+               ret = wait_for_user_access(data);
+               if (ret == -EAGAIN)
+                       continue;
+               if (ret < 0)
+                       break;
+
+               __raw_writel(reg, &data->regs->user[0].access);
+
+               ret = wait_for_user_access(data);
+               if (ret == -EAGAIN)
+                       continue;
+               break;
+       }
+
+       spin_unlock(&data->lock);
+
+       return 0;
+}
+
+static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+{
+       struct mdio_platform_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct davinci_mdio_data *data;
+       struct resource *res;
+       struct phy_device *phy;
+       int ret, addr;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(dev, "failed to alloc device data\n");
+               return -ENOMEM;
+       }
+
+       data->pdata = pdata ? (*pdata) : default_pdata;
+
+       data->bus = mdiobus_alloc();
+       if (!data->bus) {
+               dev_err(dev, "failed to alloc mii bus\n");
+               ret = -ENOMEM;
+               goto bail_out;
+       }
+
+       data->bus->name         = dev_name(dev);
+       data->bus->read         = davinci_mdio_read,
+       data->bus->write        = davinci_mdio_write,
+       data->bus->reset        = davinci_mdio_reset,
+       data->bus->parent       = dev;
+       data->bus->priv         = data;
+       snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+       data->clk = clk_get(dev, NULL);
+       if (IS_ERR(data->clk)) {
+               data->clk = NULL;
+               dev_err(dev, "failed to get device clock\n");
+               ret = PTR_ERR(data->clk);
+               goto bail_out;
+       }
+
+       clk_enable(data->clk);
+
+       dev_set_drvdata(dev, data);
+       data->dev = dev;
+       spin_lock_init(&data->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(dev, "could not find register map resource\n");
+               ret = -ENOENT;
+               goto bail_out;
+       }
+
+       res = devm_request_mem_region(dev, res->start, resource_size(res),
+                                           dev_name(dev));
+       if (!res) {
+               dev_err(dev, "could not allocate register map resource\n");
+               ret = -ENXIO;
+               goto bail_out;
+       }
+
+       data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+       if (!data->regs) {
+               dev_err(dev, "could not map mdio registers\n");
+               ret = -ENOMEM;
+               goto bail_out;
+       }
+
+       /* register the mii bus */
+       ret = mdiobus_register(data->bus);
+       if (ret)
+               goto bail_out;
+
+       /* scan and dump the bus */
+       for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
+               phy = data->bus->phy_map[addr];
+               if (phy) {
+                       dev_info(dev, "phy[%d]: device %s, driver %s\n",
+                                phy->addr, dev_name(&phy->dev),
+                                phy->drv ? phy->drv->name : "unknown");
+               }
+       }
+
+       return 0;
+
+bail_out:
+       if (data->bus)
+               mdiobus_free(data->bus);
+
+       if (data->clk) {
+               clk_disable(data->clk);
+               clk_put(data->clk);
+       }
+
+       kfree(data);
+
+       return ret;
+}
+
+static int __devexit davinci_mdio_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct davinci_mdio_data *data = dev_get_drvdata(dev);
+
+       if (data->bus)
+               mdiobus_free(data->bus);
+
+       if (data->clk) {
+               clk_disable(data->clk);
+               clk_put(data->clk);
+       }
+
+       dev_set_drvdata(dev, NULL);
+
+       kfree(data);
+
+       return 0;
+}
+
+static int davinci_mdio_suspend(struct device *dev)
+{
+       struct davinci_mdio_data *data = dev_get_drvdata(dev);
+       u32 ctrl;
+
+       spin_lock(&data->lock);
+
+       /* shutdown the scan state machine */
+       ctrl = __raw_readl(&data->regs->control);
+       ctrl &= ~CONTROL_ENABLE;
+       __raw_writel(ctrl, &data->regs->control);
+       wait_for_idle(data);
+
+       if (data->clk)
+               clk_disable(data->clk);
+
+       data->suspended = true;
+       spin_unlock(&data->lock);
+
+       return 0;
+}
+
+static int davinci_mdio_resume(struct device *dev)
+{
+       struct davinci_mdio_data *data = dev_get_drvdata(dev);
+       u32 ctrl;
+
+       spin_lock(&data->lock);
+       if (data->clk)
+               clk_enable(data->clk);
+
+       /* restart the scan state machine */
+       ctrl = __raw_readl(&data->regs->control);
+       ctrl |= CONTROL_ENABLE;
+       __raw_writel(ctrl, &data->regs->control);
+
+       data->suspended = false;
+       spin_unlock(&data->lock);
+
+       return 0;
+}
+
+static const struct dev_pm_ops davinci_mdio_pm_ops = {
+       .suspend        = davinci_mdio_suspend,
+       .resume         = davinci_mdio_resume,
+};
+
+static struct platform_driver davinci_mdio_driver = {
+       .driver = {
+               .name    = "davinci_mdio",
+               .owner   = THIS_MODULE,
+               .pm      = &davinci_mdio_pm_ops,
+       },
+       .probe = davinci_mdio_probe,
+       .remove = __devexit_p(davinci_mdio_remove),
+};
+
+static int __init davinci_mdio_init(void)
+{
+       return platform_driver_register(&davinci_mdio_driver);
+}
+device_initcall(davinci_mdio_init);
+
+static void __exit davinci_mdio_exit(void)
+{
+       platform_driver_unregister(&davinci_mdio_driver);
+}
+module_exit(davinci_mdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DaVinci MDIO driver");
index f3f8be5..14f0955 100644 (file)
@@ -430,8 +430,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        }
 
        /* Get the protocol type of the ethernet frame that arrived */
-       proto_type = ((in_be32(addr + XEL_HEADER_OFFSET +
-                       XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) &
+       proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
+                       XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
                        XEL_RPLR_LENGTH_MASK);
 
        /* Check if received ethernet frame is a raw ethernet frame
@@ -439,9 +439,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
 
                if (proto_type == ETH_P_IP) {
-                       length = ((in_be32(addr +
+                       length = ((ntohl(in_be32(addr +
                                        XEL_HEADER_IP_LENGTH_OFFSET +
-                                       XEL_RXBUFF_OFFSET) >>
+                                       XEL_RXBUFF_OFFSET)) >>
                                        XEL_HEADER_SHIFT) &
                                        XEL_RPLR_LENGTH_MASK);
                        length += ETH_HLEN + ETH_FCS_LEN;
index 6acbff3..aa675eb 100644 (file)
@@ -4,7 +4,7 @@ config DTC
 config OF
        bool
 
-menu "Flattened Device Tree and Open Firmware support"
+menu "Device Tree and Open Firmware support"
        depends on OF
 
 config PROC_DEVICETREE
@@ -19,6 +19,9 @@ config OF_FLATTREE
        bool
        select DTC
 
+config OF_PROMTREE
+       bool
+
 config OF_DYNAMIC
        def_bool y
        depends on PPC_OF
index 0052c40..7888155 100644 (file)
@@ -1,5 +1,6 @@
 obj-y = base.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
+obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
 obj-$(CONFIG_OF_IRQ)    += irq.o
 obj-$(CONFIG_OF_DEVICE) += device.o platform.o
index fcadb72..3a1c7e7 100644 (file)
@@ -163,7 +163,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                        unsigned int *flags)
 {
-       const u32 *prop;
+       const __be32 *prop;
        unsigned int psize;
        struct device_node *parent;
        struct of_bus *bus;
index aa80525..710b53b 100644 (file)
@@ -33,7 +33,7 @@ DEFINE_RWLOCK(devtree_lock);
 
 int of_n_addr_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
 
 int of_n_size_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
index 92de0eb..45d8653 100644 (file)
@@ -81,29 +81,10 @@ struct device_attribute of_platform_device_attrs[] = {
        __ATTR_NULL
 };
 
-/**
- * of_release_dev - free an of device structure when all users of it are finished.
- * @dev: device that's been disconnected
- *
- * Will be called only by the device core when all users of this of device are
- * done.
- */
-void of_release_dev(struct device *dev)
-{
-       struct platform_device *ofdev;
-
-       ofdev = to_platform_device(dev);
-       of_node_put(ofdev->dev.of_node);
-       kfree(ofdev);
-}
-EXPORT_SYMBOL(of_release_dev);
-
-int of_device_register(struct platform_device *ofdev)
+int of_device_add(struct platform_device *ofdev)
 {
        BUG_ON(ofdev->dev.of_node == NULL);
 
-       device_initialize(&ofdev->dev);
-
        /* name and id have to be set so that the platform bus doesn't get
         * confused on matching */
        ofdev->name = dev_name(&ofdev->dev);
@@ -117,6 +98,12 @@ int of_device_register(struct platform_device *ofdev)
 
        return device_add(&ofdev->dev);
 }
+
+int of_device_register(struct platform_device *pdev)
+{
+       device_initialize(&pdev->dev);
+       return of_device_add(pdev);
+}
 EXPORT_SYMBOL(of_device_register);
 
 void of_device_unregister(struct platform_device *ofdev)
index 65da5ae..c1360e0 100644 (file)
@@ -533,8 +533,6 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
                strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
 
-       early_init_dt_scan_chosen_arch(node);
-
        pr_debug("Command line is: %s\n", cmd_line);
 
        /* break now */
index 6e595e5..75b0d3c 100644 (file)
 #include <linux/of_irq.h>
 #include <linux/string.h>
 
+/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
 /**
  * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
  * @device: Device node of the device whose interrupt is to be mapped
@@ -347,3 +352,37 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
        return irq;
 }
 EXPORT_SYMBOL_GPL(of_irq_to_resource);
+
+/**
+ * of_irq_count - Count the number of IRQs a node uses
+ * @dev: pointer to device tree node
+ */
+int of_irq_count(struct device_node *dev)
+{
+       int nr = 0;
+
+       while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ)
+               nr++;
+
+       return nr;
+}
+
+/**
+ * of_irq_to_resource_table - Fill in resource table with node's IRQ info
+ * @dev: pointer to device tree node
+ * @res: array of resources to fill in
+ * @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
+ *
+ * Returns the size of the filled in table (up to @nr_irqs).
+ */
+int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
+               int nr_irqs)
+{
+       int i;
+
+       for (i = 0; i < nr_irqs; i++, res++)
+               if (of_irq_to_resource(dev, i, res) == NO_IRQ)
+                       break;
+
+       return i;
+}
index 0a694de..c85d3c7 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_i2c.h>
 #include <linux/of_irq.h>
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
new file mode 100644 (file)
index 0000000..28295d0
--- /dev/null
@@ -0,0 +1,276 @@
+/* pdt.c: OF PROM device tree support code.
+ *
+ * Paul Mackerras      August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com
+ *
+ *  Adapted for sparc by David S. Miller davem@davemloft.net
+ *  Adapted for multiple architectures by Andres Salomon <dilinger@queued.net>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_pdt.h>
+#include <asm/prom.h>
+
+static struct of_pdt_ops *of_pdt_prom_ops __initdata;
+
+void __initdata (*of_pdt_build_more)(struct device_node *dp,
+               struct device_node ***nextp);
+
+#if defined(CONFIG_SPARC)
+unsigned int of_pdt_unique_id __initdata;
+
+#define of_pdt_incr_unique_id(p) do { \
+       (p)->unique_id = of_pdt_unique_id++; \
+} while (0)
+
+static inline const char *of_pdt_node_name(struct device_node *dp)
+{
+       return dp->path_component_name;
+}
+
+#else
+
+static inline void of_pdt_incr_unique_id(void *p) { }
+static inline void irq_trans_init(struct device_node *dp) { }
+
+static inline const char *of_pdt_node_name(struct device_node *dp)
+{
+       return dp->name;
+}
+
+#endif /* !CONFIG_SPARC */
+
+static struct property * __init of_pdt_build_one_prop(phandle node, char *prev,
+                                              char *special_name,
+                                              void *special_val,
+                                              int special_len)
+{
+       static struct property *tmp = NULL;
+       struct property *p;
+       int err;
+
+       if (tmp) {
+               p = tmp;
+               memset(p, 0, sizeof(*p) + 32);
+               tmp = NULL;
+       } else {
+               p = prom_early_alloc(sizeof(struct property) + 32);
+               of_pdt_incr_unique_id(p);
+       }
+
+       p->name = (char *) (p + 1);
+       if (special_name) {
+               strcpy(p->name, special_name);
+               p->length = special_len;
+               p->value = prom_early_alloc(special_len);
+               memcpy(p->value, special_val, special_len);
+       } else {
+               err = of_pdt_prom_ops->nextprop(node, prev, p->name);
+               if (err) {
+                       tmp = p;
+                       return NULL;
+               }
+               p->length = of_pdt_prom_ops->getproplen(node, p->name);
+               if (p->length <= 0) {
+                       p->length = 0;
+               } else {
+                       int len;
+
+                       p->value = prom_early_alloc(p->length + 1);
+                       len = of_pdt_prom_ops->getproperty(node, p->name,
+                                       p->value, p->length);
+                       if (len <= 0)
+                               p->length = 0;
+                       ((unsigned char *)p->value)[p->length] = '\0';
+               }
+       }
+       return p;
+}
+
+static struct property * __init of_pdt_build_prop_list(phandle node)
+{
+       struct property *head, *tail;
+
+       head = tail = of_pdt_build_one_prop(node, NULL,
+                                    ".node", &node, sizeof(node));
+
+       tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0);
+       tail = tail->next;
+       while(tail) {
+               tail->next = of_pdt_build_one_prop(node, tail->name,
+                                           NULL, NULL, 0);
+               tail = tail->next;
+       }
+
+       return head;
+}
+
+static char * __init of_pdt_get_one_property(phandle node, const char *name)
+{
+       char *buf = "<NULL>";
+       int len;
+
+       len = of_pdt_prom_ops->getproplen(node, name);
+       if (len > 0) {
+               buf = prom_early_alloc(len);
+               len = of_pdt_prom_ops->getproperty(node, name, buf, len);
+       }
+
+       return buf;
+}
+
+static char * __init of_pdt_try_pkg2path(phandle node)
+{
+       char *res, *buf = NULL;
+       int len;
+
+       if (!of_pdt_prom_ops->pkg2path)
+               return NULL;
+
+       if (of_pdt_prom_ops->pkg2path(node, buf, 0, &len))
+               return NULL;
+       buf = prom_early_alloc(len + 1);
+       if (of_pdt_prom_ops->pkg2path(node, buf, len, &len)) {
+               pr_err("%s: package-to-path failed\n", __func__);
+               return NULL;
+       }
+
+       res = strrchr(buf, '/');
+       if (!res) {
+               pr_err("%s: couldn't find / in %s\n", __func__, buf);
+               return NULL;
+       }
+       return res+1;
+}
+
+/*
+ * When fetching the node's name, first try using package-to-path; if
+ * that fails (either because the arch hasn't supplied a PROM callback,
+ * or some other random failure), fall back to just looking at the node's
+ * 'name' property.
+ */
+static char * __init of_pdt_build_name(phandle node)
+{
+       char *buf;
+
+       buf = of_pdt_try_pkg2path(node);
+       if (!buf)
+               buf = of_pdt_get_one_property(node, "name");
+
+       return buf;
+}
+
+static struct device_node * __init of_pdt_create_node(phandle node,
+                                                   struct device_node *parent)
+{
+       struct device_node *dp;
+
+       if (!node)
+               return NULL;
+
+       dp = prom_early_alloc(sizeof(*dp));
+       of_pdt_incr_unique_id(dp);
+       dp->parent = parent;
+
+       kref_init(&dp->kref);
+
+       dp->name = of_pdt_build_name(node);
+       dp->type = of_pdt_get_one_property(node, "device_type");
+       dp->phandle = node;
+
+       dp->properties = of_pdt_build_prop_list(node);
+
+       irq_trans_init(dp);
+
+       return dp;
+}
+
+static char * __init of_pdt_build_full_name(struct device_node *dp)
+{
+       int len, ourlen, plen;
+       char *n;
+
+       plen = strlen(dp->parent->full_name);
+       ourlen = strlen(of_pdt_node_name(dp));
+       len = ourlen + plen + 2;
+
+       n = prom_early_alloc(len);
+       strcpy(n, dp->parent->full_name);
+       if (!of_node_is_root(dp->parent)) {
+               strcpy(n + plen, "/");
+               plen++;
+       }
+       strcpy(n + plen, of_pdt_node_name(dp));
+
+       return n;
+}
+
+static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
+                                                  phandle node,
+                                                  struct device_node ***nextp)
+{
+       struct device_node *ret = NULL, *prev_sibling = NULL;
+       struct device_node *dp;
+
+       while (1) {
+               dp = of_pdt_create_node(node, parent);
+               if (!dp)
+                       break;
+
+               if (prev_sibling)
+                       prev_sibling->sibling = dp;
+
+               if (!ret)
+                       ret = dp;
+               prev_sibling = dp;
+
+               *(*nextp) = dp;
+               *nextp = &dp->allnext;
+
+#if defined(CONFIG_SPARC)
+               dp->path_component_name = build_path_component(dp);
+#endif
+               dp->full_name = of_pdt_build_full_name(dp);
+
+               dp->child = of_pdt_build_tree(dp,
+                               of_pdt_prom_ops->getchild(node), nextp);
+
+               if (of_pdt_build_more)
+                       of_pdt_build_more(dp, nextp);
+
+               node = of_pdt_prom_ops->getsibling(node);
+       }
+
+       return ret;
+}
+
+void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
+{
+       struct device_node **nextp;
+
+       BUG_ON(!ops);
+       of_pdt_prom_ops = ops;
+
+       allnodes = of_pdt_create_node(root_node, NULL);
+#if defined(CONFIG_SPARC)
+       allnodes->path_component_name = "";
+#endif
+       allnodes->full_name = "/";
+
+       nextp = &allnodes->allnext;
+       allnodes->child = of_pdt_build_tree(allnodes,
+                       of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+}
index bb72223..5b4a07f 100644 (file)
@@ -584,34 +584,33 @@ struct platform_device *of_device_alloc(struct device_node *np,
                                  struct device *parent)
 {
        struct platform_device *dev;
-       int rc, i, num_reg = 0, num_irq = 0;
+       int rc, i, num_reg = 0, num_irq;
        struct resource *res, temp_res;
 
-       /* First count how many resources are needed */
-       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-               num_reg++;
-       while (of_irq_to_resource(np, num_irq, &temp_res) != NO_IRQ)
-               num_irq++;
-
-       /* Allocate memory for both the struct device and the resource table */
-       dev = kzalloc(sizeof(*dev) + (sizeof(*res) * (num_reg + num_irq)),
-                     GFP_KERNEL);
+       dev = platform_device_alloc("", -1);
        if (!dev)
                return NULL;
-       res = (struct resource *) &dev[1];
+
+       /* count the io and irq resources */
+       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
+               num_reg++;
+       num_irq = of_irq_count(np);
 
        /* Populate the resource table */
        if (num_irq || num_reg) {
+               res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+               if (!res) {
+                       platform_device_put(dev);
+                       return NULL;
+               }
+
                dev->num_resources = num_reg + num_irq;
                dev->resource = res;
                for (i = 0; i < num_reg; i++, res++) {
                        rc = of_address_to_resource(np, i, res);
                        WARN_ON(rc);
                }
-               for (i = 0; i < num_irq; i++, res++) {
-                       rc = of_irq_to_resource(np, i, res);
-                       WARN_ON(rc == NO_IRQ);
-               }
+               WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
        }
 
        dev->dev.of_node = of_node_get(np);
@@ -619,7 +618,6 @@ struct platform_device *of_device_alloc(struct device_node *np,
        dev->dev.dma_mask = &dev->archdata.dma_mask;
 #endif
        dev->dev.parent = parent;
-       dev->dev.release = of_release_dev;
 
        if (bus_id)
                dev_set_name(&dev->dev, "%s", bus_id);
@@ -657,8 +655,8 @@ struct platform_device *of_platform_device_create(struct device_node *np,
         * to do such, possibly using a device notifier
         */
 
-       if (of_device_register(dev) != 0) {
-               of_device_free(dev);
+       if (of_device_add(dev) != 0) {
+               platform_device_put(dev);
                return NULL;
        }
 
index cff7cc2..faec777 100644 (file)
@@ -92,6 +92,7 @@ config DELL_WMI
        tristate "Dell WMI extras"
        depends on ACPI_WMI
        depends on INPUT
+       select INPUT_SPARSEKMAP
        ---help---
          Say Y here if you want to support WMI-based hotkeys on Dell laptops.
 
@@ -140,6 +141,7 @@ config HP_WMI
        depends on ACPI_WMI
        depends on INPUT
        depends on RFKILL || RFKILL = n
+       select INPUT_SPARSEKMAP
        help
         Say Y here if you want to support WMI-based hotkeys on HP laptops and
         to read data from WMI such as docking or ambient light sensor state.
@@ -171,6 +173,7 @@ config PANASONIC_LAPTOP
        tristate "Panasonic Laptop Extras"
        depends on INPUT && ACPI
        depends on BACKLIGHT_CLASS_DEVICE
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for access to backlight control and hotkeys
          on Panasonic Let's Note laptops.
@@ -219,8 +222,8 @@ config SONYPI_COMPAT
          ---help---
          Build the sonypi driver compatibility code into the sony-laptop driver.
 
-config IDEAPAD_ACPI
-       tristate "Lenovo IdeaPad ACPI Laptop Extras"
+config IDEAPAD_LAPTOP
+       tristate "Lenovo IdeaPad Laptop Extras"
        depends on ACPI
        depends on RFKILL
        help
@@ -365,6 +368,26 @@ config THINKPAD_ACPI_HOTKEY_POLL
          If you are not sure, say Y here.  The driver enables polling only if
          it is strictly necessary to do so.
 
+config SENSORS_HDAPS
+       tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
+       depends on INPUT && X86
+       select INPUT_POLLDEV
+       default n
+       help
+         This driver provides support for the IBM Hard Drive Active Protection
+         System (hdaps), which provides an accelerometer and other misc. data.
+         ThinkPads starting with the R50, T41, and X40 are supported.  The
+         accelerometer data is readable via sysfs.
+
+         This driver also provides an absolute input class device, allowing
+         the laptop to act as a pinball machine-esque joystick.
+
+         If your ThinkPad is not recognized by the driver, please update to latest
+         BIOS. This is especially the case for some R52 ThinkPads.
+
+         Say Y here if you have an applicable laptop and want to experience
+         the awesome power of hdaps.
+
 config INTEL_MENLOW
        tristate "Thermal Management driver for Intel menlow platform"
        depends on ACPI_THERMAL
@@ -478,6 +501,7 @@ config TOPSTAR_LAPTOP
        tristate "Topstar Laptop Extras"
        depends on ACPI
        depends on INPUT
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for hotkeys found on Topstar laptops.
 
@@ -492,6 +516,7 @@ config ACPI_TOSHIBA
        depends on INPUT
        depends on RFKILL || RFKILL = n
        select INPUT_POLLDEV
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for access to certain system settings
          on "legacy free" Toshiba laptops.  These laptops can be recognized by
@@ -590,4 +615,28 @@ config INTEL_IPS
          functionality.  If in doubt, say Y here; it will only load on
          supported platforms.
 
+config IBM_RTL
+       tristate "Device driver to enable PRTL support"
+       depends on X86 && PCI
+       ---help---
+        Enable support for IBM Premium Real Time Mode (PRTM).
+        This module will allow you the enter and exit PRTM in the BIOS via
+        sysfs on platforms that support this feature.  System in PRTM will
+        not receive CPU-generated SMIs for recoverable errors.  Use of this
+        feature without proper support may void your hardware warranty.
+
+        If the proper BIOS support is found the driver will load and create
+        /sys/devices/system/ibm_rtl/.  The "state" variable will indicate
+        whether or not the BIOS is in PRTM.
+        state = 0 (BIOS SMIs on)
+        state = 1 (BIOS SMIs off)
+
+config XO1_RFKILL
+       tristate "OLPC XO-1 software RF kill switch"
+       depends on OLPC
+       depends on RFKILL
+       ---help---
+         Support for enabling/disabling the WLAN interface on the OLPC XO-1
+         laptop.
+
 endif # X86_PLATFORM_DEVICES
index 85fb2b8..9950ccc 100644 (file)
@@ -15,8 +15,9 @@ obj-$(CONFIG_ACERHDF)         += acerhdf.o
 obj-$(CONFIG_HP_WMI)           += hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)       += tc1100-wmi.o
 obj-$(CONFIG_SONY_LAPTOP)      += sony-laptop.o
-obj-$(CONFIG_IDEAPAD_ACPI)     += ideapad_acpi.o
+obj-$(CONFIG_IDEAPAD_LAPTOP)   += ideapad-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)    += thinkpad_acpi.o
+obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_FUJITSU_LAPTOP)   += fujitsu-laptop.o
 obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
 obj-$(CONFIG_INTEL_MENLOW)     += intel_menlow.o
@@ -30,4 +31,5 @@ obj-$(CONFIG_INTEL_SCU_IPC)   += intel_scu_ipc.o
 obj-$(CONFIG_RAR_REGISTER)     += intel_rar_register.o
 obj-$(CONFIG_INTEL_IPS)                += intel_ips.o
 obj-$(CONFIG_GPIO_INTEL_PMIC)  += intel_pmic_gpio.o
-
+obj-$(CONFIG_XO1_RFKILL)       += xo1-rfkill.o
+obj-$(CONFIG_IBM_RTL)          += ibm_rtl.o
index 2badee2..c8c6537 100644 (file)
@@ -1314,7 +1314,7 @@ static int __init acer_wmi_init(void)
                AMW0_find_mailled();
 
        if (!interface) {
-               printk(ACER_ERR "No or unsupported WMI interface, unable to "
+               printk(ACER_INFO "No or unsupported WMI interface, unable to "
                                "load\n");
                return -ENODEV;
        }
index b756e07..60a5a5c 100644 (file)
@@ -236,7 +236,6 @@ struct asus_laptop {
        u8 light_level;         /* light sensor level */
        u8 light_switch;        /* light sensor switch value */
        u16 event_count[128];   /* count for each event TODO make this better */
-       u16 *keycode_map;
 };
 
 static const struct key_entry asus_keymap[] = {
@@ -278,6 +277,7 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x99, { KEY_PHONE } },
        {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
        {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+       {KE_KEY, 0xb5, { KEY_CALC } },
        {KE_END, 0},
 };
 
@@ -639,29 +639,29 @@ static int asus_backlight_notify(struct asus_laptop *asus)
 static int asus_backlight_init(struct asus_laptop *asus)
 {
        struct backlight_device *bd;
-       struct device *dev = &asus->platform_device->dev;
        struct backlight_properties props;
 
-       if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
-           lcd_switch_handle) {
-               memset(&props, 0, sizeof(struct backlight_properties));
-               props.max_brightness = 15;
-
-               bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
-                                              asus, &asusbl_ops, &props);
-               if (IS_ERR(bd)) {
-                       pr_err("Could not register asus backlight device\n");
-                       asus->backlight_device = NULL;
-                       return PTR_ERR(bd);
-               }
+       if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
+           acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
+           !lcd_switch_handle)
+               return 0;
 
-               asus->backlight_device = bd;
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = 15;
 
-               bd->props.power = FB_BLANK_UNBLANK;
-               bd->props.brightness = asus_read_brightness(bd);
-               backlight_update_status(bd);
+       bd = backlight_device_register(ASUS_LAPTOP_FILE,
+                                      &asus->platform_device->dev, asus,
+                                      &asusbl_ops, &props);
+       if (IS_ERR(bd)) {
+               pr_err("Could not register asus backlight device\n");
+               asus->backlight_device = NULL;
+               return PTR_ERR(bd);
        }
+
+       asus->backlight_device = bd;
+       bd->props.brightness = asus_read_brightness(bd);
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
        return 0;
 }
 
@@ -1065,9 +1065,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
  */
 static int asus_gps_rfkill_set(void *data, bool blocked)
 {
-       acpi_handle handle = data;
+       struct asus_laptop *asus = data;
 
-       return asus_gps_switch(handle, !blocked);
+       return asus_gps_switch(asus, !blocked);
 }
 
 static const struct rfkill_ops asus_gps_rfkill_ops = {
@@ -1094,7 +1094,7 @@ static int asus_rfkill_init(struct asus_laptop *asus)
 
        asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
                                        RFKILL_TYPE_GPS,
-                                       &asus_gps_rfkill_ops, NULL);
+                                       &asus_gps_rfkill_ops, asus);
        if (!asus->gps_rfkill)
                return -EINVAL;
 
@@ -1130,7 +1130,6 @@ static int asus_input_init(struct asus_laptop *asus)
        input->phys = ASUS_LAPTOP_FILE "/input0";
        input->id.bustype = BUS_HOST;
        input->dev.parent = &asus->platform_device->dev;
-       input_set_drvdata(input, asus);
 
        error = sparse_keymap_setup(input, asus_keymap, NULL);
        if (error) {
@@ -1159,6 +1158,7 @@ static void asus_input_exit(struct asus_laptop *asus)
                sparse_keymap_free(asus->inputdev);
                input_unregister_device(asus->inputdev);
        }
+       asus->inputdev = NULL;
 }
 
 /*
@@ -1200,111 +1200,100 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
 
 static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
 static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
-static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
-                  store_bluetooth);
+static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
+                  show_bluetooth, store_bluetooth);
 static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
 static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
 static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
 
-static void asus_sysfs_exit(struct asus_laptop *asus)
-{
-       struct platform_device *device = asus->platform_device;
-
-       device_remove_file(&device->dev, &dev_attr_infos);
-       device_remove_file(&device->dev, &dev_attr_wlan);
-       device_remove_file(&device->dev, &dev_attr_bluetooth);
-       device_remove_file(&device->dev, &dev_attr_display);
-       device_remove_file(&device->dev, &dev_attr_ledd);
-       device_remove_file(&device->dev, &dev_attr_ls_switch);
-       device_remove_file(&device->dev, &dev_attr_ls_level);
-       device_remove_file(&device->dev, &dev_attr_gps);
-}
+static struct attribute *asus_attributes[] = {
+       &dev_attr_infos.attr,
+       &dev_attr_wlan.attr,
+       &dev_attr_bluetooth.attr,
+       &dev_attr_display.attr,
+       &dev_attr_ledd.attr,
+       &dev_attr_ls_level.attr,
+       &dev_attr_ls_switch.attr,
+       &dev_attr_gps.attr,
+       NULL
+};
 
-static int asus_sysfs_init(struct asus_laptop *asus)
+static mode_t asus_sysfs_is_visible(struct kobject *kobj,
+                                   struct attribute *attr,
+                                   int idx)
 {
-       struct platform_device *device = asus->platform_device;
-       int err;
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct asus_laptop *asus = platform_get_drvdata(pdev);
+       acpi_handle handle = asus->handle;
+       bool supported;
 
-       err = device_create_file(&device->dev, &dev_attr_infos);
-       if (err)
-               return err;
+       if (attr == &dev_attr_wlan.attr) {
+               supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_wlan);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_bluetooth.attr) {
+               supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_bluetooth);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_display.attr) {
+               supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_display);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_ledd.attr) {
+               supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_ledd);
-               if (err)
-                       return err;
-       }
-
-       if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_ls_switch);
-               if (err)
-                       return err;
-               err = device_create_file(&device->dev, &dev_attr_ls_level);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_ls_switch.attr ||
+                  attr == &dev_attr_ls_level.attr) {
+               supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
+                           !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_gps);
-               if (err)
-                       return err;
+       } else if (attr == &dev_attr_gps.attr) {
+               supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
+                           !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
+                           !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
+       } else {
+               supported = true;
        }
 
-       return err;
+       return supported ? attr->mode : 0;
 }
 
+
+static const struct attribute_group asus_attr_group = {
+       .is_visible     = asus_sysfs_is_visible,
+       .attrs          = asus_attributes,
+};
+
 static int asus_platform_init(struct asus_laptop *asus)
 {
-       int err;
+       int result;
 
        asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
        if (!asus->platform_device)
                return -ENOMEM;
        platform_set_drvdata(asus->platform_device, asus);
 
-       err = platform_device_add(asus->platform_device);
-       if (err)
+       result = platform_device_add(asus->platform_device);
+       if (result)
                goto fail_platform_device;
 
-       err = asus_sysfs_init(asus);
-       if (err)
+       result = sysfs_create_group(&asus->platform_device->dev.kobj,
+                                   &asus_attr_group);
+       if (result)
                goto fail_sysfs;
+
        return 0;
 
 fail_sysfs:
-       asus_sysfs_exit(asus);
        platform_device_del(asus->platform_device);
 fail_platform_device:
        platform_device_put(asus->platform_device);
-       return err;
+       return result;
 }
 
 static void asus_platform_exit(struct asus_laptop *asus)
 {
-       asus_sysfs_exit(asus);
+       sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
        platform_device_unregister(asus->platform_device);
 }
 
@@ -1428,8 +1417,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
        return AE_OK;
 }
 
-static bool asus_device_present;
-
 static int __devinit asus_acpi_init(struct asus_laptop *asus)
 {
        int result = 0;
@@ -1474,6 +1461,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        return result;
 }
 
+static bool asus_device_present;
+
 static int __devinit asus_acpi_add(struct acpi_device *device)
 {
        struct asus_laptop *asus;
index 4413975..cf8a89a 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/mm.h>
 #include <linux/i8042.h>
 #include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
@@ -325,6 +327,75 @@ static const struct rfkill_ops dell_rfkill_ops = {
        .query = dell_rfkill_query,
 };
 
+static struct dentry *dell_laptop_dir;
+
+static int dell_debugfs_show(struct seq_file *s, void *data)
+{
+       int status;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+       release_buffer();
+
+       seq_printf(s, "status:\t0x%X\n", status);
+       seq_printf(s, "Bit 0 : Hardware switch supported:   %lu\n",
+                  status & BIT(0));
+       seq_printf(s, "Bit 1 : Wifi locator supported:      %lu\n",
+                 (status & BIT(1)) >> 1);
+       seq_printf(s, "Bit 2 : Wifi is supported:           %lu\n",
+                 (status & BIT(2)) >> 2);
+       seq_printf(s, "Bit 3 : Bluetooth is supported:      %lu\n",
+                 (status & BIT(3)) >> 3);
+       seq_printf(s, "Bit 4 : WWAN is supported:           %lu\n",
+                 (status & BIT(4)) >> 4);
+       seq_printf(s, "Bit 5 : Wireless keyboard supported: %lu\n",
+                 (status & BIT(5)) >> 5);
+       seq_printf(s, "Bit 8 : Wifi is installed:           %lu\n",
+                 (status & BIT(8)) >> 8);
+       seq_printf(s, "Bit 9 : Bluetooth is installed:      %lu\n",
+                 (status & BIT(9)) >> 9);
+       seq_printf(s, "Bit 10: WWAN is installed:           %lu\n",
+                 (status & BIT(10)) >> 10);
+       seq_printf(s, "Bit 16: Hardware switch is on:       %lu\n",
+                 (status & BIT(16)) >> 16);
+       seq_printf(s, "Bit 17: Wifi is blocked:             %lu\n",
+                 (status & BIT(17)) >> 17);
+       seq_printf(s, "Bit 18: Bluetooth is blocked:        %lu\n",
+                 (status & BIT(18)) >> 18);
+       seq_printf(s, "Bit 19: WWAN is blocked:             %lu\n",
+                 (status & BIT(19)) >> 19);
+
+       seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
+       seq_printf(s, "Bit 0 : Wifi controlled by switch:      %lu\n",
+                  hwswitch_state & BIT(0));
+       seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
+                  (hwswitch_state & BIT(1)) >> 1);
+       seq_printf(s, "Bit 2 : WWAN controlled by switch:      %lu\n",
+                  (hwswitch_state & BIT(2)) >> 2);
+       seq_printf(s, "Bit 7 : Wireless switch config locked:  %lu\n",
+                  (hwswitch_state & BIT(7)) >> 7);
+       seq_printf(s, "Bit 8 : Wifi locator enabled:           %lu\n",
+                  (hwswitch_state & BIT(8)) >> 8);
+       seq_printf(s, "Bit 15: Wifi locator setting locked:    %lu\n",
+                  (hwswitch_state & BIT(15)) >> 15);
+
+       return 0;
+}
+
+static int dell_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dell_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations dell_debugfs_fops = {
+       .owner = THIS_MODULE,
+       .open = dell_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 static void dell_update_rfkill(struct work_struct *ignored)
 {
        if (wifi_rfkill)
@@ -556,6 +627,11 @@ static int __init dell_init(void)
                goto fail_filter;
        }
 
+       dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
+       if (dell_laptop_dir != NULL)
+               debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
+                                   &dell_debugfs_fops);
+
 #ifdef CONFIG_ACPI
        /* In the event of an ACPI backlight being available, don't
         * register the platform controller.
@@ -615,6 +691,7 @@ fail_platform_driver:
 
 static void __exit dell_exit(void)
 {
+       debugfs_remove_recursive(dell_laptop_dir);
        i8042_remove_filter(dell_laptop_i8042_filter);
        cancel_delayed_work_sync(&dell_rfkill_work);
        backlight_device_unregister(dell_backlight_device);
index 08fb70f..77f1d55 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
@@ -44,78 +45,70 @@ static int acpi_video;
 
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
-struct key_entry {
-       char type;              /* See KE_* below */
-       u16 code;
-       u16 keycode;
-};
-
-enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
-
 /*
  * Certain keys are flagged as KE_IGNORE. All of these are either
  * notifications (rather than requests for change) or are also sent
  * via the keyboard controller so should not be sent again.
  */
 
-static struct key_entry dell_legacy_wmi_keymap[] = {
-       {KE_KEY, 0xe045, KEY_PROG1},
-       {KE_KEY, 0xe009, KEY_EJECTCD},
+static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+       { KE_KEY, 0xe045, { KEY_PROG1 } },
+       { KE_KEY, 0xe009, { KEY_EJECTCD } },
 
        /* These also contain the brightness level at offset 6 */
-       {KE_KEY, 0xe006, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN},
+       { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
 
        /* Battery health status button */
-       {KE_KEY, 0xe007, KEY_BATTERY},
+       { KE_KEY, 0xe007, { KEY_BATTERY } },
 
        /* This is actually for all radios. Although physically a
         * switch, the notification does not provide an indication of
         * state and so it should be reported as a key */
-       {KE_KEY, 0xe008, KEY_WLAN},
+       { KE_KEY, 0xe008, { KEY_WLAN } },
 
        /* The next device is at offset 6, the active devices are at
           offset 8 and the attached devices at offset 10 */
-       {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
+       { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
 
-       {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
+       { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
 
        /* BIOS error detected */
-       {KE_IGNORE, 0xe00d, KEY_RESERVED},
+       { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
 
        /* Wifi Catcher */
-       {KE_KEY, 0xe011, KEY_PROG2},
+       { KE_KEY, 0xe011, {KEY_PROG2 } },
 
        /* Ambient light sensor toggle */
-       {KE_IGNORE, 0xe013, KEY_RESERVED},
-
-       {KE_IGNORE, 0xe020, KEY_MUTE},
-       {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN},
-       {KE_IGNORE, 0xe030, KEY_VOLUMEUP},
-       {KE_IGNORE, 0xe033, KEY_KBDILLUMUP},
-       {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN},
-       {KE_IGNORE, 0xe03a, KEY_CAPSLOCK},
-       {KE_IGNORE, 0xe045, KEY_NUMLOCK},
-       {KE_IGNORE, 0xe046, KEY_SCROLLLOCK},
-       {KE_END, 0}
+       { KE_IGNORE, 0xe013, { KEY_RESERVED } },
+
+       { KE_IGNORE, 0xe020, { KEY_MUTE } },
+       { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
+       { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
+       { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
+       { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
+       { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
+       { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
+       { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+       { KE_END, 0 }
 };
 
 static bool dell_new_hk_type;
 
-struct dell_new_keymap_entry {
+struct dell_bios_keymap_entry {
        u16 scancode;
        u16 keycode;
 };
 
-struct dell_hotkey_table {
+struct dell_bios_hotkey_table {
        struct dmi_header header;
-       struct dell_new_keymap_entry keymap[];
+       struct dell_bios_keymap_entry keymap[];
 
 };
 
-static struct key_entry *dell_new_wmi_keymap;
+static const struct dell_bios_hotkey_table *dell_bios_hotkey_table;
 
-static u16 bios_to_linux_keycode[256] = {
+static const u16 bios_to_linux_keycode[256] __initconst = {
 
        KEY_MEDIA,      KEY_NEXTSONG,   KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
        KEY_STOPCD,     KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_UNKNOWN,
@@ -138,68 +131,11 @@ static u16 bios_to_linux_keycode[256] = {
        KEY_PROG3
 };
 
-
-static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
-
 static struct input_dev *dell_wmi_input_dev;
 
-static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode)
-{
-       struct key_entry *key;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++)
-               if (key->type == KE_KEY && keycode == key->keycode)
-                       return key;
-
-       return NULL;
-}
-
-static int dell_wmi_getkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int dell_wmi_setkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = dell_wmi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!dell_wmi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-       return -EINVAL;
-}
-
 static void dell_wmi_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-       static struct key_entry *key;
        union acpi_object *obj;
        acpi_status status;
 
@@ -212,8 +148,10 @@ static void dell_wmi_notify(u32 value, void *context)
        obj = (union acpi_object *)response.pointer;
 
        if (obj && obj->type == ACPI_TYPE_BUFFER) {
+               const struct key_entry *key;
                int reported_key;
                u16 *buffer_entry = (u16 *)obj->buffer.pointer;
+
                if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
                        printk(KERN_INFO "dell-wmi: Received unknown WMI event"
                                         " (0x%x)\n", buffer_entry[1]);
@@ -226,8 +164,8 @@ static void dell_wmi_notify(u32 value, void *context)
                else
                        reported_key = (int)buffer_entry[1] & 0xffff;
 
-               key = dell_wmi_get_entry_by_scancode(reported_key);
-
+               key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
+                                                       reported_key);
                if (!key) {
                        printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
                                reported_key);
@@ -237,92 +175,98 @@ static void dell_wmi_notify(u32 value, void *context)
                         * come via ACPI */
                        ;
                } else {
-                       input_report_key(dell_wmi_input_dev, key->keycode, 1);
-                       input_sync(dell_wmi_input_dev);
-                       input_report_key(dell_wmi_input_dev, key->keycode, 0);
-                       input_sync(dell_wmi_input_dev);
+                       sparse_keymap_report_entry(dell_wmi_input_dev, key,
+                                                  1, true);
                }
        }
        kfree(obj);
 }
 
-
-static void setup_new_hk_map(const struct dmi_header *dm)
+static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
 {
-
+       int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
+                               sizeof(struct dell_bios_keymap_entry);
+       struct key_entry *keymap;
        int i;
-       int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
-       struct dell_hotkey_table *table =
-               container_of(dm, struct dell_hotkey_table, header);
 
-       dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
-                                     sizeof(struct key_entry), GFP_KERNEL);
+       keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL);
+       if (!keymap)
+               return NULL;
 
        for (i = 0; i < hotkey_num; i++) {
-               dell_new_wmi_keymap[i].type = KE_KEY;
-               dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
-               dell_new_wmi_keymap[i].keycode =
-                       (table->keymap[i].keycode > 255) ? 0 :
-                       bios_to_linux_keycode[table->keymap[i].keycode];
+               const struct dell_bios_keymap_entry *bios_entry =
+                                       &dell_bios_hotkey_table->keymap[i];
+               keymap[i].type = KE_KEY;
+               keymap[i].code = bios_entry->scancode;
+               keymap[i].keycode = bios_entry->keycode < 256 ?
+                                   bios_to_linux_keycode[bios_entry->keycode] :
+                                   KEY_RESERVED;
        }
 
-       dell_new_wmi_keymap[i].type = KE_END;
-       dell_new_wmi_keymap[i].code = 0;
-       dell_new_wmi_keymap[i].keycode = 0;
-
-       dell_wmi_keymap = dell_new_wmi_keymap;
+       keymap[hotkey_num].type = KE_END;
 
+       return keymap;
 }
 
-
-static void find_hk_type(const struct dmi_header *dm, void *dummy)
-{
-
-       if ((dm->type == 0xb2) && (dm->length > 6)) {
-               dell_new_hk_type = true;
-               setup_new_hk_map(dm);
-       }
-
-}
-
-
 static int __init dell_wmi_input_setup(void)
 {
-       struct key_entry *key;
        int err;
 
        dell_wmi_input_dev = input_allocate_device();
-
        if (!dell_wmi_input_dev)
                return -ENOMEM;
 
        dell_wmi_input_dev->name = "Dell WMI hotkeys";
        dell_wmi_input_dev->phys = "wmi/input0";
        dell_wmi_input_dev->id.bustype = BUS_HOST;
-       dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode;
-       dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++) {
-               switch (key->type) {
-               case KE_KEY:
-                       set_bit(EV_KEY, dell_wmi_input_dev->evbit);
-                       set_bit(key->keycode, dell_wmi_input_dev->keybit);
-                       break;
-               case KE_SW:
-                       set_bit(EV_SW, dell_wmi_input_dev->evbit);
-                       set_bit(key->keycode, dell_wmi_input_dev->swbit);
-                       break;
+
+       if (dell_new_hk_type) {
+               const struct key_entry *keymap = dell_wmi_prepare_new_keymap();
+               if (!keymap) {
+                       err = -ENOMEM;
+                       goto err_free_dev;
                }
-       }
 
-       err = input_register_device(dell_wmi_input_dev);
+               err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
 
-       if (err) {
-               input_free_device(dell_wmi_input_dev);
-               return err;
+               /*
+                * Sparse keymap library makes a copy of keymap so we
+                * don't need the original one that was allocated.
+                */
+               kfree(keymap);
+       } else {
+               err = sparse_keymap_setup(dell_wmi_input_dev,
+                                         dell_wmi_legacy_keymap, NULL);
        }
+       if (err)
+               goto err_free_dev;
+
+       err = input_register_device(dell_wmi_input_dev);
+       if (err)
+               goto err_free_keymap;
 
        return 0;
+
+ err_free_keymap:
+       sparse_keymap_free(dell_wmi_input_dev);
+ err_free_dev:
+       input_free_device(dell_wmi_input_dev);
+       return err;
+}
+
+static void dell_wmi_input_destroy(void)
+{
+       sparse_keymap_free(dell_wmi_input_dev);
+       input_unregister_device(dell_wmi_input_dev);
+}
+
+static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
+{
+       if (dm->type == 0xb2 && dm->length > 6) {
+               dell_new_hk_type = true;
+               dell_bios_hotkey_table =
+                       container_of(dm, struct dell_bios_hotkey_table, header);
+       }
 }
 
 static int __init dell_wmi_init(void)
@@ -339,18 +283,13 @@ static int __init dell_wmi_init(void)
        acpi_video = acpi_video_backlight_support();
 
        err = dell_wmi_input_setup();
-       if (err) {
-               if (dell_new_hk_type)
-                       kfree(dell_wmi_keymap);
+       if (err)
                return err;
-       }
 
        status = wmi_install_notify_handler(DELL_EVENT_GUID,
                                         dell_wmi_notify, NULL);
        if (ACPI_FAILURE(status)) {
-               input_unregister_device(dell_wmi_input_dev);
-               if (dell_new_hk_type)
-                       kfree(dell_wmi_keymap);
+               dell_wmi_input_destroy();
                printk(KERN_ERR
                        "dell-wmi: Unable to register notify handler - %d\n",
                        status);
@@ -359,14 +298,11 @@ static int __init dell_wmi_init(void)
 
        return 0;
 }
+module_init(dell_wmi_init);
 
 static void __exit dell_wmi_exit(void)
 {
        wmi_remove_notify_handler(DELL_EVENT_GUID);
-       input_unregister_device(dell_wmi_input_dev);
-       if (dell_new_hk_type)
-               kfree(dell_wmi_keymap);
+       dell_wmi_input_destroy();
 }
-
-module_init(dell_wmi_init);
 module_exit(dell_wmi_exit);
index 6b8e062..b2edfdc 100644 (file)
@@ -165,6 +165,7 @@ struct eeepc_laptop {
        u16 event_count[128];           /* count for each event */
 
        struct platform_device *platform_device;
+       struct acpi_device *device;             /* the device we are in */
        struct device *hwmon_device;
        struct backlight_device *backlight_device;
 
@@ -1193,9 +1194,9 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
        eeepc->inputdev = input;
        return 0;
 
- err_free_keymap:
+err_free_keymap:
        sparse_keymap_free(input);
- err_free_dev:
+err_free_dev:
        input_free_device(input);
        return error;
 }
@@ -1206,6 +1207,7 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
                sparse_keymap_free(eeepc->inputdev);
                input_unregister_device(eeepc->inputdev);
        }
+       eeepc->inputdev = NULL;
 }
 
 /*
@@ -1326,16 +1328,15 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)
        cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
 }
 
-static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
-                          struct acpi_device *device)
+static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
 {
        unsigned int init_flags;
        int result;
 
-       result = acpi_bus_get_status(device);
+       result = acpi_bus_get_status(eeepc->device);
        if (result)
                return result;
-       if (!device->status.present) {
+       if (!eeepc->device->status.present) {
                pr_err("Hotkey device not present, aborting\n");
                return -ENODEV;
        }
@@ -1384,12 +1385,13 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
        strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
        strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
        device->driver_data = eeepc;
+       eeepc->device = device;
 
        eeepc->hotplug_disabled = hotplug_disabled;
 
        eeepc_dmi_check(eeepc);
 
-       result = eeepc_acpi_init(eeepc, device);
+       result = eeepc_acpi_init(eeepc);
        if (result)
                goto fail_platform;
        eeepc_enable_camera(eeepc);
index 9dc50fb..462ceab 100644 (file)
@@ -57,6 +57,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
 
 #define EEEPC_WMI_METHODID_DEVS        0x53564544
 #define EEEPC_WMI_METHODID_DSTS        0x53544344
+#define EEEPC_WMI_METHODID_CFVS        0x53564643
 
 #define EEEPC_WMI_DEVID_BACKLIGHT      0x00050012
 
@@ -69,6 +70,11 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
        { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
+       { KE_KEY, 0xe1, { KEY_F14 } },
+       { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
+       { KE_KEY, 0xe0, { KEY_PROG1 } },
+       { KE_KEY, 0x5c, { KEY_F15 } },
        { KE_END, 0},
 };
 
@@ -292,6 +298,49 @@ static void eeepc_wmi_notify(u32 value, void *context)
        kfree(obj);
 }
 
+static int store_cpufv(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       int value;
+       struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
+       acpi_status status;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+       if (value < 0 || value > 2)
+               return -EINVAL;
+
+       status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
+                                    1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
+
+       if (ACPI_FAILURE(status))
+               return -EIO;
+       else
+               return count;
+}
+
+static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
+
+static void eeepc_wmi_sysfs_exit(struct platform_device *device)
+{
+       device_remove_file(&device->dev, &dev_attr_cpufv);
+}
+
+static int eeepc_wmi_sysfs_init(struct platform_device *device)
+{
+       int retval = -ENOMEM;
+
+       retval = device_create_file(&device->dev, &dev_attr_cpufv);
+       if (retval)
+               goto error_sysfs;
+
+       return 0;
+
+error_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
+       return retval;
+}
+
 static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
 {
        struct eeepc_wmi *eeepc;
@@ -387,8 +436,14 @@ static int __init eeepc_wmi_init(void)
                goto del_dev;
        }
 
+       err = eeepc_wmi_sysfs_init(platform_device);
+       if (err)
+               goto del_sysfs;
+
        return 0;
 
+del_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
 del_dev:
        platform_device_del(platform_device);
 put_dev:
@@ -403,6 +458,7 @@ static void __exit eeepc_wmi_exit(void)
 {
        struct eeepc_wmi *eeepc;
 
+       eeepc_wmi_sysfs_exit(platform_device);
        eeepc = platform_get_drvdata(platform_device);
        platform_driver_unregister(&platform_driver);
        platform_device_unregister(platform_device);
similarity index 99%
rename from drivers/hwmon/hdaps.c
rename to drivers/platform/x86/hdaps.c
index bfd42f1..067bf36 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
+ * hdaps.c - driver for IBM's Hard Drive Active Protection System
  *
  * Copyright (C) 2005 Robert Love <rml@novell.com>
  * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
index c174114..1dac659 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/rfkill.h>
@@ -88,24 +89,16 @@ struct bios_return {
        u32 value;
 };
 
-struct key_entry {
-       char type;              /* See KE_* below */
-       u16 code;
-       u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry hp_wmi_keymap[] = {
-       {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
-       {KE_KEY, 0x20e6, KEY_PROG1},
-       {KE_KEY, 0x20e8, KEY_MEDIA},
-       {KE_KEY, 0x2142, KEY_MEDIA},
-       {KE_KEY, 0x213b, KEY_INFO},
-       {KE_KEY, 0x2169, KEY_DIRECTION},
-       {KE_KEY, 0x231b, KEY_HELP},
-       {KE_END, 0}
+static const struct key_entry hp_wmi_keymap[] = {
+       { KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x20e6, { KEY_PROG1 } },
+       { KE_KEY, 0x20e8, { KEY_MEDIA } },
+       { KE_KEY, 0x2142, { KEY_MEDIA } },
+       { KE_KEY, 0x213b, { KEY_INFO } },
+       { KE_KEY, 0x2169, { KEY_DIRECTION } },
+       { KE_KEY, 0x231b, { KEY_HELP } },
+       { KE_END, 0 }
 };
 
 static struct input_dev *hp_wmi_input_dev;
@@ -347,64 +340,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
 static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
 static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
 
-static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
-{
-       struct key_entry *key;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++)
-               if (key->type == KE_KEY && keycode == key->keycode)
-                       return key;
-
-       return NULL;
-}
-
-static int hp_wmi_getkeycode(struct input_dev *dev,
-                            unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int hp_wmi_setkeycode(struct input_dev *dev,
-                            unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = hp_wmi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!hp_wmi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
 static void hp_wmi_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-       static struct key_entry *key;
        union acpi_object *obj;
        u32 event_id, event_data;
        int key_code = 0, ret;
@@ -465,19 +403,9 @@ static void hp_wmi_notify(u32 value, void *context)
                                           sizeof(key_code));
                if (ret)
                        break;
-               key = hp_wmi_get_entry_by_scancode(key_code);
-               if (key) {
-                       switch (key->type) {
-                       case KE_KEY:
-                               input_report_key(hp_wmi_input_dev,
-                                                key->keycode, 1);
-                               input_sync(hp_wmi_input_dev);
-                               input_report_key(hp_wmi_input_dev,
-                                                key->keycode, 0);
-                               input_sync(hp_wmi_input_dev);
-                               break;
-                       }
-               } else
+
+               if (!sparse_keymap_report_event(hp_wmi_input_dev,
+                                               key_code, 1, true))
                        printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
                               key_code);
                break;
@@ -510,7 +438,7 @@ static void hp_wmi_notify(u32 value, void *context)
 
 static int __init hp_wmi_input_setup(void)
 {
-       struct key_entry *key;
+       acpi_status status;
        int err;
 
        hp_wmi_input_dev = input_allocate_device();
@@ -520,21 +448,14 @@ static int __init hp_wmi_input_setup(void)
        hp_wmi_input_dev->name = "HP WMI hotkeys";
        hp_wmi_input_dev->phys = "wmi/input0";
        hp_wmi_input_dev->id.bustype = BUS_HOST;
-       hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
-       hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++) {
-               switch (key->type) {
-               case KE_KEY:
-                       set_bit(EV_KEY, hp_wmi_input_dev->evbit);
-                       set_bit(key->keycode, hp_wmi_input_dev->keybit);
-                       break;
-               }
-       }
 
-       set_bit(EV_SW, hp_wmi_input_dev->evbit);
-       set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
-       set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+       __set_bit(EV_SW, hp_wmi_input_dev->evbit);
+       __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
+       __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+
+       err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
+       if (err)
+               goto err_free_dev;
 
        /* Set initial hardware state */
        input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -542,14 +463,32 @@ static int __init hp_wmi_input_setup(void)
                            hp_wmi_tablet_state());
        input_sync(hp_wmi_input_dev);
 
-       err = input_register_device(hp_wmi_input_dev);
-
-       if (err) {
-               input_free_device(hp_wmi_input_dev);
-               return err;
+       status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               err = -EIO;
+               goto err_free_keymap;
        }
 
+       err = input_register_device(hp_wmi_input_dev);
+       if (err)
+               goto err_uninstall_notifier;
+
        return 0;
+
+ err_uninstall_notifier:
+       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ err_free_keymap:
+       sparse_keymap_free(hp_wmi_input_dev);
+ err_free_dev:
+       input_free_device(hp_wmi_input_dev);
+       return err;
+}
+
+static void hp_wmi_input_destroy(void)
+{
+       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+       sparse_keymap_free(hp_wmi_input_dev);
+       input_unregister_device(hp_wmi_input_dev);
 }
 
 static void cleanup_sysfs(struct platform_device *device)
@@ -704,15 +643,9 @@ static int __init hp_wmi_init(void)
        int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
 
        if (event_capable) {
-               err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
-                                                hp_wmi_notify, NULL);
-               if (ACPI_FAILURE(err))
-                       return -EINVAL;
                err = hp_wmi_input_setup();
-               if (err) {
-                       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+               if (err)
                        return err;
-               }
        }
 
        if (bios_capable) {
@@ -739,20 +672,17 @@ err_device_add:
 err_device_alloc:
        platform_driver_unregister(&hp_wmi_driver);
 err_driver_reg:
-       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-               input_unregister_device(hp_wmi_input_dev);
-               wmi_remove_notify_handler(HPWMI_EVENT_GUID);
-       }
+       if (event_capable)
+               hp_wmi_input_destroy();
 
        return err;
 }
 
 static void __exit hp_wmi_exit(void)
 {
-       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-               wmi_remove_notify_handler(HPWMI_EVENT_GUID);
-               input_unregister_device(hp_wmi_input_dev);
-       }
+       if (wmi_has_guid(HPWMI_EVENT_GUID))
+               hp_wmi_input_destroy();
+
        if (hp_wmi_platform_dev) {
                platform_device_unregister(hp_wmi_platform_dev);
                platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
new file mode 100644 (file)
index 0000000..3c2c6b9
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * IBM Real-Time Linux driver
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Keith Mannthey <kmannth@us.ibm.com>
+ *         Vernon Mauery <vernux@us.ibm.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/dmi.h>
+#include <linux/mutex.h>
+#include <asm/bios_ebda.h>
+
+static bool force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
+
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Show debug output");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
+MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");
+
+#define RTL_ADDR_TYPE_IO    1
+#define RTL_ADDR_TYPE_MMIO  2
+
+#define RTL_CMD_ENTER_PRTM  1
+#define RTL_CMD_EXIT_PRTM   2
+
+/* The RTL table as presented by the EBDA: */
+struct ibm_rtl_table {
+       char signature[5]; /* signature should be "_RTL_" */
+       u8 version;
+       u8 rt_status;
+       u8 command;
+       u8 command_status;
+       u8 cmd_address_type;
+       u8 cmd_granularity;
+       u8 cmd_offset;
+       u16 reserve1;
+       u32 cmd_port_address; /* platform dependent address */
+       u32 cmd_port_value;   /* platform dependent value */
+} __attribute__((packed));
+
+/* to locate "_RTL_" signature do a masked 5-byte integer compare */
+#define RTL_SIGNATURE 0x0000005f4c54525fULL
+#define RTL_MASK      0x000000ffffffffffULL
+
+#define RTL_DEBUG(A, ...) do { \
+       if (debug) \
+               pr_info("ibm-rtl: " A, ##__VA_ARGS__ ); \
+} while (0)
+
+static DEFINE_MUTEX(rtl_lock);
+static struct ibm_rtl_table __iomem *rtl_table;
+static void __iomem *ebda_map;
+static void __iomem *rtl_cmd_addr;
+static u8 rtl_cmd_type;
+static u8 rtl_cmd_width;
+
+static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
+{
+       if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
+               return ioremap(addr, len);
+       return ioport_map(addr, len);
+}
+
+static void rtl_port_unmap(void __iomem *addr)
+{
+       if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
+               iounmap(addr);
+       else
+               ioport_unmap(addr);
+}
+
+static int ibm_rtl_write(u8 value)
+{
+       int ret = 0, count = 0;
+       static u32 cmd_port_val;
+
+       RTL_DEBUG("%s(%d)\n", __FUNCTION__, value);
+
+       value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;
+
+       mutex_lock(&rtl_lock);
+
+       if (ioread8(&rtl_table->rt_status) != value) {
+               iowrite8(value, &rtl_table->command);
+
+               switch (rtl_cmd_width) {
+               case 8:
+                       cmd_port_val = ioread8(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite8((u8)cmd_port_val, rtl_cmd_addr);
+                       break;
+               case 16:
+                       cmd_port_val = ioread16(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite16((u16)cmd_port_val, rtl_cmd_addr);
+                       break;
+               case 32:
+                       cmd_port_val = ioread32(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite32(cmd_port_val, rtl_cmd_addr);
+                       break;
+               }
+
+               while (ioread8(&rtl_table->command)) {
+                       msleep(10);
+                       if (count++ > 500) {
+                               pr_err("ibm-rtl: Hardware not responding to "
+                                       "mode switch request\n");
+                               ret = -EIO;
+                               break;
+                       }
+
+               }
+
+               if (ioread8(&rtl_table->command_status)) {
+                       RTL_DEBUG("command_status reports failed command\n");
+                       ret = -EIO;
+               }
+       }
+
+       mutex_unlock(&rtl_lock);
+       return ret;
+}
+
+static ssize_t rtl_show_version(struct sysdev_class * dev,
+                                struct sysdev_class_attribute *attr,
+                                char *buf)
+{
+       return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
+}
+
+static ssize_t rtl_show_state(struct sysdev_class *dev,
+                              struct sysdev_class_attribute *attr,
+                              char *buf)
+{
+       return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
+}
+
+static ssize_t rtl_set_state(struct sysdev_class *dev,
+                             struct sysdev_class_attribute *attr,
+                             const char *buf,
+                             size_t count)
+{
+       ssize_t ret;
+
+       if (count < 1 || count > 2)
+               return -EINVAL;
+
+       switch (buf[0]) {
+       case '0':
+               ret = ibm_rtl_write(0);
+               break;
+       case '1':
+               ret = ibm_rtl_write(1);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       if (ret >= 0)
+               ret = count;
+
+       return ret;
+}
+
+static struct sysdev_class class_rtl = {
+       .name = "ibm_rtl",
+};
+
+static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
+static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
+
+static struct sysdev_class_attribute *rtl_attributes[] = {
+       &attr_version,
+       &attr_state,
+       NULL
+};
+
+
+static int rtl_setup_sysfs(void) {
+       int ret, i;
+       ret = sysdev_class_register(&class_rtl);
+
+       if (!ret) {
+               for (i = 0; rtl_attributes[i]; i ++)
+                       sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
+       }
+       return ret;
+}
+
+static void rtl_teardown_sysfs(void) {
+       int i;
+       for (i = 0; rtl_attributes[i]; i ++)
+               sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
+       sysdev_class_unregister(&class_rtl);
+}
+
+static int dmi_check_cb(const struct dmi_system_id *id)
+{
+       RTL_DEBUG("found IBM server '%s'\n", id->ident);
+       return 0;
+}
+
+#define ibm_dmi_entry(NAME, TYPE)                  \
+{                                                  \
+       .ident = NAME,                             \
+       .matches = {                               \
+               DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
+               DMI_MATCH(DMI_PRODUCT_NAME, TYPE), \
+       },                                         \
+       .callback = dmi_check_cb                   \
+}
+
+static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
+       ibm_dmi_entry("BladeCenter LS21", "7971"),
+       ibm_dmi_entry("BladeCenter LS22", "7901"),
+       ibm_dmi_entry("BladeCenter HS21 XM", "7995"),
+       ibm_dmi_entry("BladeCenter HS22", "7870"),
+       ibm_dmi_entry("BladeCenter HS22V", "7871"),
+       ibm_dmi_entry("System x3550 M2", "7946"),
+       ibm_dmi_entry("System x3650 M2", "7947"),
+       ibm_dmi_entry("System x3550 M3", "7944"),
+       ibm_dmi_entry("System x3650 M3", "7945"),
+       { }
+};
+
+static int __init ibm_rtl_init(void) {
+       unsigned long ebda_addr, ebda_size;
+       unsigned int ebda_kb;
+       int ret = -ENODEV, i;
+
+       if (force)
+               pr_warning("ibm-rtl: module loaded by force\n");
+       /* first ensure that we are running on IBM HW */
+       else if (!dmi_check_system(ibm_rtl_dmi_table))
+               return -ENODEV;
+
+       /* Get the address for the Extended BIOS Data Area */
+       ebda_addr = get_bios_ebda();
+       if (!ebda_addr) {
+               RTL_DEBUG("no BIOS EBDA found\n");
+               return -ENODEV;
+       }
+
+       ebda_map = ioremap(ebda_addr, 4);
+       if (!ebda_map)
+               return -ENOMEM;
+
+       /* First word in the EDBA is the Size in KB */
+       ebda_kb = ioread16(ebda_map);
+       RTL_DEBUG("EBDA is %d kB\n", ebda_kb);
+
+       if (ebda_kb == 0)
+               goto out;
+
+       iounmap(ebda_map);
+       ebda_size = ebda_kb*1024;
+
+       /* Remap the whole table */
+       ebda_map = ioremap(ebda_addr, ebda_size);
+       if (!ebda_map)
+               return -ENOMEM;
+
+       /* search for the _RTL_ signature at the start of the table */
+       for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
+               struct ibm_rtl_table __iomem * tmp;
+               tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
+               if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
+                       phys_addr_t addr;
+                       unsigned int plen;
+                       RTL_DEBUG("found RTL_SIGNATURE at %#llx\n", (u64)tmp);
+                       rtl_table = tmp;
+                       /* The address, value, width and offset are platform
+                        * dependent and found in the ibm_rtl_table */
+                       rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
+                       rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
+                       RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
+                             rtl_cmd_width, rtl_cmd_type);
+                       addr = ioread32(&rtl_table->cmd_port_address);
+                       RTL_DEBUG("addr = %#llx\n", addr);
+                       plen = rtl_cmd_width/sizeof(char);
+                       rtl_cmd_addr = rtl_port_map(addr, plen);
+                       RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);
+                       if (!rtl_cmd_addr) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = rtl_setup_sysfs();
+                       break;
+               }
+       }
+
+out:
+       if (ret) {
+               iounmap(ebda_map);
+               rtl_port_unmap(rtl_cmd_addr);
+       }
+
+       return ret;
+}
+
+static void __exit ibm_rtl_exit(void)
+{
+       if (rtl_table) {
+               RTL_DEBUG("cleaning up");
+               /* do not leave the machine in SMI-free mode */
+               ibm_rtl_write(0);
+               /* unmap, unlink and remove all traces */
+               rtl_teardown_sysfs();
+               iounmap(ebda_map);
+               rtl_port_unmap(rtl_cmd_addr);
+       }
+}
+
+module_init(ibm_rtl_init);
+module_exit(ibm_rtl_exit);
similarity index 53%
rename from drivers/platform/x86/ideapad_acpi.c
rename to drivers/platform/x86/ideapad-laptop.c
index 7984963..5ff1220 100644 (file)
 #define IDEAPAD_DEV_KILLSW     4
 
 struct ideapad_private {
+       acpi_handle handle;
        struct rfkill *rfk[5];
-};
+} *ideapad_priv;
 
 static struct {
        char *name;
+       int cfgbit;
+       int opcode;
        int type;
 } ideapad_rfk_data[] = {
-       /* camera has no rfkill */
-       { "ideapad_wlan",       RFKILL_TYPE_WLAN },
-       { "ideapad_bluetooth",  RFKILL_TYPE_BLUETOOTH },
-       { "ideapad_3g",         RFKILL_TYPE_WWAN },
-       { "ideapad_killsw",     RFKILL_TYPE_WLAN }
+       { "ideapad_camera",     19, 0x1E, NUM_RFKILL_TYPES },
+       { "ideapad_wlan",       18, 0x15, RFKILL_TYPE_WLAN },
+       { "ideapad_bluetooth",  16, 0x17, RFKILL_TYPE_BLUETOOTH },
+       { "ideapad_3g",         17, 0x20, RFKILL_TYPE_WWAN },
+       { "ideapad_killsw",     0,  0,    RFKILL_TYPE_WLAN }
 };
 
-static int ideapad_dev_exists(int device)
-{
-       acpi_status status;
-       union acpi_object in_param;
-       struct acpi_object_list input = { 1, &in_param };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
+static bool no_bt_rfkill;
+module_param(no_bt_rfkill, bool, 0444);
+MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
 
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
+/*
+ * ACPI Helpers
+ */
+#define IDEAPAD_EC_TIMEOUT (100) /* in ms */
 
-       in_param.type = ACPI_TYPE_INTEGER;
-       in_param.integer.value = device + 1;
+static int read_method_int(acpi_handle handle, const char *method, int *val)
+{
+       acpi_status status;
+       unsigned long long result;
 
-       status = acpi_evaluate_object(NULL, "\\_SB_.DECN", &input, &output);
+       status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method failed %d. Is this an IdeaPAD?\n", status);
-               return -ENODEV;
-       }
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method returned unexpected type\n");
-               return -ENODEV;
+               *val = -1;
+               return -1;
+       } else {
+               *val = result;
+               return 0;
        }
-       return out_obj.integer.value;
 }
 
-static int ideapad_dev_get_state(int device)
+static int method_vpcr(acpi_handle handle, int cmd, int *ret)
 {
        acpi_status status;
-       union acpi_object in_param;
-       struct acpi_object_list input = { 1, &in_param };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
+       unsigned long long result;
+       struct acpi_object_list params;
+       union acpi_object in_obj;
 
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
+       params.count = 1;
+       params.pointer = &in_obj;
+       in_obj.type = ACPI_TYPE_INTEGER;
+       in_obj.integer.value = cmd;
 
-       in_param.type = ACPI_TYPE_INTEGER;
-       in_param.integer.value = device + 1;
+       status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
 
-       status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status);
-               return -ENODEV;
-       }
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n");
-               return -ENODEV;
+               *ret = -1;
+               return -1;
+       } else {
+               *ret = result;
+               return 0;
        }
-       return out_obj.integer.value;
 }
 
-static int ideapad_dev_set_state(int device, int state)
+static int method_vpcw(acpi_handle handle, int cmd, int data)
 {
+       struct acpi_object_list params;
+       union acpi_object in_obj[2];
        acpi_status status;
-       union acpi_object in_params[2];
-       struct acpi_object_list input = { 2, in_params };
 
-       in_params[0].type = ACPI_TYPE_INTEGER;
-       in_params[0].integer.value = device + 1;
-       in_params[1].type = ACPI_TYPE_INTEGER;
-       in_params[1].integer.value = state;
+       params.count = 2;
+       params.pointer = in_obj;
+       in_obj[0].type = ACPI_TYPE_INTEGER;
+       in_obj[0].integer.value = cmd;
+       in_obj[1].type = ACPI_TYPE_INTEGER;
+       in_obj[1].integer.value = data;
 
-       status = acpi_evaluate_object(NULL, "\\_SB_.SECN", &input, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.SECN method failed %d\n", status);
-               return -ENODEV;
-       }
+       status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
+       if (status != AE_OK)
+               return -1;
        return 0;
 }
+
+static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
+{
+       int val;
+       unsigned long int end_jiffies;
+
+       if (method_vpcw(handle, 1, cmd))
+               return -1;
+
+       for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
+            time_before(jiffies, end_jiffies);) {
+               schedule();
+               if (method_vpcr(handle, 1, &val))
+                       return -1;
+               if (val == 0) {
+                       if (method_vpcr(handle, 0, &val))
+                               return -1;
+                       *data = val;
+                       return 0;
+               }
+       }
+       pr_err("timeout in read_ec_cmd\n");
+       return -1;
+}
+
+static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
+{
+       int val;
+       unsigned long int end_jiffies;
+
+       if (method_vpcw(handle, 0, data))
+               return -1;
+       if (method_vpcw(handle, 1, cmd))
+               return -1;
+
+       for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
+            time_before(jiffies, end_jiffies);) {
+               schedule();
+               if (method_vpcr(handle, 1, &val))
+                       return -1;
+               if (val == 0)
+                       return 0;
+       }
+       pr_err("timeout in write_ec_cmd\n");
+       return -1;
+}
+/* the above is ACPI helpers */
+
 static ssize_t show_ideapad_cam(struct device *dev,
                                struct device_attribute *attr,
                                char *buf)
 {
-       int state = ideapad_dev_get_state(IDEAPAD_DEV_CAMERA);
-       if (state < 0)
-               return state;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       acpi_handle handle = priv->handle;
+       unsigned long result;
 
-       return sprintf(buf, "%d\n", state);
+       if (read_ec_data(handle, 0x1D, &result))
+               return sprintf(buf, "-1\n");
+       return sprintf(buf, "%lu\n", result);
 }
 
 static ssize_t store_ideapad_cam(struct device *dev,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       acpi_handle handle = priv->handle;
        int ret, state;
 
        if (!count)
                return 0;
        if (sscanf(buf, "%i", &state) != 1)
                return -EINVAL;
-       ret = ideapad_dev_set_state(IDEAPAD_DEV_CAMERA, !!state);
+       ret = write_ec_cmd(handle, 0x1E, state);
        if (ret < 0)
                return ret;
        return count;
@@ -154,7 +204,10 @@ static int ideapad_rfk_set(void *data, bool blocked)
 
        if (device == IDEAPAD_DEV_KILLSW)
                return -EINVAL;
-       return ideapad_dev_set_state(device, !blocked);
+
+       return write_ec_cmd(ideapad_priv->handle,
+                           ideapad_rfk_data[device].opcode,
+                           !blocked);
 }
 
 static struct rfkill_ops ideapad_rfk_ops = {
@@ -164,32 +217,47 @@ static struct rfkill_ops ideapad_rfk_ops = {
 static void ideapad_sync_rfk_state(struct acpi_device *adevice)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW);
+       acpi_handle handle = priv->handle;
+       unsigned long hw_blocked;
        int i;
 
-       rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], hw_blocked);
-       for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
-               if (priv->rfk[i])
-                       rfkill_set_hw_state(priv->rfk[i], hw_blocked);
-       if (hw_blocked)
+       if (read_ec_data(handle, 0x23, &hw_blocked))
                return;
+       hw_blocked = !hw_blocked;
 
-       for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
+       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
                if (priv->rfk[i])
-                       rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i));
+                       rfkill_set_hw_state(priv->rfk[i], hw_blocked);
 }
 
 static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int ret;
+       unsigned long sw_blocked;
+
+       if (no_bt_rfkill &&
+           (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
+               /* Force to enable bluetooth when no_bt_rfkill=1 */
+               write_ec_cmd(ideapad_priv->handle,
+                            ideapad_rfk_data[dev].opcode, 1);
+               return 0;
+       }
 
-       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev,
-                                     ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops,
+       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
+                                     ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
                                      (void *)(long)dev);
        if (!priv->rfk[dev])
                return -ENOMEM;
 
+       if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1,
+                        &sw_blocked)) {
+               rfkill_init_sw_state(priv->rfk[dev], 0);
+       } else {
+               sw_blocked = !sw_blocked;
+               rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
+       }
+
        ret = rfkill_register(priv->rfk[dev]);
        if (ret) {
                rfkill_destroy(priv->rfk[dev]);
@@ -217,14 +285,18 @@ MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
 
 static int ideapad_acpi_add(struct acpi_device *adevice)
 {
-       int i;
+       int i, cfg;
        int devs_present[5];
        struct ideapad_private *priv;
 
+       if (read_method_int(adevice->handle, "_CFG", &cfg))
+               return -ENODEV;
+
        for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) {
-               devs_present[i] = ideapad_dev_exists(i);
-               if (devs_present[i] < 0)
-                       return devs_present[i];
+               if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
+                       devs_present[i] = 1;
+               else
+                       devs_present[i] = 0;
        }
 
        /* The hardware switch is always present */
@@ -242,7 +314,9 @@ static int ideapad_acpi_add(struct acpi_device *adevice)
                }
        }
 
+       priv->handle = adevice->handle;
        dev_set_drvdata(&adevice->dev, priv);
+       ideapad_priv = priv;
        for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) {
                if (!devs_present[i])
                        continue;
@@ -270,7 +344,21 @@ static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
 
 static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
 {
-       ideapad_sync_rfk_state(adevice);
+       acpi_handle handle = adevice->handle;
+       unsigned long vpc1, vpc2, vpc_bit;
+
+       if (read_ec_data(handle, 0x10, &vpc1))
+               return;
+       if (read_ec_data(handle, 0x1A, &vpc2))
+               return;
+
+       vpc1 = (vpc2 << 8) | vpc1;
+       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
+               if (test_bit(vpc_bit, &vpc1)) {
+                       if (vpc_bit == 9)
+                               ideapad_sync_rfk_state(adevice);
+               }
+       }
 }
 
 static struct acpi_driver ideapad_acpi_driver = {
index 5cdcff6..f540ff9 100644 (file)
@@ -142,16 +142,16 @@ static int pmic_gpio_direction_output(struct gpio_chip *chip,
 
        if (offset < 8)/* it is GPIO */
                rc = intel_scu_ipc_update_register(GPIO0 + offset,
-                               GPIO_DRV | GPIO_DOU | GPIO_DIR,
-                               GPIO_DRV | (value ? GPIO_DOU : 0));
+                               GPIO_DRV | (value ? GPIO_DOU : 0),
+                               GPIO_DRV | GPIO_DOU | GPIO_DIR);
        else if (offset < 16)/* it is GPOSW */
                rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
-                               GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
-                               GPOSW_DRV | (value ? GPOSW_DOU : 0));
+                               GPOSW_DRV | (value ? GPOSW_DOU : 0),
+                               GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
        else if (offset > 15 && offset < 24)/* it is GPO */
                rc = intel_scu_ipc_update_register(GPO,
-                               1 << (offset - 16),
-                               value ? 1 << (offset - 16) : 0);
+                               value ? 1 << (offset - 16) : 0,
+                               1 << (offset - 16));
        else {
                printk(KERN_ERR
                        "%s: invalid PMIC GPIO pin %d!\n", __func__, offset);
@@ -179,16 +179,16 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        if (offset < 8)/* it is GPIO */
                intel_scu_ipc_update_register(GPIO0 + offset,
-                       GPIO_DRV | GPIO_DOU,
-                       GPIO_DRV | (value ? GPIO_DOU : 0));
+                       GPIO_DRV | (value ? GPIO_DOU : 0),
+                       GPIO_DRV | GPIO_DOU);
        else if (offset < 16)/* it is GPOSW */
                intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
-                       GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
-                       GPOSW_DRV | (value ? GPOSW_DOU : 0));
+                       GPOSW_DRV | (value ? GPOSW_DOU : 0),
+                       GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
        else if (offset > 15 && offset < 24) /* it is GPO */
                intel_scu_ipc_update_register(GPO,
-                       1 << (offset - 16),
-                       value ? 1 << (offset - 16) : 0);
+                       value ? 1 << (offset - 16) : 0,
+                       1 << (offset - 16));
 }
 
 static int pmic_irq_type(unsigned irq, unsigned type)
@@ -197,7 +197,7 @@ static int pmic_irq_type(unsigned irq, unsigned type)
        u32 gpio = irq - pg->irq_base;
        unsigned long flags;
 
-       if (gpio > pg->chip.ngpio)
+       if (gpio >= pg->chip.ngpio)
                return -EINVAL;
 
        spin_lock_irqsave(&pg->irqtypes.lock, flags);
index 6abe18e..41a9e34 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/sfi.h>
 #include <asm/mrst.h>
 #include <asm/intel_scu_ipc.h>
 
index ec01c3d..cc1e0ba 100644 (file)
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 
 #ifndef ACPI_HOTKEY_COMPONENT
@@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = {
                        },
 };
 
-#define KEYMAP_SIZE            11
-static const unsigned int initial_keymap[KEYMAP_SIZE] = {
-       /*  0 */ KEY_RESERVED,
-       /*  1 */ KEY_BRIGHTNESSDOWN,
-       /*  2 */ KEY_BRIGHTNESSUP,
-       /*  3 */ KEY_DISPLAYTOGGLE,
-       /*  4 */ KEY_MUTE,
-       /*  5 */ KEY_VOLUMEDOWN,
-       /*  6 */ KEY_VOLUMEUP,
-       /*  7 */ KEY_SLEEP,
-       /*  8 */ KEY_PROG1, /* Change CPU boost */
-       /*  9 */ KEY_BATTERY,
-       /* 10 */ KEY_SUSPEND,
+static const struct key_entry panasonic_keymap[] = {
+       { KE_KEY, 0, { KEY_RESERVED } },
+       { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
+       { KE_KEY, 4, { KEY_MUTE } },
+       { KE_KEY, 5, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 6, { KEY_VOLUMEUP } },
+       { KE_KEY, 7, { KEY_SLEEP } },
+       { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
+       { KE_KEY, 9, { KEY_BATTERY } },
+       { KE_KEY, 10, { KEY_SUSPEND } },
+       { KE_END, 0 }
 };
 
 struct pcc_acpi {
        acpi_handle             handle;
        unsigned long           num_sifr;
        int                     sticky_mode;
-       u32                     *sinf;
+       u32                     *sinf;
        struct acpi_device      *device;
        struct input_dev        *input_dev;
        struct backlight_device *backlight;
-       unsigned int            keymap[KEYMAP_SIZE];
 };
 
 struct pcc_keyinput {
@@ -267,7 +267,7 @@ static inline int acpi_pcc_get_sqty(struct acpi_device *device)
        }
 }
 
-static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
+static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
 {
        acpi_status status;
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -285,6 +285,7 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
        hkey = buffer.pointer;
        if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
+               status = AE_ERROR;
                goto end;
        }
 
@@ -298,12 +299,12 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
        for (i = 0; i < hkey->package.count; i++) {
                union acpi_object *element = &(hkey->package.elements[i]);
                if (likely(element->type == ACPI_TYPE_INTEGER)) {
-                       sinf[i] = element->integer.value;
+                       pcc->sinf[i] = element->integer.value;
                } else
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                         "Invalid HKEY.SINF data\n"));
        }
-       sinf[hkey->package.count] = -1;
+       pcc->sinf[hkey->package.count] = -1;
 
 end:
        kfree(buffer.pointer);
@@ -321,7 +322,7 @@ static int bl_get(struct backlight_device *bd)
 {
        struct pcc_acpi *pcc = bl_get_data(bd);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return pcc->sinf[SINF_AC_CUR_BRIGHT];
@@ -333,7 +334,7 @@ static int bl_set_status(struct backlight_device *bd)
        int bright = bd->props.brightness;
        int rc;
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
@@ -367,7 +368,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
@@ -379,7 +380,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
@@ -391,7 +392,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]);
@@ -403,7 +404,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
@@ -446,56 +447,10 @@ static struct attribute_group pcc_attr_group = {
 
 /* hotkey input device driver */
 
-static int pcc_getkeycode(struct input_dev *dev,
-                         unsigned int scancode, unsigned int *keycode)
-{
-       struct pcc_acpi *pcc = input_get_drvdata(dev);
-
-       if (scancode >= ARRAY_SIZE(pcc->keymap))
-               return -EINVAL;
-
-       *keycode = pcc->keymap[scancode];
-
-       return 0;
-}
-
-static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
-               if (pcc->keymap[i] == keycode)
-                       return i+1;
-       }
-
-       return 0;
-}
-
-static int pcc_setkeycode(struct input_dev *dev,
-                         unsigned int scancode, unsigned int keycode)
-{
-       struct pcc_acpi *pcc = input_get_drvdata(dev);
-       int oldkeycode;
-
-       if (scancode >= ARRAY_SIZE(pcc->keymap))
-               return -EINVAL;
-
-       oldkeycode = pcc->keymap[scancode];
-       pcc->keymap[scancode] = keycode;
-
-       set_bit(keycode, dev->keybit);
-
-       if (!keymap_get_by_keycode(pcc, oldkeycode))
-               clear_bit(oldkeycode, dev->keybit);
-
-       return 0;
-}
-
 static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 {
        struct input_dev *hotk_input_dev = pcc->input_dev;
        int rc;
-       int key_code, hkey_num;
        unsigned long long result;
 
        rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@@ -508,25 +463,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 
        acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
 
-       hkey_num = result & 0xf;
-
-       if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
+       if (!sparse_keymap_report_event(hotk_input_dev,
+                                       result & 0xf, result & 0x80, false))
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "hotkey number out of range: %d\n",
-                                 hkey_num));
-               return;
-       }
-
-       key_code = pcc->keymap[hkey_num];
-
-       if (key_code != KEY_RESERVED) {
-               int pushed = (result & 0x80) ? TRUE : FALSE;
-
-               input_report_key(hotk_input_dev, key_code, pushed);
-               input_sync(hotk_input_dev);
-       }
-
-       return;
+                                 "Unknown hotkey event: %d\n", result));
 }
 
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -545,40 +485,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
 
 static int acpi_pcc_init_input(struct pcc_acpi *pcc)
 {
-       int i, rc;
+       struct input_dev *input_dev;
+       int error;
 
-       pcc->input_dev = input_allocate_device();
-       if (!pcc->input_dev) {
+       input_dev = input_allocate_device();
+       if (!input_dev) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Couldn't allocate input device for hotkey"));
                return -ENOMEM;
        }
 
-       pcc->input_dev->evbit[0] = BIT(EV_KEY);
-
-       pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
-       pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
-       pcc->input_dev->id.bustype = BUS_HOST;
-       pcc->input_dev->id.vendor = 0x0001;
-       pcc->input_dev->id.product = 0x0001;
-       pcc->input_dev->id.version = 0x0100;
-       pcc->input_dev->getkeycode = pcc_getkeycode;
-       pcc->input_dev->setkeycode = pcc_setkeycode;
+       input_dev->name = ACPI_PCC_DRIVER_NAME;
+       input_dev->phys = ACPI_PCC_INPUT_PHYS;
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
 
-       /* load initial keymap */
-       memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+       error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
+       if (error) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Unable to setup input device keymap\n"));
+               goto err_free_dev;
+       }
 
-       for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
-               __set_bit(pcc->keymap[i], pcc->input_dev->keybit);
-       __clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+       error = input_register_device(input_dev);
+       if (error) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Unable to register input device\n"));
+               goto err_free_keymap;
+       }
 
-       input_set_drvdata(pcc->input_dev, pcc);
+       pcc->input_dev = input_dev;
+       return 0;
 
-       rc = input_register_device(pcc->input_dev);
-       if (rc < 0)
-               input_free_device(pcc->input_dev);
+ err_free_keymap:
+       sparse_keymap_free(input_dev);
+ err_free_dev:
+       input_free_device(input_dev);
+       return error;
+}
 
-       return rc;
+static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
+{
+       sparse_keymap_free(pcc->input_dev);
+       input_unregister_device(pcc->input_dev);
+       /*
+        * No need to input_free_device() since core input API refcounts
+        * and free()s the device.
+        */
 }
 
 /* kernel module interface */
@@ -636,12 +591,13 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
        if (result) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Error installing keyinput handler\n"));
-               goto out_hotkey;
+               goto out_sinf;
        }
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
+       if (!acpi_pcc_retrieve_biosdata(pcc)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                 "Couldn't retrieve BIOS data\n"));
+               result = -EIO;
                goto out_input;
        }
        /* initialize backlight */
@@ -651,7 +607,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
                                                   &pcc_backlight_ops, &props);
        if (IS_ERR(pcc->backlight)) {
                result = PTR_ERR(pcc->backlight);
-               goto out_sinf;
+               goto out_input;
        }
 
        /* read the initial brightness setting from the hardware */
@@ -669,12 +625,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
 
 out_backlight:
        backlight_device_unregister(pcc->backlight);
+out_input:
+       acpi_pcc_destroy_input(pcc);
 out_sinf:
        kfree(pcc->sinf);
-out_input:
-       input_unregister_device(pcc->input_dev);
-       /* no need to input_free_device() since core input API refcount and
-        * free()s the device */
 out_hotkey:
        kfree(pcc);
 
@@ -709,9 +663,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
 
        backlight_device_unregister(pcc->backlight);
 
-       input_unregister_device(pcc->input_dev);
-       /* no need to input_free_device() since core input API refcount and
-        * free()s the device */
+       acpi_pcc_destroy_input(pcc);
 
        kfree(pcc->sinf);
        kfree(pcc);
index ff4b476..1d07d6d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define ACPI_TOPSTAR_CLASS "topstar"
 
@@ -26,52 +27,37 @@ struct topstar_hkey {
        struct input_dev *inputdev;
 };
 
-struct tps_key_entry {
-       u8 code;
-       u16 keycode;
-};
-
-static struct tps_key_entry topstar_keymap[] = {
-       { 0x80, KEY_BRIGHTNESSUP },
-       { 0x81, KEY_BRIGHTNESSDOWN },
-       { 0x83, KEY_VOLUMEUP },
-       { 0x84, KEY_VOLUMEDOWN },
-       { 0x85, KEY_MUTE },
-       { 0x86, KEY_SWITCHVIDEOMODE },
-       { 0x87, KEY_F13 }, /* touchpad enable/disable key */
-       { 0x88, KEY_WLAN },
-       { 0x8a, KEY_WWW },
-       { 0x8b, KEY_MAIL },
-       { 0x8c, KEY_MEDIA },
-       { 0x96, KEY_F14 }, /* G key? */
-       { }
-};
-
-static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
-{
-       struct tps_key_entry *key;
-
-       for (key = topstar_keymap; key->code; key++)
-               if (code == key->code)
-                       return key;
+static const struct key_entry topstar_keymap[] = {
+       { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x83, { KEY_VOLUMEUP } },
+       { KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x85, { KEY_MUTE } },
+       { KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
+       { KE_KEY, 0x88, { KEY_WLAN } },
+       { KE_KEY, 0x8a, { KEY_WWW } },
+       { KE_KEY, 0x8b, { KEY_MAIL } },
+       { KE_KEY, 0x8c, { KEY_MEDIA } },
 
-       return NULL;
-}
-
-static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code)
-{
-       struct tps_key_entry *key;
+       /* Known non hotkey events don't handled or that we don't care yet */
+       { KE_IGNORE, 0x8e, },
+       { KE_IGNORE, 0x8f, },
+       { KE_IGNORE, 0x90, },
 
-       for (key = topstar_keymap; key->code; key++)
-               if (code == key->keycode)
-                       return key;
+       /*
+        * 'G key' generate two event codes, convert to only
+        * one event/key code for now, consider replacing by
+        * a switch (3G switch - SW_3G?)
+        */
+       { KE_KEY, 0x96, { KEY_F14 } },
+       { KE_KEY, 0x97, { KEY_F14 } },
 
-       return NULL;
-}
+       { KE_END, 0 }
+};
 
 static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 {
-       struct tps_key_entry *key;
        static bool dup_evnt[2];
        bool *dup;
        struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -86,27 +72,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
                *dup = true;
        }
 
-       /*
-        * 'G key' generate two event codes, convert to only
-        * one event/key code for now (3G switch?)
-        */
-       if (event == 0x97)
-               event = 0x96;
-
-       key = tps_get_key_by_scancode(event);
-       if (key) {
-               input_report_key(hkey->inputdev, key->keycode, 1);
-               input_sync(hkey->inputdev);
-               input_report_key(hkey->inputdev, key->keycode, 0);
-               input_sync(hkey->inputdev);
-               return;
-       }
-
-       /* Known non hotkey events don't handled or that we don't care yet */
-       if (event == 0x8e || event == 0x8f || event == 0x90)
-               return;
-
-       pr_info("unknown event = 0x%02x\n", event);
+       if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+               pr_info("unknown event = 0x%02x\n", event);
 }
 
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -127,62 +94,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
        return 0;
 }
 
-static int topstar_getkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int *keycode)
-{
-       struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
-
-       if (!key)
-               return -EINVAL;
-
-       *keycode = key->keycode;
-       return 0;
-}
-
-static int topstar_setkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int keycode)
-{
-       struct tps_key_entry *key;
-       int old_keycode;
-
-       key = tps_get_key_by_scancode(scancode);
-
-       if (!key)
-               return -EINVAL;
-
-       old_keycode = key->keycode;
-       key->keycode = keycode;
-       set_bit(keycode, dev->keybit);
-       if (!tps_get_key_by_keycode(old_keycode))
-               clear_bit(old_keycode, dev->keybit);
-       return 0;
-}
-
 static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
 {
-       struct tps_key_entry *key;
+       struct input_dev *input;
+       int error;
 
-       hkey->inputdev = input_allocate_device();
-       if (!hkey->inputdev) {
+       input = input_allocate_device();
+       if (!input) {
                pr_err("Unable to allocate input device\n");
-               return -ENODEV;
+               return -ENOMEM;
        }
-       hkey->inputdev->name = "Topstar Laptop extra buttons";
-       hkey->inputdev->phys = "topstar/input0";
-       hkey->inputdev->id.bustype = BUS_HOST;
-       hkey->inputdev->getkeycode = topstar_getkeycode;
-       hkey->inputdev->setkeycode = topstar_setkeycode;
-       for (key = topstar_keymap; key->code; key++) {
-               set_bit(EV_KEY, hkey->inputdev->evbit);
-               set_bit(key->keycode, hkey->inputdev->keybit);
+
+       input->name = "Topstar Laptop extra buttons";
+       input->phys = "topstar/input0";
+       input->id.bustype = BUS_HOST;
+
+       error = sparse_keymap_setup(input, topstar_keymap, NULL);
+       if (error) {
+               pr_err("Unable to setup input device keymap\n");
+               goto err_free_dev;
        }
-       if (input_register_device(hkey->inputdev)) {
+
+       error = input_register_device(input);
+       if (error) {
                pr_err("Unable to register input device\n");
-               input_free_device(hkey->inputdev);
-               return -ENODEV;
+               goto err_free_keymap;
        }
 
+       hkey->inputdev = input;
        return 0;
+
+ err_free_keymap:
+       sparse_keymap_free(input);
+ err_free_dev:
+       input_free_device(input);
+       return error;
 }
 
 static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
 
        acpi_topstar_fncx_switch(device, false);
 
+       sparse_keymap_free(tps_hkey->inputdev);
        input_unregister_device(tps_hkey->inputdev);
        kfree(tps_hkey);
 
index 7d67a45..06f304f 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 
@@ -121,36 +122,28 @@ static const struct acpi_device_id toshiba_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
 
-struct key_entry {
-       char type;
-       u16 code;
-       u16 keycode;
-};
-
-enum {KE_KEY, KE_END};
-
-static struct key_entry toshiba_acpi_keymap[]  = {
-       {KE_KEY, 0x101, KEY_MUTE},
-       {KE_KEY, 0x102, KEY_ZOOMOUT},
-       {KE_KEY, 0x103, KEY_ZOOMIN},
-       {KE_KEY, 0x13b, KEY_COFFEE},
-       {KE_KEY, 0x13c, KEY_BATTERY},
-       {KE_KEY, 0x13d, KEY_SLEEP},
-       {KE_KEY, 0x13e, KEY_SUSPEND},
-       {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
-       {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
-       {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0x142, KEY_WLAN},
-       {KE_KEY, 0x143, KEY_PROG1},
-       {KE_KEY, 0xb05, KEY_PROG2},
-       {KE_KEY, 0xb06, KEY_WWW},
-       {KE_KEY, 0xb07, KEY_MAIL},
-       {KE_KEY, 0xb30, KEY_STOP},
-       {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
-       {KE_KEY, 0xb32, KEY_NEXTSONG},
-       {KE_KEY, 0xb33, KEY_PLAYPAUSE},
-       {KE_KEY, 0xb5a, KEY_MEDIA},
-       {KE_END, 0, 0},
+static const struct key_entry toshiba_acpi_keymap[] __initconst = {
+       { KE_KEY, 0x101, { KEY_MUTE } },
+       { KE_KEY, 0x102, { KEY_ZOOMOUT } },
+       { KE_KEY, 0x103, { KEY_ZOOMIN } },
+       { KE_KEY, 0x13b, { KEY_COFFEE } },
+       { KE_KEY, 0x13c, { KEY_BATTERY } },
+       { KE_KEY, 0x13d, { KEY_SLEEP } },
+       { KE_KEY, 0x13e, { KEY_SUSPEND } },
+       { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x142, { KEY_WLAN } },
+       { KE_KEY, 0x143, { KEY_PROG1 } },
+       { KE_KEY, 0xb05, { KEY_PROG2 } },
+       { KE_KEY, 0xb06, { KEY_WWW } },
+       { KE_KEY, 0xb07, { KEY_MAIL } },
+       { KE_KEY, 0xb30, { KEY_STOP } },
+       { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
+       { KE_KEY, 0xb32, { KEY_NEXTSONG } },
+       { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
+       { KE_KEY, 0xb5a, { KEY_MEDIA } },
+       { KE_END, 0 },
 };
 
 /* utility
@@ -852,64 +845,9 @@ static struct backlight_ops toshiba_backlight_data = {
         .update_status  = set_lcd_status,
 };
 
-static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
-               if (code == key->keycode && key->type == KE_KEY)
-                       return key;
-
-       return NULL;
-}
-
-static int toshiba_acpi_getkeycode(struct input_dev *dev,
-                                  unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int toshiba_acpi_setkeycode(struct input_dev *dev,
-                                  unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = toshiba_acpi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
 static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
 {
        u32 hci_result, value;
-       struct key_entry *key;
 
        if (event != 0x80)
                return;
@@ -922,19 +860,11 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
                        if (value & 0x80)
                                continue;
 
-                       key = toshiba_acpi_get_entry_by_scancode
-                               (value);
-                       if (!key) {
+                       if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
+                                                       value, 1, true)) {
                                printk(MY_INFO "Unknown key %x\n",
                                       value);
-                               continue;
                        }
-                       input_report_key(toshiba_acpi.hotkey_dev,
-                                        key->keycode, 1);
-                       input_sync(toshiba_acpi.hotkey_dev);
-                       input_report_key(toshiba_acpi.hotkey_dev,
-                                        key->keycode, 0);
-                       input_sync(toshiba_acpi.hotkey_dev);
                } else if (hci_result == HCI_NOT_SUPPORTED) {
                        /* This is a workaround for an unresolved issue on
                         * some machines where system events sporadically
@@ -945,34 +875,17 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
        } while (hci_result != HCI_EMPTY);
 }
 
-static int toshiba_acpi_setup_keyboard(char *device)
+static int __init toshiba_acpi_setup_keyboard(char *device)
 {
        acpi_status status;
-       acpi_handle handle;
-       int result;
-       const struct key_entry *key;
+       int error;
 
-       status = acpi_get_handle(NULL, device, &handle);
+       status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
        if (ACPI_FAILURE(status)) {
                printk(MY_INFO "Unable to get notification device\n");
                return -ENODEV;
        }
 
-       toshiba_acpi.handle = handle;
-
-       status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(MY_INFO "Unable to enable hotkeys\n");
-               return -ENODEV;
-       }
-
-       status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
-                                             toshiba_acpi_notify, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(MY_INFO "Unable to install hotkey notification\n");
-               return -ENODEV;
-       }
-
        toshiba_acpi.hotkey_dev = input_allocate_device();
        if (!toshiba_acpi.hotkey_dev) {
                printk(MY_INFO "Unable to register input device\n");
@@ -982,27 +895,54 @@ static int toshiba_acpi_setup_keyboard(char *device)
        toshiba_acpi.hotkey_dev->name = "Toshiba input device";
        toshiba_acpi.hotkey_dev->phys = device;
        toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
-       toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
-       toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
 
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
-               set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
-               set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
+       error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
+                                   toshiba_acpi_keymap, NULL);
+       if (error)
+               goto err_free_dev;
+
+       status = acpi_install_notify_handler(toshiba_acpi.handle,
+                               ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to install hotkey notification\n");
+               error = -ENODEV;
+               goto err_free_keymap;
+       }
+
+       status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to enable hotkeys\n");
+               error = -ENODEV;
+               goto err_remove_notify;
        }
 
-       result = input_register_device(toshiba_acpi.hotkey_dev);
-       if (result) {
+       error = input_register_device(toshiba_acpi.hotkey_dev);
+       if (error) {
                printk(MY_INFO "Unable to register input device\n");
-               return result;
+               goto err_remove_notify;
        }
 
        return 0;
+
+ err_remove_notify:
+       acpi_remove_notify_handler(toshiba_acpi.handle,
+                                  ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+ err_free_keymap:
+       sparse_keymap_free(toshiba_acpi.hotkey_dev);
+ err_free_dev:
+       input_free_device(toshiba_acpi.hotkey_dev);
+       toshiba_acpi.hotkey_dev = NULL;
+       return error;
 }
 
 static void toshiba_acpi_exit(void)
 {
-       if (toshiba_acpi.hotkey_dev)
+       if (toshiba_acpi.hotkey_dev) {
+               acpi_remove_notify_handler(toshiba_acpi.handle,
+                               ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+               sparse_keymap_free(toshiba_acpi.hotkey_dev);
                input_unregister_device(toshiba_acpi.hotkey_dev);
+       }
 
        if (toshiba_acpi.bt_rfk) {
                rfkill_unregister(toshiba_acpi.bt_rfk);
@@ -1017,9 +957,6 @@ static void toshiba_acpi_exit(void)
        if (toshiba_proc_dir)
                remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 
-       acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
-                                  toshiba_acpi_notify);
-
        if (toshiba_acpi.illumination_installed)
                led_classdev_unregister(&toshiba_led);
 
index b2978a0..104b77c 100644 (file)
@@ -27,6 +27,8 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -44,9 +46,8 @@ MODULE_LICENSE("GPL");
 
 #define ACPI_WMI_CLASS "wmi"
 
-#define PREFIX "ACPI: WMI: "
-
 static DEFINE_MUTEX(wmi_data_lock);
+static LIST_HEAD(wmi_block_list);
 
 struct guid_block {
        char guid[16];
@@ -67,10 +68,9 @@ struct wmi_block {
        acpi_handle handle;
        wmi_notify_handler handler;
        void *handler_data;
-       struct device *dev;
+       struct device dev;
 };
 
-static struct wmi_block wmi_blocks;
 
 /*
  * If the GUID data block is marked as expensive, we must enable and
@@ -110,7 +110,7 @@ static struct acpi_driver acpi_wmi_driver = {
                .add = acpi_wmi_add,
                .remove = acpi_wmi_remove,
                .notify = acpi_wmi_notify,
-               },
+       },
 };
 
 /*
@@ -128,30 +128,18 @@ static struct acpi_driver acpi_wmi_driver = {
  */
 static int wmi_parse_hexbyte(const u8 *src)
 {
-       unsigned int x; /* For correct wrapping */
        int h;
+       int value;
 
        /* high part */
-       x = src[0];
-       if (x - '0' <= '9' - '0') {
-               h = x - '0';
-       } else if (x - 'a' <= 'f' - 'a') {
-               h = x - 'a' + 10;
-       } else if (x - 'A' <= 'F' - 'A') {
-               h = x - 'A' + 10;
-       } else {
+       h = value = hex_to_bin(src[0]);
+       if (value < 0)
                return -1;
-       }
-       h <<= 4;
 
        /* low part */
-       x = src[1];
-       if (x - '0' <= '9' - '0')
-               return h | (x - '0');
-       if (x - 'a' <= 'f' - 'a')
-               return h | (x - 'a' + 10);
-       if (x - 'A' <= 'F' - 'A')
-               return h | (x - 'A' + 10);
+       value = hex_to_bin(src[1]);
+       if (value >= 0)
+               return (h << 4) | value;
        return -1;
 }
 
@@ -232,7 +220,7 @@ static int wmi_gtoa(const char *in, char *out)
        for (i = 10; i <= 15; i++)
                out += sprintf(out, "%02X", in[i] & 0xFF);
 
-       out = '\0';
+       *out = '\0';
        return 0;
 }
 
@@ -246,7 +234,7 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
        wmi_parse_guid(guid_string, tmp);
        wmi_swap_bytes(tmp, guid_input);
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                block = &wblock->gblock;
 
@@ -487,30 +475,29 @@ const struct acpi_buffer *in)
 }
 EXPORT_SYMBOL_GPL(wmi_set_block);
 
-static void wmi_dump_wdg(struct guid_block *g)
+static void wmi_dump_wdg(const struct guid_block *g)
 {
        char guid_string[37];
 
        wmi_gtoa(g->guid, guid_string);
-       printk(KERN_INFO PREFIX "%s:\n", guid_string);
-       printk(KERN_INFO PREFIX "\tobject_id: %c%c\n",
-              g->object_id[0], g->object_id[1]);
-       printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id);
-       printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved);
-       printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count);
-       printk(KERN_INFO PREFIX "\tflags: %#x", g->flags);
+
+       pr_info("%s:\n", guid_string);
+       pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]);
+       pr_info("\tnotify_id: %02X\n", g->notify_id);
+       pr_info("\treserved: %02X\n", g->reserved);
+       pr_info("\tinstance_count: %d\n", g->instance_count);
+       pr_info("\tflags: %#x ", g->flags);
        if (g->flags) {
-               printk(" ");
                if (g->flags & ACPI_WMI_EXPENSIVE)
-                       printk("ACPI_WMI_EXPENSIVE ");
+                       pr_cont("ACPI_WMI_EXPENSIVE ");
                if (g->flags & ACPI_WMI_METHOD)
-                       printk("ACPI_WMI_METHOD ");
+                       pr_cont("ACPI_WMI_METHOD ");
                if (g->flags & ACPI_WMI_STRING)
-                       printk("ACPI_WMI_STRING ");
+                       pr_cont("ACPI_WMI_STRING ");
                if (g->flags & ACPI_WMI_EVENT)
-                       printk("ACPI_WMI_EVENT ");
+                       pr_cont("ACPI_WMI_EVENT ");
        }
-       printk("\n");
+       pr_cont("\n");
 
 }
 
@@ -522,7 +509,7 @@ static void wmi_notify_debug(u32 value, void *context)
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
-               printk(KERN_INFO "wmi: bad event status 0x%x\n", status);
+               pr_info("bad event status 0x%x\n", status);
                return;
        }
 
@@ -531,22 +518,22 @@ static void wmi_notify_debug(u32 value, void *context)
        if (!obj)
                return;
 
-       printk(KERN_INFO PREFIX "DEBUG Event ");
+       pr_info("DEBUG Event ");
        switch(obj->type) {
        case ACPI_TYPE_BUFFER:
-               printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
+               pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length);
                break;
        case ACPI_TYPE_STRING:
-               printk("STRING_TYPE - %s\n", obj->string.pointer);
+               pr_cont("STRING_TYPE - %s\n", obj->string.pointer);
                break;
        case ACPI_TYPE_INTEGER:
-               printk("INTEGER_TYPE - %llu\n", obj->integer.value);
+               pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value);
                break;
        case ACPI_TYPE_PACKAGE:
-               printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
+               pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count);
                break;
        default:
-               printk("object type 0x%X\n", obj->type);
+               pr_cont("object type 0x%X\n", obj->type);
        }
        kfree(obj);
 }
@@ -633,7 +620,7 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
        params[0].type = ACPI_TYPE_INTEGER;
        params[0].integer.value = event;
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                gblock = &wblock->gblock;
 
@@ -662,7 +649,7 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
 /*
  * sysfs interface
  */
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        char guid_string[37];
@@ -676,7 +663,11 @@ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
 
        return sprintf(buf, "wmi:%s\n", guid_string);
 }
-static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+
+static struct device_attribute wmi_dev_attrs[] = {
+       __ATTR_RO(modalias),
+       __ATTR_NULL
+};
 
 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -702,108 +693,71 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 
 static void wmi_dev_free(struct device *dev)
 {
-       kfree(dev);
+       struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev);
+
+       kfree(wmi_block);
 }
 
 static struct class wmi_class = {
        .name = "wmi",
        .dev_release = wmi_dev_free,
        .dev_uevent = wmi_dev_uevent,
+       .dev_attrs = wmi_dev_attrs,
 };
 
-static int wmi_create_devs(void)
+static struct wmi_block *wmi_create_device(const struct guid_block *gblock,
+                                          acpi_handle handle)
 {
-       int result;
-       char guid_string[37];
-       struct guid_block *gblock;
        struct wmi_block *wblock;
-       struct list_head *p;
-       struct device *guid_dev;
-
-       /* Create devices for all the GUIDs */
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-
-               guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-               if (!guid_dev)
-                       return -ENOMEM;
-
-               wblock->dev = guid_dev;
-
-               guid_dev->class = &wmi_class;
-               dev_set_drvdata(guid_dev, wblock);
-
-               gblock = &wblock->gblock;
-
-               wmi_gtoa(gblock->guid, guid_string);
-               dev_set_name(guid_dev, guid_string);
-
-               result = device_register(guid_dev);
-               if (result)
-                       return result;
+       int error;
+       char guid_string[37];
 
-               result = device_create_file(guid_dev, &dev_attr_modalias);
-               if (result)
-                       return result;
+       wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
+       if (!wblock) {
+               error = -ENOMEM;
+               goto err_out;
        }
 
-       return 0;
-}
+       wblock->handle = handle;
+       wblock->gblock = *gblock;
 
-static void wmi_remove_devs(void)
-{
-       struct guid_block *gblock;
-       struct wmi_block *wblock;
-       struct list_head *p;
-       struct device *guid_dev;
+       wblock->dev.class = &wmi_class;
 
-       /* Delete devices for all the GUIDs */
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
+       wmi_gtoa(gblock->guid, guid_string);
+       dev_set_name(&wblock->dev, guid_string);
 
-               guid_dev = wblock->dev;
-               gblock = &wblock->gblock;
+       dev_set_drvdata(&wblock->dev, wblock);
 
-               device_remove_file(guid_dev, &dev_attr_modalias);
+       error = device_register(&wblock->dev);
+       if (error)
+               goto err_free;
 
-               device_unregister(guid_dev);
-       }
-}
+       list_add_tail(&wblock->list, &wmi_block_list);
+       return wblock;
 
-static void wmi_class_exit(void)
-{
-       wmi_remove_devs();
-       class_unregister(&wmi_class);
+err_free:
+       kfree(wblock);
+err_out:
+       return ERR_PTR(error);
 }
 
-static int wmi_class_init(void)
+static void wmi_free_devices(void)
 {
-       int ret;
-
-       ret = class_register(&wmi_class);
-       if (ret)
-               return ret;
+       struct wmi_block *wblock, *next;
 
-       ret = wmi_create_devs();
-       if (ret)
-               wmi_class_exit();
-
-       return ret;
+       /* Delete devices for all the GUIDs */
+       list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
+               device_unregister(&wblock->dev);
 }
 
 static bool guid_already_parsed(const char *guid_string)
 {
-       struct guid_block *gblock;
        struct wmi_block *wblock;
-       struct list_head *p;
 
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-               gblock = &wblock->gblock;
-
-               if (strncmp(gblock->guid, guid_string, 16) == 0)
+       list_for_each_entry(wblock, &wmi_block_list, list)
+               if (strncmp(wblock->gblock.guid, guid_string, 16) == 0)
                        return true;
-       }
+
        return false;
 }
 
@@ -814,30 +768,29 @@ static acpi_status parse_wdg(acpi_handle handle)
 {
        struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
        union acpi_object *obj;
-       struct guid_block *gblock;
+       const struct guid_block *gblock;
        struct wmi_block *wblock;
        char guid_string[37];
        acpi_status status;
+       int retval;
        u32 i, total;
 
        status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
-
        if (ACPI_FAILURE(status))
-               return status;
+               return -ENXIO;
 
        obj = (union acpi_object *) out.pointer;
+       if (!obj)
+               return -ENXIO;
 
-       if (obj->type != ACPI_TYPE_BUFFER)
-               return AE_ERROR;
-
-       total = obj->buffer.length / sizeof(struct guid_block);
-
-       gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
-       if (!gblock) {
-               status = AE_NO_MEMORY;
+       if (obj->type != ACPI_TYPE_BUFFER) {
+               retval = -ENXIO;
                goto out_free_pointer;
        }
 
+       gblock = (const struct guid_block *)obj->buffer.pointer;
+       total = obj->buffer.length / sizeof(struct guid_block);
+
        for (i = 0; i < total; i++) {
                /*
                  Some WMI devices, like those for nVidia hooks, have a
@@ -848,34 +801,32 @@ static acpi_status parse_wdg(acpi_handle handle)
                */
                if (guid_already_parsed(gblock[i].guid) == true) {
                        wmi_gtoa(gblock[i].guid, guid_string);
-                       printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
-                               guid_string);
+                       pr_info("Skipping duplicate GUID %s\n", guid_string);
                        continue;
                }
+
                if (debug_dump_wdg)
                        wmi_dump_wdg(&gblock[i]);
 
-               wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
-               if (!wblock) {
-                       status = AE_NO_MEMORY;
-                       goto out_free_gblock;
+               wblock = wmi_create_device(&gblock[i], handle);
+               if (IS_ERR(wblock)) {
+                       retval = PTR_ERR(wblock);
+                       wmi_free_devices();
+                       break;
                }
 
-               wblock->gblock = gblock[i];
-               wblock->handle = handle;
                if (debug_event) {
                        wblock->handler = wmi_notify_debug;
-                       status = wmi_method_enable(wblock, 1);
+                       wmi_method_enable(wblock, 1);
                }
-               list_add_tail(&wblock->list, &wmi_blocks.list);
        }
 
-out_free_gblock:
-       kfree(gblock);
+       retval = 0;
+
 out_free_pointer:
        kfree(out.pointer);
 
-       return status;
+       return retval;
 }
 
 /*
@@ -929,7 +880,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
        struct list_head *p;
        char guid_string[37];
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                block = &wblock->gblock;
 
@@ -939,8 +890,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
                                wblock->handler(event, wblock->handler_data);
                        if (debug_event) {
                                wmi_gtoa(wblock->gblock.guid, guid_string);
-                               printk(KERN_INFO PREFIX "DEBUG Event GUID:"
-                                      " %s\n", guid_string);
+                               pr_info("DEBUG Event GUID: %s\n", guid_string);
                        }
 
                        acpi_bus_generate_netlink_event(
@@ -955,6 +905,7 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
 {
        acpi_remove_address_space_handler(device->handle,
                                ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
+       wmi_free_devices();
 
        return 0;
 }
@@ -962,68 +913,57 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
 static int acpi_wmi_add(struct acpi_device *device)
 {
        acpi_status status;
-       int result = 0;
+       int error;
 
        status = acpi_install_address_space_handler(device->handle,
                                                    ACPI_ADR_SPACE_EC,
                                                    &acpi_wmi_ec_space_handler,
                                                    NULL, NULL);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       status = parse_wdg(device->handle);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR PREFIX "Error installing EC region handler\n");
+               pr_err("Error installing EC region handler\n");
                return -ENODEV;
        }
 
-       return result;
+       error = parse_wdg(device->handle);
+       if (error) {
+               acpi_remove_address_space_handler(device->handle,
+                                                 ACPI_ADR_SPACE_EC,
+                                                 &acpi_wmi_ec_space_handler);
+               pr_err("Failed to parse WDG method\n");
+               return error;
+       }
+
+       return 0;
 }
 
 static int __init acpi_wmi_init(void)
 {
-       int result;
-
-       INIT_LIST_HEAD(&wmi_blocks.list);
+       int error;
 
        if (acpi_disabled)
                return -ENODEV;
 
-       result = acpi_bus_register_driver(&acpi_wmi_driver);
+       error = class_register(&wmi_class);
+       if (error)
+               return error;
 
-       if (result < 0) {
-               printk(KERN_INFO PREFIX "Error loading mapper\n");
-               return -ENODEV;
+       error = acpi_bus_register_driver(&acpi_wmi_driver);
+       if (error) {
+               pr_err("Error loading mapper\n");
+               class_unregister(&wmi_class);
+               return error;
        }
 
-       result = wmi_class_init();
-       if (result) {
-               acpi_bus_unregister_driver(&acpi_wmi_driver);
-               return result;
-       }
-
-       printk(KERN_INFO PREFIX "Mapper loaded\n");
-
-       return result;
+       pr_info("Mapper loaded\n");
+       return 0;
 }
 
 static void __exit acpi_wmi_exit(void)
 {
-       struct list_head *p, *tmp;
-       struct wmi_block *wblock;
-
-       wmi_class_exit();
-
        acpi_bus_unregister_driver(&acpi_wmi_driver);
+       class_unregister(&wmi_class);
 
-       list_for_each_safe(p, tmp, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-
-               list_del(p);
-               kfree(wblock);
-       }
-
-       printk(KERN_INFO PREFIX "Mapper unloaded\n");
+       pr_info("Mapper unloaded\n");
 }
 
 subsys_initcall(acpi_wmi_init);
diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c
new file mode 100644 (file)
index 0000000..e549eee
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Support for rfkill through the OLPC XO-1 laptop embedded controller
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+
+#include <asm/olpc.h>
+
+static int rfkill_set_block(void *data, bool blocked)
+{
+       unsigned char cmd;
+       if (blocked)
+               cmd = EC_WLAN_ENTER_RESET;
+       else
+               cmd = EC_WLAN_LEAVE_RESET;
+
+       return olpc_ec_cmd(cmd, NULL, 0, NULL, 0);
+}
+
+static const struct rfkill_ops rfkill_ops = {
+       .set_block = rfkill_set_block,
+};
+
+static int __devinit xo1_rfkill_probe(struct platform_device *pdev)
+{
+       struct rfkill *rfk;
+       int r;
+
+       rfk = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_WLAN,
+                          &rfkill_ops, NULL);
+       if (!rfk)
+               return -ENOMEM;
+
+       r = rfkill_register(rfk);
+       if (r) {
+               rfkill_destroy(rfk);
+               return r;
+       }
+
+       platform_set_drvdata(pdev, rfk);
+       return 0;
+}
+
+static int __devexit xo1_rfkill_remove(struct platform_device *pdev)
+{
+       struct rfkill *rfk = platform_get_drvdata(pdev);
+       rfkill_unregister(rfk);
+       rfkill_destroy(rfk);
+       return 0;
+}
+
+static struct platform_driver xo1_rfkill_driver = {
+       .driver = {
+               .name = "xo1-rfkill",
+               .owner = THIS_MODULE,
+       },
+       .probe          = xo1_rfkill_probe,
+       .remove         = __devexit_p(xo1_rfkill_remove),
+};
+
+static int __init xo1_rfkill_init(void)
+{
+       return platform_driver_register(&xo1_rfkill_driver);
+}
+
+static void __exit xo1_rfkill_exit(void)
+{
+       platform_driver_unregister(&xo1_rfkill_driver);
+}
+
+MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:xo1-rfkill");
+
+module_init(xo1_rfkill_init);
+module_exit(xo1_rfkill_exit);
index aa95f10..fb613d7 100644 (file)
@@ -1099,16 +1099,30 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
        cqr = (struct dasd_ccw_req *) intparm;
        if (!cqr || ((scsw_cc(&irb->scsw) == 1) &&
                     (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
-                    (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) {
+                    ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) ||
+                     (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND |
+                                                 SCSW_STCTL_ALERT_STATUS))))) {
                if (cqr && cqr->status == DASD_CQR_IN_IO)
                        cqr->status = DASD_CQR_QUEUED;
+               if (cqr)
+                       memcpy(&cqr->irb, irb, sizeof(*irb));
                device = dasd_device_from_cdev_locked(cdev);
-               if (!IS_ERR(device)) {
-                       dasd_device_clear_timer(device);
-                       device->discipline->handle_unsolicited_interrupt(device,
-                                                                        irb);
+               if (IS_ERR(device))
+                       return;
+               /* ignore unsolicited interrupts for DIAG discipline */
+               if (device->discipline == dasd_diag_discipline_pointer) {
                        dasd_put_device(device);
+                       return;
                }
+               device->discipline->dump_sense_dbf(device, irb,
+                                                  "unsolicited");
+               if ((device->features & DASD_FEATURE_ERPLOG))
+                       device->discipline->dump_sense(device, cqr,
+                                                      irb);
+               dasd_device_clear_timer(device);
+               device->discipline->handle_unsolicited_interrupt(device,
+                                                                irb);
+               dasd_put_device(device);
                return;
        }
 
index e82d427..968c76c 100644 (file)
@@ -221,6 +221,7 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
        ccw->cmd_code = CCW_CMD_DCTL;
        ccw->count = 4;
        ccw->cda = (__u32)(addr_t) DCTL_data;
+       dctl_cqr->flags = erp->flags;
        dctl_cqr->function = dasd_3990_erp_DCTL;
        dctl_cqr->refers = erp;
        dctl_cqr->startdev = device;
@@ -1710,6 +1711,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
        ccw->cda = cpa;
 
        /* fill erp related fields */
+       erp->flags = default_erp->flags;
        erp->function = dasd_3990_erp_action_1B_32;
        erp->refers = default_erp->refers;
        erp->startdev = device;
@@ -2354,6 +2356,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
                ccw->cda      = (long)(cqr->cpaddr);
        }
 
+       erp->flags = cqr->flags;
        erp->function = dasd_3990_erp_add_erp;
        erp->refers   = cqr;
        erp->startdev = device;
index 2b3bc3e..266b34b 100644 (file)
@@ -228,25 +228,22 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr)
 }
 
 /* Handle external interruption. */
-static void
-dasd_ext_handler(__u16 code)
+static void dasd_ext_handler(unsigned int ext_int_code,
+                            unsigned int param32, unsigned long param64)
 {
        struct dasd_ccw_req *cqr, *next;
        struct dasd_device *device;
        unsigned long long expires;
        unsigned long flags;
-       u8 int_code, status;
        addr_t ip;
        int rc;
 
-       int_code = *((u8 *) DASD_DIAG_LC_INT_CODE);
-       status = *((u8 *) DASD_DIAG_LC_INT_STATUS);
-       switch (int_code) {
+       switch (ext_int_code >> 24) {
        case DASD_DIAG_CODE_31BIT:
-               ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT);
+               ip = (addr_t) param32;
                break;
        case DASD_DIAG_CODE_64BIT:
-               ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT);
+               ip = (addr_t) param64;
                break;
        default:
                return;
@@ -281,7 +278,7 @@ dasd_ext_handler(__u16 code)
        cqr->stopclk = get_clock();
 
        expires = 0;
-       if (status == 0) {
+       if ((ext_int_code & 0xff0000) == 0) {
                cqr->status = DASD_CQR_SUCCESS;
                /* Start first request on queue if possible -> fast_io. */
                if (!list_empty(&device->ccw_queue)) {
@@ -296,8 +293,8 @@ dasd_ext_handler(__u16 code)
        } else {
                cqr->status = DASD_CQR_QUEUED;
                DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
-                           "request %p was %d (%d retries left)", cqr, status,
-                           cqr->retries);
+                             "request %p was %d (%d retries left)", cqr,
+                             (ext_int_code >> 16) & 0xff, cqr->retries);
                dasd_diag_erp(device);
        }
 
index b8c7826..4f71fbe 100644 (file)
 #define DEV_CLASS_FBA  0x01
 #define DEV_CLASS_ECKD 0x04
 
-#define DASD_DIAG_LC_INT_CODE          132
-#define DASD_DIAG_LC_INT_STATUS                133
-#define DASD_DIAG_LC_INT_PARM_31BIT    128
-#define DASD_DIAG_LC_INT_PARM_64BIT    4536
 #define DASD_DIAG_CODE_31BIT           0x03
 #define DASD_DIAG_CODE_64BIT           0x07
 
index 59b4ecf..50cf963 100644 (file)
@@ -1776,13 +1776,13 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
        }
 
        /* summary unit check */
-       if ((scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
-           (irb->ecw[7] == 0x0D)) {
+       sense = dasd_get_sense(irb);
+       if (sense && (sense[7] == 0x0D) &&
+           (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
                dasd_alias_handle_summary_unit_check(device, irb);
                return;
        }
 
-       sense = dasd_get_sense(irb);
        /* service information message SIM */
        if (sense && !(sense[27] & DASD_SENSE_BIT_0) &&
            ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
@@ -1791,26 +1791,15 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
                return;
        }
 
-       if ((scsw_cc(&irb->scsw) == 1) &&
-           (scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
-           (scsw_actl(&irb->scsw) & SCSW_ACTL_START_PEND) &&
-           (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND)) {
+       if ((scsw_cc(&irb->scsw) == 1) && !sense &&
+           (scsw_fctl(&irb->scsw) == SCSW_FCTL_START_FUNC) &&
+           (scsw_actl(&irb->scsw) == SCSW_ACTL_START_PEND) &&
+           (scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND)) {
                /* fake irb do nothing, they are handled elsewhere */
                dasd_schedule_device_bh(device);
                return;
        }
 
-       if (!sense) {
-               /* just report other unsolicited interrupts */
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
-                           "unsolicited interrupt received");
-       } else {
-               DBF_DEV_EVENT(DBF_ERR, device, "%s",
-                           "unsolicited interrupt received "
-                           "(sense available)");
-               device->discipline->dump_sense_dbf(device, irb, "unsolicited");
-       }
-
        dasd_schedule_device_bh(device);
        return;
 };
@@ -3093,19 +3082,19 @@ dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct irb *irb,
                         char *reason)
 {
        u64 *sense;
+       u64 *stat;
 
        sense = (u64 *) dasd_get_sense(irb);
+       stat = (u64 *) &irb->scsw;
        if (sense) {
-               DBF_DEV_EVENT(DBF_EMERG, device,
-                             "%s: %s %02x%02x%02x %016llx %016llx %016llx "
-                             "%016llx", reason,
-                             scsw_is_tm(&irb->scsw) ? "t" : "c",
-                             scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw),
-                             scsw_dstat(&irb->scsw), sense[0], sense[1],
-                             sense[2], sense[3]);
+               DBF_DEV_EVENT(DBF_EMERG, device, "%s: %016llx %08x : "
+                             "%016llx %016llx %016llx %016llx",
+                             reason, *stat, *((u32 *) (stat + 1)),
+                             sense[0], sense[1], sense[2], sense[3]);
        } else {
-               DBF_DEV_EVENT(DBF_EMERG, device, "%s",
-                             "SORRY - NO VALID SENSE AVAILABLE\n");
+               DBF_DEV_EVENT(DBF_EMERG, device, "%s: %016llx %08x : %s",
+                             reason, *stat, *((u32 *) (stat + 1)),
+                             "NO VALID SENSE");
        }
 }
 
@@ -3131,9 +3120,12 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device,
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-                      " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n",
-                      req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
-                      scsw_cc(&irb->scsw), req ? req->intrc : 0);
+                      " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
+                      "CS:%02X RC:%d\n",
+                      req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
+                      scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw),
+                      scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
+                      req ? req->intrc : 0);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing CCW: %p\n",
                       dev_name(&device->cdev->dev),
@@ -3234,11 +3226,13 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
                      " I/O status report for device %s:\n",
                      dev_name(&device->cdev->dev));
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
-                      " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d "
-                      "fcxs: 0x%02X schxs: 0x%02X\n", req,
-                      scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw),
-                      scsw_cc(&irb->scsw), req->intrc,
-                      irb->scsw.tm.fcxs, irb->scsw.tm.schxs);
+                      " in req: %p CC:%02X FC:%02X AC:%02X SC:%02X DS:%02X "
+                      "CS:%02X fcxs:%02X schxs:%02X RC:%d\n",
+                      req, scsw_cc(&irb->scsw), scsw_fctl(&irb->scsw),
+                      scsw_actl(&irb->scsw), scsw_stctl(&irb->scsw),
+                      scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw),
+                      irb->scsw.tm.fcxs, irb->scsw.tm.schxs,
+                      req ? req->intrc : 0);
        len += sprintf(page + len, KERN_ERR PRINTK_HEADER
                       " device %s: Failing TCW: %p\n",
                       dev_name(&device->cdev->dev),
@@ -3246,7 +3240,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 
        tsb = NULL;
        sense = NULL;
-       if (irb->scsw.tm.tcw && (irb->scsw.tm.fcxs == 0x01))
+       if (irb->scsw.tm.tcw && (irb->scsw.tm.fcxs & 0x01))
                tsb = tcw_get_tsb(
                        (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
 
@@ -3344,7 +3338,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device,
 static void dasd_eckd_dump_sense(struct dasd_device *device,
                                 struct dasd_ccw_req *req, struct irb *irb)
 {
-       if (req && scsw_is_tm(&req->irb.scsw))
+       if (scsw_is_tm(&irb->scsw))
                dasd_eckd_dump_sense_tcw(device, req, irb);
        else
                dasd_eckd_dump_sense_ccw(device, req, irb);
index 2eb0255..c4a6a31 100644 (file)
@@ -251,7 +251,6 @@ static ssize_t dasd_stats_proc_write(struct file *file,
        buffer = dasd_get_user_string(user_buf, user_len);
        if (IS_ERR(buffer))
                return PTR_ERR(buffer);
-       DBF_EVENT(DBF_DEBUG, "/proc/dasd/statictics: '%s'\n", buffer);
 
        /* check for valid verbs */
        str = skip_spaces(buffer);
index 5707a80..35cc468 100644 (file)
@@ -395,16 +395,16 @@ __sclp_find_req(u32 sccb)
 /* Handler for external interruption. Perform request post-processing.
  * Prepare read event data request if necessary. Start processing of next
  * request on queue. */
-static void
-sclp_interrupt_handler(__u16 code)
+static void sclp_interrupt_handler(unsigned int ext_int_code,
+                                  unsigned int param32, unsigned long param64)
 {
        struct sclp_req *req;
        u32 finished_sccb;
        u32 evbuf_pending;
 
        spin_lock(&sclp_lock);
-       finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
-       evbuf_pending = S390_lowcore.ext_params & 0x3;
+       finished_sccb = param32 & 0xfffffff8;
+       evbuf_pending = param32 & 0x3;
        if (finished_sccb) {
                del_timer(&sclp_request_timer);
                sclp_running_state = sclp_running_state_reset_pending;
@@ -819,12 +819,12 @@ EXPORT_SYMBOL(sclp_reactivate);
 
 /* Handler for external interruption used during initialization. Modify
  * request state to done. */
-static void
-sclp_check_handler(__u16 code)
+static void sclp_check_handler(unsigned int ext_int_code,
+                              unsigned int param32, unsigned long param64)
 {
        u32 finished_sccb;
 
-       finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
+       finished_sccb = param32 & 0xfffffff8;
        /* Is this the interrupt we are waiting for? */
        if (finished_sccb == 0)
                return;
index 0d6dc4b..9f66142 100644 (file)
@@ -215,7 +215,7 @@ static void vmlogrdr_iucv_message_pending(struct iucv_path *path,
 
 static int vmlogrdr_get_recording_class_AB(void)
 {
-       char cp_command[]="QUERY COMMAND RECORDING ";
+       static const char cp_command[] = "QUERY COMMAND RECORDING ";
        char cp_response[80];
        char *tail;
        int len,i;
@@ -638,7 +638,7 @@ static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
                                              char *buf)
 {
 
-       char cp_command[] = "QUERY RECORDING ";
+       static const char cp_command[] = "QUERY RECORDING ";
        int len;
 
        cpcmd(cp_command, buf, 4096, NULL);
index 13cb601..76058a5 100644 (file)
@@ -79,17 +79,15 @@ static int pure_hex(char **cp, unsigned int *val, int min_digit,
                    int max_digit, int max_val)
 {
        int diff;
-       unsigned int value;
 
        diff = 0;
        *val = 0;
 
-       while (isxdigit(**cp) && (diff <= max_digit)) {
+       while (diff <= max_digit) {
+               int value = hex_to_bin(**cp);
 
-               if (isdigit(**cp))
-                       value = **cp - '0';
-               else
-                       value = tolower(**cp) - 'a' + 10;
+               if (value < 0)
+                       break;
                *val = *val * 16 + value;
                (*cp)++;
                diff++;
index 6c9fa15..2d32233 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chp.c
  *
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999,2010
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
  *              Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
@@ -54,12 +54,6 @@ static struct work_struct cfg_work;
 /* Wait queue for configure completion events. */
 static wait_queue_head_t cfg_wait_queue;
 
-/* Return channel_path struct for given chpid. */
-static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
-{
-       return channel_subsystems[chpid.cssid]->chps[chpid.id];
-}
-
 /* Set vary state for given chpid. */
 static void set_chp_logically_online(struct chp_id chpid, int onoff)
 {
@@ -241,11 +235,13 @@ static ssize_t chp_status_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
 {
        struct channel_path *chp = to_channelpath(dev);
+       int status;
 
-       if (!chp)
-               return 0;
-       return (chp_get_status(chp->chpid) ? sprintf(buf, "online\n") :
-               sprintf(buf, "offline\n"));
+       mutex_lock(&chp->lock);
+       status = chp->state;
+       mutex_unlock(&chp->lock);
+
+       return status ? sprintf(buf, "online\n") : sprintf(buf, "offline\n");
 }
 
 static ssize_t chp_status_write(struct device *dev,
@@ -261,15 +257,18 @@ static ssize_t chp_status_write(struct device *dev,
        if (!num_args)
                return count;
 
-       if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1"))
+       if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
+               mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 1);
-       else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0"))
+               mutex_unlock(&cp->lock);
+       } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
+               mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 0);
-       else
+               mutex_unlock(&cp->lock);
+       } else
                error = -EINVAL;
 
        return error < 0 ? error : count;
-
 }
 
 static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);
@@ -315,10 +314,12 @@ static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct channel_path *chp = to_channelpath(dev);
+       u8 type;
 
-       if (!chp)
-               return 0;
-       return sprintf(buf, "%x\n", chp->desc.desc);
+       mutex_lock(&chp->lock);
+       type = chp->desc.desc;
+       mutex_unlock(&chp->lock);
+       return sprintf(buf, "%x\n", type);
 }
 
 static DEVICE_ATTR(type, 0444, chp_type_show, NULL);
@@ -395,6 +396,7 @@ int chp_new(struct chp_id chpid)
        chp->state = 1;
        chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
        chp->dev.release = chp_release;
+       mutex_init(&chp->lock);
 
        /* Obtain channel path description and fill it in. */
        ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
@@ -464,7 +466,10 @@ void *chp_get_chp_desc(struct chp_id chpid)
        desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
        if (!desc)
                return NULL;
+
+       mutex_lock(&chp->lock);
        memcpy(desc, &chp->desc, sizeof(struct channel_path_desc));
+       mutex_unlock(&chp->lock);
        return desc;
 }
 
index 26c3d22..12b4903 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chp.h
  *
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007,2010
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/device.h>
+#include <linux/mutex.h>
 #include <asm/chpid.h>
 #include "chsc.h"
 #include "css.h"
@@ -40,16 +41,23 @@ static inline int chp_test_bit(u8 *bitmap, int num)
 
 
 struct channel_path {
+       struct device dev;
        struct chp_id chpid;
+       struct mutex lock; /* Serialize access to below members. */
        int state;
        struct channel_path_desc desc;
        /* Channel-measurement related stuff: */
        int cmg;
        int shared;
        void *cmg_chars;
-       struct device dev;
 };
 
+/* Return channel_path struct for given chpid. */
+static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
+{
+       return channel_subsystems[chpid.cssid]->chps[chpid.id];
+}
+
 int chp_get_status(struct chp_id chpid);
 u8 chp_get_sch_opm(struct subchannel *sch);
 int chp_is_registered(struct chp_id chpid);
index 4cbb1a6..1aaddea 100644 (file)
@@ -2,7 +2,7 @@
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
  *
- *    Copyright IBM Corp. 1999,2008
+ *    Copyright IBM Corp. 1999,2010
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
@@ -29,8 +29,8 @@
 #include "chsc.h"
 
 static void *sei_page;
-static DEFINE_SPINLOCK(siosl_lock);
-static DEFINE_SPINLOCK(sda_lock);
+static void *chsc_page;
+static DEFINE_SPINLOCK(chsc_page_lock);
 
 /**
  * chsc_error_from_response() - convert a chsc response to an error
@@ -85,17 +85,15 @@ struct chsc_ssd_area {
 
 int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
 {
-       unsigned long page;
        struct chsc_ssd_area *ssd_area;
        int ccode;
        int ret;
        int i;
        int mask;
 
-       page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!page)
-               return -ENOMEM;
-       ssd_area = (struct chsc_ssd_area *) page;
+       spin_lock_irq(&chsc_page_lock);
+       memset(chsc_page, 0, PAGE_SIZE);
+       ssd_area = chsc_page;
        ssd_area->request.length = 0x0010;
        ssd_area->request.code = 0x0004;
        ssd_area->ssid = schid.ssid;
@@ -106,25 +104,25 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
        /* Check response. */
        if (ccode > 0) {
                ret = (ccode == 3) ? -ENODEV : -EBUSY;
-               goto out_free;
+               goto out;
        }
        ret = chsc_error_from_response(ssd_area->response.code);
        if (ret != 0) {
                CIO_MSG_EVENT(2, "chsc: ssd failed for 0.%x.%04x (rc=%04x)\n",
                              schid.ssid, schid.sch_no,
                              ssd_area->response.code);
-               goto out_free;
+               goto out;
        }
        if (!ssd_area->sch_valid) {
                ret = -ENODEV;
-               goto out_free;
+               goto out;
        }
        /* Copy data */
        ret = 0;
        memset(ssd, 0, sizeof(struct chsc_ssd_info));
        if ((ssd_area->st != SUBCHANNEL_TYPE_IO) &&
            (ssd_area->st != SUBCHANNEL_TYPE_MSG))
-               goto out_free;
+               goto out;
        ssd->path_mask = ssd_area->path_mask;
        ssd->fla_valid_mask = ssd_area->fla_valid_mask;
        for (i = 0; i < 8; i++) {
@@ -136,8 +134,8 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
                if (ssd_area->fla_valid_mask & mask)
                        ssd->fla[i] = ssd_area->fla[i];
        }
-out_free:
-       free_page(page);
+out:
+       spin_unlock_irq(&chsc_page_lock);
        return ret;
 }
 
@@ -497,6 +495,7 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
  */
 int chsc_chp_vary(struct chp_id chpid, int on)
 {
+       struct channel_path *chp = chpid_to_chp(chpid);
        struct chp_link link;
 
        memset(&link, 0, sizeof(struct chp_link));
@@ -506,11 +505,12 @@ int chsc_chp_vary(struct chp_id chpid, int on)
        /*
         * Redo PathVerification on the devices the chpid connects to
         */
-
-       if (on)
+       if (on) {
+               /* Try to update the channel path descritor. */
+               chsc_determine_base_channel_path_desc(chpid, &chp->desc);
                for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
                                           __s390_vary_chpid_on, &link);
-       else
+       else
                for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
                                           NULL, &link);
 
@@ -552,7 +552,7 @@ cleanup:
        return ret;
 }
 
-int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
+int __chsc_do_secm(struct channel_subsystem *css, int enable)
 {
        struct {
                struct chsc_header request;
@@ -573,7 +573,9 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
        } __attribute__ ((packed)) *secm_area;
        int ret, ccode;
 
-       secm_area = page;
+       spin_lock_irq(&chsc_page_lock);
+       memset(chsc_page, 0, PAGE_SIZE);
+       secm_area = chsc_page;
        secm_area->request.length = 0x0050;
        secm_area->request.code = 0x0016;
 
@@ -584,8 +586,10 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
        secm_area->operation_code = enable ? 0 : 1;
 
        ccode = chsc(secm_area);
-       if (ccode > 0)
-               return (ccode == 3) ? -ENODEV : -EBUSY;
+       if (ccode > 0) {
+               ret = (ccode == 3) ? -ENODEV : -EBUSY;
+               goto out;
+       }
 
        switch (secm_area->response.code) {
        case 0x0102:
@@ -598,37 +602,32 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
        if (ret != 0)
                CIO_CRW_EVENT(2, "chsc: secm failed (rc=%04x)\n",
                              secm_area->response.code);
+out:
+       spin_unlock_irq(&chsc_page_lock);
        return ret;
 }
 
 int
 chsc_secm(struct channel_subsystem *css, int enable)
 {
-       void  *secm_area;
        int ret;
 
-       secm_area = (void *)get_zeroed_page(GFP_KERNEL |  GFP_DMA);
-       if (!secm_area)
-               return -ENOMEM;
-
        if (enable && !css->cm_enabled) {
                css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
                css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
                if (!css->cub_addr1 || !css->cub_addr2) {
                        free_page((unsigned long)css->cub_addr1);
                        free_page((unsigned long)css->cub_addr2);
-                       free_page((unsigned long)secm_area);
                        return -ENOMEM;
                }
        }
-       ret = __chsc_do_secm(css, enable, secm_area);
+       ret = __chsc_do_secm(css, enable);
        if (!ret) {
                css->cm_enabled = enable;
                if (css->cm_enabled) {
                        ret = chsc_add_cmg_attr(css);
                        if (ret) {
-                               memset(secm_area, 0, PAGE_SIZE);
-                               __chsc_do_secm(css, 0, secm_area);
+                               __chsc_do_secm(css, 0);
                                css->cm_enabled = 0;
                        }
                } else
@@ -638,44 +637,24 @@ chsc_secm(struct channel_subsystem *css, int enable)
                free_page((unsigned long)css->cub_addr1);
                free_page((unsigned long)css->cub_addr2);
        }
-       free_page((unsigned long)secm_area);
        return ret;
 }
 
 int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
-                                    int c, int m,
-                                    struct chsc_response_struct *resp)
+                                    int c, int m, void *page)
 {
+       struct chsc_scpd *scpd_area;
        int ccode, ret;
 
-       struct {
-               struct chsc_header request;
-               u32 : 2;
-               u32 m : 1;
-               u32 c : 1;
-               u32 fmt : 4;
-               u32 cssid : 8;
-               u32 : 4;
-               u32 rfmt : 4;
-               u32 first_chpid : 8;
-               u32 : 24;
-               u32 last_chpid : 8;
-               u32 zeroes1;
-               struct chsc_header response;
-               u8 data[PAGE_SIZE - 20];
-       } __attribute__ ((packed)) *scpd_area;
-
        if ((rfmt == 1) && !css_general_characteristics.fcs)
                return -EINVAL;
        if ((rfmt == 2) && !css_general_characteristics.cib)
                return -EINVAL;
-       scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!scpd_area)
-               return -ENOMEM;
 
+       memset(page, 0, PAGE_SIZE);
+       scpd_area = page;
        scpd_area->request.length = 0x0010;
        scpd_area->request.code = 0x0002;
-
        scpd_area->cssid = chpid.cssid;
        scpd_area->first_chpid = chpid.id;
        scpd_area->last_chpid = chpid.id;
@@ -685,20 +664,13 @@ int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
        scpd_area->rfmt = rfmt;
 
        ccode = chsc(scpd_area);
-       if (ccode > 0) {
-               ret = (ccode == 3) ? -ENODEV : -EBUSY;
-               goto out;
-       }
+       if (ccode > 0)
+               return (ccode == 3) ? -ENODEV : -EBUSY;
 
        ret = chsc_error_from_response(scpd_area->response.code);
-       if (ret == 0)
-               /* Success. */
-               memcpy(resp, &scpd_area->response, scpd_area->response.length);
-       else
+       if (ret)
                CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n",
                              scpd_area->response.code);
-out:
-       free_page((unsigned long)scpd_area);
        return ret;
 }
 EXPORT_SYMBOL_GPL(chsc_determine_channel_path_desc);
@@ -707,17 +679,19 @@ int chsc_determine_base_channel_path_desc(struct chp_id chpid,
                                          struct channel_path_desc *desc)
 {
        struct chsc_response_struct *chsc_resp;
+       struct chsc_scpd *scpd_area;
+       unsigned long flags;
        int ret;
 
-       chsc_resp = kzalloc(sizeof(*chsc_resp), GFP_KERNEL);
-       if (!chsc_resp)
-               return -ENOMEM;
-       ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, chsc_resp);
+       spin_lock_irqsave(&chsc_page_lock, flags);
+       scpd_area = chsc_page;
+       ret = chsc_determine_channel_path_desc(chpid, 0, 0, 0, 0, scpd_area);
        if (ret)
-               goto out_free;
+               goto out;
+       chsc_resp = (void *)&scpd_area->response;
        memcpy(desc, &chsc_resp->data, sizeof(*desc));
-out_free:
-       kfree(chsc_resp);
+out:
+       spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
 }
 
@@ -725,33 +699,22 @@ static void
 chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
                          struct cmg_chars *chars)
 {
-       switch (chp->cmg) {
-       case 2:
-       case 3:
-               chp->cmg_chars = kmalloc(sizeof(struct cmg_chars),
-                                        GFP_KERNEL);
-               if (chp->cmg_chars) {
-                       int i, mask;
-                       struct cmg_chars *cmg_chars;
-
-                       cmg_chars = chp->cmg_chars;
-                       for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
-                               mask = 0x80 >> (i + 3);
-                               if (cmcv & mask)
-                                       cmg_chars->values[i] = chars->values[i];
-                               else
-                                       cmg_chars->values[i] = 0;
-                       }
-               }
-               break;
-       default:
-               /* No cmg-dependent data. */
-               break;
+       struct cmg_chars *cmg_chars;
+       int i, mask;
+
+       cmg_chars = chp->cmg_chars;
+       for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
+               mask = 0x80 >> (i + 3);
+               if (cmcv & mask)
+                       cmg_chars->values[i] = chars->values[i];
+               else
+                       cmg_chars->values[i] = 0;
        }
 }
 
 int chsc_get_channel_measurement_chars(struct channel_path *chp)
 {
+       struct cmg_chars *cmg_chars;
        int ccode, ret;
 
        struct {
@@ -775,13 +738,16 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
                u32 data[NR_MEASUREMENT_CHARS];
        } __attribute__ ((packed)) *scmc_area;
 
-       scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!scmc_area)
+       chp->cmg_chars = NULL;
+       cmg_chars = kmalloc(sizeof(*cmg_chars), GFP_KERNEL);
+       if (!cmg_chars)
                return -ENOMEM;
 
+       spin_lock_irq(&chsc_page_lock);
+       memset(chsc_page, 0, PAGE_SIZE);
+       scmc_area = chsc_page;
        scmc_area->request.length = 0x0010;
        scmc_area->request.code = 0x0022;
-
        scmc_area->first_chpid = chp->chpid.id;
        scmc_area->last_chpid = chp->chpid.id;
 
@@ -792,53 +758,65 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
        }
 
        ret = chsc_error_from_response(scmc_area->response.code);
-       if (ret == 0) {
-               /* Success. */
-               if (!scmc_area->not_valid) {
-                       chp->cmg = scmc_area->cmg;
-                       chp->shared = scmc_area->shared;
-                       chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
-                                                 (struct cmg_chars *)
-                                                 &scmc_area->data);
-               } else {
-                       chp->cmg = -1;
-                       chp->shared = -1;
-               }
-       } else {
+       if (ret) {
                CIO_CRW_EVENT(2, "chsc: scmc failed (rc=%04x)\n",
                              scmc_area->response.code);
+               goto out;
+       }
+       if (scmc_area->not_valid) {
+               chp->cmg = -1;
+               chp->shared = -1;
+               goto out;
        }
+       chp->cmg = scmc_area->cmg;
+       chp->shared = scmc_area->shared;
+       if (chp->cmg != 2 && chp->cmg != 3) {
+               /* No cmg-dependent data. */
+               goto out;
+       }
+       chp->cmg_chars = cmg_chars;
+       chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
+                                 (struct cmg_chars *) &scmc_area->data);
 out:
-       free_page((unsigned long)scmc_area);
+       spin_unlock_irq(&chsc_page_lock);
+       if (!chp->cmg_chars)
+               kfree(cmg_chars);
+
        return ret;
 }
 
-int __init chsc_alloc_sei_area(void)
+int __init chsc_init(void)
 {
        int ret;
 
        sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!sei_page) {
-               CIO_MSG_EVENT(0, "Can't allocate page for processing of "
-                             "chsc machine checks!\n");
-               return -ENOMEM;
+       chsc_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!sei_page || !chsc_page) {
+               ret = -ENOMEM;
+               goto out_err;
        }
        ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw);
        if (ret)
-               kfree(sei_page);
+               goto out_err;
+       return ret;
+out_err:
+       free_page((unsigned long)chsc_page);
+       free_page((unsigned long)sei_page);
        return ret;
 }
 
-void __init chsc_free_sei_area(void)
+void __init chsc_init_cleanup(void)
 {
        crw_unregister_handler(CRW_RSC_CSS);
-       kfree(sei_page);
+       free_page((unsigned long)chsc_page);
+       free_page((unsigned long)sei_page);
 }
 
 int chsc_enable_facility(int operation_code)
 {
+       unsigned long flags;
        int ret;
-       static struct {
+       struct {
                struct chsc_header request;
                u8 reserved1:4;
                u8 format:4;
@@ -851,32 +829,33 @@ int chsc_enable_facility(int operation_code)
                u32 reserved5:4;
                u32 format2:4;
                u32 reserved6:24;
-       } __attribute__ ((packed, aligned(4096))) sda_area;
+       } __attribute__ ((packed)) *sda_area;
 
-       spin_lock(&sda_lock);
-       memset(&sda_area, 0, sizeof(sda_area));
-       sda_area.request.length = 0x0400;
-       sda_area.request.code = 0x0031;
-       sda_area.operation_code = operation_code;
+       spin_lock_irqsave(&chsc_page_lock, flags);
+       memset(chsc_page, 0, PAGE_SIZE);
+       sda_area = chsc_page;
+       sda_area->request.length = 0x0400;
+       sda_area->request.code = 0x0031;
+       sda_area->operation_code = operation_code;
 
-       ret = chsc(&sda_area);
+       ret = chsc(sda_area);
        if (ret > 0) {
                ret = (ret == 3) ? -ENODEV : -EBUSY;
                goto out;
        }
 
-       switch (sda_area.response.code) {
+       switch (sda_area->response.code) {
        case 0x0101:
                ret = -EOPNOTSUPP;
                break;
        default:
-               ret = chsc_error_from_response(sda_area.response.code);
+               ret = chsc_error_from_response(sda_area->response.code);
        }
        if (ret != 0)
                CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
-                             operation_code, sda_area.response.code);
- out:
-       spin_unlock(&sda_lock);
+                             operation_code, sda_area->response.code);
+out:
+       spin_unlock_irqrestore(&chsc_page_lock, flags);
        return ret;
 }
 
@@ -895,13 +874,12 @@ chsc_determine_css_characteristics(void)
                struct chsc_header response;
                u32 reserved4;
                u32 general_char[510];
-               u32 chsc_char[518];
+               u32 chsc_char[508];
        } __attribute__ ((packed)) *scsc_area;
 
-       scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!scsc_area)
-               return -ENOMEM;
-
+       spin_lock_irq(&chsc_page_lock);
+       memset(chsc_page, 0, PAGE_SIZE);
+       scsc_area = chsc_page;
        scsc_area->request.length = 0x0010;
        scsc_area->request.code = 0x0010;
 
@@ -921,7 +899,7 @@ chsc_determine_css_characteristics(void)
                CIO_CRW_EVENT(2, "chsc: scsc failed (rc=%04x)\n",
                              scsc_area->response.code);
 exit:
-       free_page ((unsigned long) scsc_area);
+       spin_unlock_irq(&chsc_page_lock);
        return result;
 }
 
@@ -976,29 +954,29 @@ int chsc_sstpi(void *page, void *result, size_t size)
        return (rr->response.code == 0x0001) ? 0 : -EIO;
 }
 
-static struct {
-       struct chsc_header request;
-       u32 word1;
-       struct subchannel_id sid;
-       u32 word3;
-       struct chsc_header response;
-       u32 word[11];
-} __attribute__ ((packed)) siosl_area __attribute__ ((__aligned__(PAGE_SIZE)));
-
 int chsc_siosl(struct subchannel_id schid)
 {
+       struct {
+               struct chsc_header request;
+               u32 word1;
+               struct subchannel_id sid;
+               u32 word3;
+               struct chsc_header response;
+               u32 word[11];
+       } __attribute__ ((packed)) *siosl_area;
        unsigned long flags;
        int ccode;
        int rc;
 
-       spin_lock_irqsave(&siosl_lock, flags);
-       memset(&siosl_area, 0, sizeof(siosl_area));
-       siosl_area.request.length = 0x0010;
-       siosl_area.request.code = 0x0046;
-       siosl_area.word1 = 0x80000000;
-       siosl_area.sid = schid;
+       spin_lock_irqsave(&chsc_page_lock, flags);
+       memset(chsc_page, 0, PAGE_SIZE);
+       siosl_area = chsc_page;
+       siosl_area->request.length = 0x0010;
+       siosl_area->request.code = 0x0046;
+       siosl_area->word1 = 0x80000000;
+       siosl_area->sid = schid;
 
-       ccode = chsc(&siosl_area);
+       ccode = chsc(siosl_area);
        if (ccode > 0) {
                if (ccode == 3)
                        rc = -ENODEV;
@@ -1008,17 +986,16 @@ int chsc_siosl(struct subchannel_id schid)
                              schid.ssid, schid.sch_no, ccode);
                goto out;
        }
-       rc = chsc_error_from_response(siosl_area.response.code);
+       rc = chsc_error_from_response(siosl_area->response.code);
        if (rc)
                CIO_MSG_EVENT(2, "chsc: siosl failed for 0.%x.%04x (rc=%04x)\n",
                              schid.ssid, schid.sch_no,
-                             siosl_area.response.code);
+                             siosl_area->response.code);
        else
                CIO_MSG_EVENT(4, "chsc: siosl succeeded for 0.%x.%04x\n",
                              schid.ssid, schid.sch_no);
 out:
-       spin_unlock_irqrestore(&siosl_lock, flags);
-
+       spin_unlock_irqrestore(&chsc_page_lock, flags);
        return rc;
 }
 EXPORT_SYMBOL_GPL(chsc_siosl);
index 5453013..6693f5e 100644 (file)
@@ -57,21 +57,39 @@ struct chsc_ssd_info {
        struct chp_id chpid[8];
        u16 fla[8];
 };
+
+struct chsc_scpd {
+       struct chsc_header request;
+       u32:2;
+       u32 m:1;
+       u32 c:1;
+       u32 fmt:4;
+       u32 cssid:8;
+       u32:4;
+       u32 rfmt:4;
+       u32 first_chpid:8;
+       u32:24;
+       u32 last_chpid:8;
+       u32 zeroes1;
+       struct chsc_header response;
+       u8 data[PAGE_SIZE - 20];
+} __attribute__ ((packed));
+
+
 extern int chsc_get_ssd_info(struct subchannel_id schid,
                             struct chsc_ssd_info *ssd);
 extern int chsc_determine_css_characteristics(void);
-extern int chsc_alloc_sei_area(void);
-extern void chsc_free_sei_area(void);
+extern int chsc_init(void);
+extern void chsc_init_cleanup(void);
 
 extern int chsc_enable_facility(int);
 struct channel_subsystem;
 extern int chsc_secm(struct channel_subsystem *, int);
-int __chsc_do_secm(struct channel_subsystem *css, int enable, void *page);
+int __chsc_do_secm(struct channel_subsystem *css, int enable);
 
 int chsc_chp_vary(struct chp_id chpid, int on);
 int chsc_determine_channel_path_desc(struct chp_id chpid, int fmt, int rfmt,
-                                    int c, int m,
-                                    struct chsc_response_struct *resp);
+                                    int c, int m, void *page);
 int chsc_determine_base_channel_path_desc(struct chp_id chpid,
                                          struct channel_path_desc *desc);
 void chsc_chp_online(struct chp_id chpid);
index f2b77e7..3c3f3ff 100644 (file)
@@ -688,25 +688,31 @@ out_free:
 
 static int chsc_ioctl_chpd(void __user *user_chpd)
 {
+       struct chsc_scpd *scpd_area;
        struct chsc_cpd_info *chpd;
        int ret;
 
        chpd = kzalloc(sizeof(*chpd), GFP_KERNEL);
-       if (!chpd)
-               return -ENOMEM;
+       scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!scpd_area || !chpd) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
        if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) {
                ret = -EFAULT;
                goto out_free;
        }
        ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt,
                                               chpd->rfmt, chpd->c, chpd->m,
-                                              &chpd->chpdb);
+                                              scpd_area);
        if (ret)
                goto out_free;
+       memcpy(&chpd->chpdb, &scpd_area->response, scpd_area->response.length);
        if (copy_to_user(user_chpd, chpd, sizeof(*chpd)))
                ret = -EFAULT;
 out_free:
        kfree(chpd);
+       free_page((unsigned long)scpd_area);
        return ret;
 }
 
index ca8e1c2..a5050e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * driver for channel subsystem
  *
- * Copyright IBM Corp. 2002, 2009
+ * Copyright IBM Corp. 2002, 2010
  *
  * Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *           Cornelia Huck (cornelia.huck@de.ibm.com)
@@ -577,7 +577,7 @@ static int __unset_registered(struct device *dev, void *data)
        return 0;
 }
 
-void css_schedule_eval_all_unreg(void)
+static void css_schedule_eval_all_unreg(void)
 {
        unsigned long flags;
        struct idset *unreg_set;
@@ -790,7 +790,6 @@ static struct notifier_block css_reboot_notifier = {
 static int css_power_event(struct notifier_block *this, unsigned long event,
                           void *ptr)
 {
-       void *secm_area;
        int ret, i;
 
        switch (event) {
@@ -806,15 +805,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
                                mutex_unlock(&css->mutex);
                                continue;
                        }
-                       secm_area = (void *)get_zeroed_page(GFP_KERNEL |
-                                                           GFP_DMA);
-                       if (secm_area) {
-                               if (__chsc_do_secm(css, 0, secm_area))
-                                       ret = NOTIFY_BAD;
-                               free_page((unsigned long)secm_area);
-                       } else
+                       if (__chsc_do_secm(css, 0))
                                ret = NOTIFY_BAD;
-
                        mutex_unlock(&css->mutex);
                }
                break;
@@ -830,15 +822,8 @@ static int css_power_event(struct notifier_block *this, unsigned long event,
                                mutex_unlock(&css->mutex);
                                continue;
                        }
-                       secm_area = (void *)get_zeroed_page(GFP_KERNEL |
-                                                           GFP_DMA);
-                       if (secm_area) {
-                               if (__chsc_do_secm(css, 1, secm_area))
-                                       ret = NOTIFY_BAD;
-                               free_page((unsigned long)secm_area);
-                       } else
+                       if (__chsc_do_secm(css, 1))
                                ret = NOTIFY_BAD;
-
                        mutex_unlock(&css->mutex);
                }
                /* search for subchannels, which appeared during hibernation */
@@ -863,14 +848,11 @@ static int __init css_bus_init(void)
 {
        int ret, i;
 
-       ret = chsc_determine_css_characteristics();
-       if (ret == -ENOMEM)
-               goto out;
-
-       ret = chsc_alloc_sei_area();
+       ret = chsc_init();
        if (ret)
-               goto out;
+               return ret;
 
+       chsc_determine_css_characteristics();
        /* Try to enable MSS. */
        ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
        if (ret)
@@ -956,9 +938,9 @@ out_unregister:
        }
        bus_unregister(&css_bus_type);
 out:
-       crw_unregister_handler(CRW_RSC_CSS);
-       chsc_free_sei_area();
+       crw_unregister_handler(CRW_RSC_SCH);
        idset_free(slow_subchannel_set);
+       chsc_init_cleanup();
        pr_alert("The CSS device driver initialization failed with "
                 "errno=%d\n", ret);
        return ret;
@@ -978,9 +960,9 @@ static void __init css_bus_cleanup(void)
                device_unregister(&css->device);
        }
        bus_unregister(&css_bus_type);
-       crw_unregister_handler(CRW_RSC_CSS);
-       chsc_free_sei_area();
+       crw_unregister_handler(CRW_RSC_SCH);
        idset_free(slow_subchannel_set);
+       chsc_init_cleanup();
        isc_unregister(IO_SCH_ISC);
 }
 
@@ -1048,7 +1030,16 @@ subsys_initcall_sync(channel_subsystem_init_sync);
 
 void channel_subsystem_reinit(void)
 {
+       struct channel_path *chp;
+       struct chp_id chpid;
+
        chsc_enable_facility(CHSC_SDA_OC_MSS);
+       chp_id_for_each(&chpid) {
+               chp = chpid_to_chp(chpid);
+               if (!chp)
+                       continue;
+               chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+       }
 }
 
 #ifdef CONFIG_PROC_FS
@@ -1200,6 +1191,7 @@ static int css_pm_restore(struct device *dev)
        struct subchannel *sch = to_subchannel(dev);
        struct css_driver *drv;
 
+       css_update_ssd_info(sch);
        if (!sch->dev.driver)
                return 0;
        drv = to_cssdriver(sch->dev.driver);
index 51bd368..2ff8a22 100644 (file)
@@ -1147,6 +1147,7 @@ err:
 static int io_subchannel_chp_event(struct subchannel *sch,
                                   struct chp_link *link, int event)
 {
+       struct ccw_device *cdev = sch_get_cdev(sch);
        int mask;
 
        mask = chp_ssd_get_mask(&sch->ssd_info, link);
@@ -1156,22 +1157,30 @@ static int io_subchannel_chp_event(struct subchannel *sch,
        case CHP_VARY_OFF:
                sch->opm &= ~mask;
                sch->lpm &= ~mask;
+               if (cdev)
+                       cdev->private->path_gone_mask |= mask;
                io_subchannel_terminate_path(sch, mask);
                break;
        case CHP_VARY_ON:
                sch->opm |= mask;
                sch->lpm |= mask;
+               if (cdev)
+                       cdev->private->path_new_mask |= mask;
                io_subchannel_verify(sch);
                break;
        case CHP_OFFLINE:
                if (cio_update_schib(sch))
                        return -ENODEV;
+               if (cdev)
+                       cdev->private->path_gone_mask |= mask;
                io_subchannel_terminate_path(sch, mask);
                break;
        case CHP_ONLINE:
                if (cio_update_schib(sch))
                        return -ENODEV;
                sch->lpm |= mask & sch->opm;
+               if (cdev)
+                       cdev->private->path_new_mask |= mask;
                io_subchannel_verify(sch);
                break;
        }
@@ -1196,6 +1205,7 @@ static void io_subchannel_quiesce(struct subchannel *sch)
                cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-EIO));
        while (ret == -EBUSY) {
                cdev->private->state = DEV_STATE_QUIESCE;
+               cdev->private->iretry = 255;
                ret = ccw_device_cancel_halt_clear(cdev);
                if (ret == -EBUSY) {
                        ccw_device_set_timeout(cdev, HZ/10);
@@ -1468,9 +1478,13 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
                        goto out;
                break;
        case IO_SCH_UNREG_ATTACH:
+               if (cdev->private->flags.resuming) {
+                       /* Device will be handled later. */
+                       rc = 0;
+                       goto out;
+               }
                /* Unregister ccw device. */
-               if (!cdev->private->flags.resuming)
-                       ccw_device_unregister(cdev);
+               ccw_device_unregister(cdev);
                break;
        default:
                break;
index c9b8526..a845695 100644 (file)
@@ -174,7 +174,10 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
                ret = cio_clear (sch);
                return (ret == 0) ? -EBUSY : ret;
        }
-       panic("Can't stop i/o on subchannel.\n");
+       /* Function was unsuccessful */
+       CIO_MSG_EVENT(0, "0.%x.%04x: could not stop I/O\n",
+                     cdev->private->dev_id.ssid, cdev->private->dev_id.devno);
+       return -EIO;
 }
 
 void ccw_device_update_sense_data(struct ccw_device *cdev)
@@ -349,9 +352,13 @@ out:
 
 static void ccw_device_oper_notify(struct ccw_device *cdev)
 {
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
        if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) {
                /* Reenable channel measurements, if needed. */
                ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
+               /* Save indication for new paths. */
+               cdev->private->path_new_mask = sch->vpm;
                return;
        }
        /* Driver doesn't want device back. */
@@ -462,6 +469,32 @@ static void ccw_device_request_event(struct ccw_device *cdev, enum dev_event e)
        }
 }
 
+static void ccw_device_report_path_events(struct ccw_device *cdev)
+{
+       struct subchannel *sch = to_subchannel(cdev->dev.parent);
+       int path_event[8];
+       int chp, mask;
+
+       for (chp = 0, mask = 0x80; chp < 8; chp++, mask >>= 1) {
+               path_event[chp] = PE_NONE;
+               if (mask & cdev->private->path_gone_mask & ~(sch->vpm))
+                       path_event[chp] |= PE_PATH_GONE;
+               if (mask & cdev->private->path_new_mask & sch->vpm)
+                       path_event[chp] |= PE_PATH_AVAILABLE;
+               if (mask & cdev->private->pgid_reset_mask & sch->vpm)
+                       path_event[chp] |= PE_PATHGROUP_ESTABLISHED;
+       }
+       if (cdev->online && cdev->drv->path_event)
+               cdev->drv->path_event(cdev, path_event);
+}
+
+static void ccw_device_reset_path_events(struct ccw_device *cdev)
+{
+       cdev->private->path_gone_mask = 0;
+       cdev->private->path_new_mask = 0;
+       cdev->private->pgid_reset_mask = 0;
+}
+
 void
 ccw_device_verify_done(struct ccw_device *cdev, int err)
 {
@@ -498,6 +531,7 @@ callback:
                                              &cdev->private->irb);
                        memset(&cdev->private->irb, 0, sizeof(struct irb));
                }
+               ccw_device_report_path_events(cdev);
                break;
        case -ETIME:
        case -EUSERS:
@@ -516,6 +550,7 @@ callback:
                ccw_device_done(cdev, DEV_STATE_NOT_OPER);
                break;
        }
+       ccw_device_reset_path_events(cdev);
 }
 
 /*
@@ -734,13 +769,14 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
        int ret;
 
        ccw_device_set_timeout(cdev, 0);
+       cdev->private->iretry = 255;
        ret = ccw_device_cancel_halt_clear(cdev);
        if (ret == -EBUSY) {
                ccw_device_set_timeout(cdev, 3*HZ);
                cdev->private->state = DEV_STATE_TIMEOUT_KILL;
                return;
        }
-       if (ret == -ENODEV)
+       if (ret)
                dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
        else if (cdev->handler)
                cdev->handler(cdev, cdev->private->intparm,
@@ -837,6 +873,7 @@ void ccw_device_kill_io(struct ccw_device *cdev)
 {
        int ret;
 
+       cdev->private->iretry = 255;
        ret = ccw_device_cancel_halt_clear(cdev);
        if (ret == -EBUSY) {
                ccw_device_set_timeout(cdev, 3*HZ);
index 82a5ad0..07a4fd2 100644 (file)
@@ -213,6 +213,17 @@ static void spid_start(struct ccw_device *cdev)
        spid_do(cdev);
 }
 
+static int pgid_is_reset(struct pgid *p)
+{
+       char *c;
+
+       for (c = (char *)p + 1; c < (char *)(p + 1); c++) {
+               if (*c != 0)
+                       return 0;
+       }
+       return 1;
+}
+
 static int pgid_cmp(struct pgid *p1, struct pgid *p2)
 {
        return memcmp((char *) p1 + 1, (char *) p2 + 1,
@@ -223,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, struct pgid *p2)
  * Determine pathgroup state from PGID data.
  */
 static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
-                        int *mismatch, int *reserved, int *reset)
+                        int *mismatch, int *reserved, u8 *reset)
 {
        struct pgid *pgid = &cdev->private->pgid[0];
        struct pgid *first = NULL;
@@ -238,9 +249,8 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p,
                        continue;
                if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE)
                        *reserved = 1;
-               if (pgid->inf.ps.state1 == SNID_STATE1_RESET) {
-                       /* A PGID was reset. */
-                       *reset = 1;
+               if (pgid_is_reset(pgid)) {
+                       *reset |= lpm;
                        continue;
                }
                if (!first) {
@@ -307,7 +317,7 @@ static void snid_done(struct ccw_device *cdev, int rc)
        struct pgid *pgid;
        int mismatch = 0;
        int reserved = 0;
-       int reset = 0;
+       u8 reset = 0;
        u8 donepm;
 
        if (rc)
@@ -321,11 +331,12 @@ static void snid_done(struct ccw_device *cdev, int rc)
                donepm = pgid_to_donepm(cdev);
                sch->vpm = donepm & sch->opm;
                cdev->private->pgid_todo_mask &= ~donepm;
+               cdev->private->pgid_reset_mask |= reset;
                pgid_fill(cdev, pgid);
        }
 out:
        CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x "
-                     "todo=%02x mism=%d rsvd=%d reset=%d\n", id->ssid,
+                     "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid,
                      id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm,
                      cdev->private->pgid_todo_mask, mismatch, reserved, reset);
        switch (rc) {
index 469ef93..d024d2c 100644 (file)
@@ -151,8 +151,11 @@ struct ccw_device_private {
        struct subchannel_id schid;     /* subchannel number */
        struct ccw_request req;         /* internal I/O request */
        int iretry;
-       u8 pgid_valid_mask;             /* mask of valid PGIDs */
-       u8 pgid_todo_mask;              /* mask of PGIDs to be adjusted */
+       u8 pgid_valid_mask;     /* mask of valid PGIDs */
+       u8 pgid_todo_mask;      /* mask of PGIDs to be adjusted */
+       u8 pgid_reset_mask;     /* mask of PGIDs which were reset */
+       u8 path_gone_mask;      /* mask of paths, that became unavailable */
+       u8 path_new_mask;       /* mask of paths, that became available */
        struct {
                unsigned int fast:1;    /* post with "channel end" */
                unsigned int repall:1;  /* report every interrupt status */
index 91c6028..8fd8c62 100644 (file)
@@ -154,14 +154,7 @@ static inline int ap_instructions_available(void)
  */
 static int ap_interrupts_available(void)
 {
-       unsigned long long facility_bits[2];
-
-       if (stfle(facility_bits, 2) <= 1)
-               return 0;
-       if (!(facility_bits[0] & (1ULL << 61)) ||
-           !(facility_bits[1] & (1ULL << 62)))
-               return 0;
-       return 1;
+       return test_facility(1) && test_facility(2);
 }
 
 /**
index 5a46b8c..375aeea 100644 (file)
@@ -372,21 +372,22 @@ static void hotplug_devices(struct work_struct *dummy)
 /*
  * we emulate the request_irq behaviour on top of s390 extints
  */
-static void kvm_extint_handler(u16 code)
+static void kvm_extint_handler(unsigned int ext_int_code,
+                              unsigned int param32, unsigned long param64)
 {
        struct virtqueue *vq;
        u16 subcode;
        u32 param;
 
-       subcode = S390_lowcore.cpu_addr;
+       subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
                return;
 
        /* The LSB might be overloaded, we have to mask it */
-       vq = (struct virtqueue *)(S390_lowcore.ext_params2 & ~1UL);
+       vq = (struct virtqueue *)(param64 & ~1UL);
 
        /* We use ext_params to decide what this interrupt means */
-       param = S390_lowcore.ext_params & VIRTIO_PARAM_MASK;
+       param = param32 & VIRTIO_PARAM_MASK;
 
        switch (param) {
        case VIRTIO_PARAM_CONFIG_CHANGED:
index 13f48e2..a624f5a 100644 (file)
@@ -461,7 +461,7 @@ static int jsflash_init(void)
 {
        int rc;
        struct jsflash *jsf;
-       int node;
+       phandle node;
        char banner[128];
        struct linux_prom_registers reg0;
 
index 58aa215..664ceb0 100644 (file)
@@ -181,13 +181,8 @@ struct m68k_serial {
 /* 
  * Define the number of ports supported and their irqs.
  */
-#ifndef CONFIG_68328_SERIAL_UART2
 #define NR_PORTS 1
 #define UART_IRQ_DEFNS {UART_IRQ_NUM}
-#else
-#define NR_PORTS 2
-#define UART_IRQ_DEFNS {UART1_IRQ_NUM, UART2_IRQ_NUM}
-#endif
 
 #endif /* __KERNEL__ */
 #endif /* !(_MC683XX_SERIAL_H) */
index 9278164..aff9dcd 100644 (file)
@@ -1410,6 +1410,33 @@ config SERIAL_OF_PLATFORM
          Currently, only 8250 compatible ports are supported, but
          others can easily be added.
 
+config SERIAL_OMAP
+       tristate "OMAP serial port support"
+       depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
+       select SERIAL_CORE
+       help
+         If you have a machine based on an Texas Instruments OMAP CPU you
+         can enable its onboard serial ports by enabling this option.
+
+         By enabling this option you take advantage of dma feature available
+         with the omap-serial driver. DMA support can be enabled from platform
+         data.
+
+config SERIAL_OMAP_CONSOLE
+       bool "Console on OMAP serial port"
+       depends on SERIAL_OMAP
+       select SERIAL_CORE_CONSOLE
+       help
+         Select this option if you would like to use omap serial port as
+         console.
+
+         Even if you say Y here, the currently visible virtual console
+         (/dev/tty0) will still be used as the system console by default, but
+         you can alter that using a kernel command line option such as
+         "console=ttyOx". (Try "man bootparam" or see the documentation of
+         your boot loader about how to pass options to the kernel at
+         boot time.)
+
 config SERIAL_OF_PLATFORM_NWPSERIAL
        tristate "NWP serial port driver"
        depends on PPC_OF && PPC_DCR
index 1ca4fd5..c570576 100644 (file)
@@ -88,3 +88,4 @@ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
 obj-$(CONFIG_SERIAL_MRST_MAX3110)      += mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)   += mfd.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
index 2af8fd1..17849dc 100644 (file)
@@ -31,8 +31,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 {
        struct resource resource;
        struct device_node *np = ofdev->dev.of_node;
-       const unsigned int *clk, *spd;
-       const u32 *prop;
+       const __be32 *clk, *spd;
+       const __be32 *prop;
        int ret, prop_size;
 
        memset(port, 0, sizeof *port);
@@ -55,23 +55,23 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
        /* Check for shifted address mapping */
        prop = of_get_property(np, "reg-offset", &prop_size);
        if (prop && (prop_size == sizeof(u32)))
-               port->mapbase += *prop;
+               port->mapbase += be32_to_cpup(prop);
 
        /* Check for registers offset within the devices address range */
        prop = of_get_property(np, "reg-shift", &prop_size);
        if (prop && (prop_size == sizeof(u32)))
-               port->regshift = *prop;
+               port->regshift = be32_to_cpup(prop);
 
        port->irq = irq_of_parse_and_map(np, 0);
        port->iotype = UPIO_MEM;
        port->type = type;
-       port->uartclk = *clk;
+       port->uartclk = be32_to_cpup(clk);
        port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
                | UPF_FIXED_PORT | UPF_FIXED_TYPE;
        port->dev = &ofdev->dev;
        /* If current-speed was set, then try not to change it. */
        if (spd)
-               port->custom_divisor = *clk / (16 * (*spd));
+               port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd)));
 
        return 0;
 }
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
new file mode 100644 (file)
index 0000000..14365f7
--- /dev/null
@@ -0,0 +1,1333 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *     Govindraj R     <govindraj.raja@ti.com>
+ *     Thara Gopinath  <thara@ti.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.
+ *
+ * Note: This driver is made seperate from 8250 driver as we cannot
+ * over load 8250 driver with omap platform specific configuration for
+ * features like DMA, it makes easier to implement features like DMA and
+ * hardware flow control and software flow control configuration with
+ * this driver as required for the omap-platform.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/omap-serial.h>
+
+static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
+
+/* Forward declaration of functions */
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
+static void serial_omap_rx_timeout(unsigned long uart_no);
+static int serial_omap_start_rxdma(struct uart_omap_port *up);
+
+static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
+{
+       offset <<= up->port.regshift;
+       return readw(up->port.membase + offset);
+}
+
+static inline void serial_out(struct uart_omap_port *up, int offset, int value)
+{
+       offset <<= up->port.regshift;
+       writew(value, up->port.membase + offset);
+}
+
+static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
+{
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                      UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+       serial_out(up, UART_FCR, 0);
+}
+
+/*
+ * serial_omap_get_divisor - calculate divisor value
+ * @port: uart port info
+ * @baud: baudrate for which divisor needs to be calculated.
+ *
+ * We have written our own function to get the divisor so as to support
+ * 13x mode. 3Mbps Baudrate as an different divisor.
+ * Reference OMAP TRM Chapter 17:
+ * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
+ * referring to oversampling - divisor value
+ * baudrate 460,800 to 3,686,400 all have divisor 13
+ * except 3,000,000 which has divisor value 16
+ */
+static unsigned int
+serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
+{
+       unsigned int divisor;
+
+       if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+               divisor = 13;
+       else
+               divisor = 16;
+       return port->uartclk/(baud * divisor);
+}
+
+static void serial_omap_stop_rxdma(struct uart_omap_port *up)
+{
+       if (up->uart_dma.rx_dma_used) {
+               del_timer(&up->uart_dma.rx_timer);
+               omap_stop_dma(up->uart_dma.rx_dma_channel);
+               omap_free_dma(up->uart_dma.rx_dma_channel);
+               up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+               up->uart_dma.rx_dma_used = false;
+       }
+}
+
+static void serial_omap_enable_ms(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+       up->ier |= UART_IER_MSI;
+       serial_out(up, UART_IER, up->ier);
+}
+
+static void serial_omap_stop_tx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       if (up->use_dma &&
+               up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
+               /*
+                * Check if dma is still active. If yes do nothing,
+                * return. Else stop dma
+                */
+               if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
+                       return;
+               omap_stop_dma(up->uart_dma.tx_dma_channel);
+               omap_free_dma(up->uart_dma.tx_dma_channel);
+               up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+       }
+
+       if (up->ier & UART_IER_THRI) {
+               up->ier &= ~UART_IER_THRI;
+               serial_out(up, UART_IER, up->ier);
+       }
+}
+
+static void serial_omap_stop_rx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       if (up->use_dma)
+               serial_omap_stop_rxdma(up);
+       up->ier &= ~UART_IER_RLSI;
+       up->port.read_status_mask &= ~UART_LSR_DR;
+       serial_out(up, UART_IER, up->ier);
+}
+
+static inline void receive_chars(struct uart_omap_port *up, int *status)
+{
+       struct tty_struct *tty = up->port.state->port.tty;
+       unsigned int flag;
+       unsigned char ch, lsr = *status;
+       int max_count = 256;
+
+       do {
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_in(up, UART_RX);
+               flag = TTY_NORMAL;
+               up->port.icount.rx++;
+
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+                       /*
+                        * For statistics only
+                        */
+                       if (lsr & UART_LSR_BI) {
+                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+                               up->port.icount.brk++;
+                               /*
+                                * We do the SysRQ and SAK checking
+                                * here because otherwise the break
+                                * may get masked by ignore_status_mask
+                                * or read_status_mask.
+                                */
+                               if (uart_handle_break(&up->port))
+                                       goto ignore_char;
+                       } else if (lsr & UART_LSR_PE) {
+                               up->port.icount.parity++;
+                       } else if (lsr & UART_LSR_FE) {
+                               up->port.icount.frame++;
+                       }
+
+                       if (lsr & UART_LSR_OE)
+                               up->port.icount.overrun++;
+
+                       /*
+                        * Mask off conditions which should be ignored.
+                        */
+                       lsr &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+                       if (up->port.line == up->port.cons->index) {
+                               /* Recover the break flag from console xmit */
+                               lsr |= up->lsr_break_flag;
+                               up->lsr_break_flag = 0;
+                       }
+#endif
+                       if (lsr & UART_LSR_BI)
+                               flag = TTY_BREAK;
+                       else if (lsr & UART_LSR_PE)
+                               flag = TTY_PARITY;
+                       else if (lsr & UART_LSR_FE)
+                               flag = TTY_FRAME;
+               }
+
+               if (uart_handle_sysrq_char(&up->port, ch))
+                       goto ignore_char;
+               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+ignore_char:
+               lsr = serial_in(up, UART_LSR);
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+       spin_unlock(&up->port.lock);
+       tty_flip_buffer_push(tty);
+       spin_lock(&up->port.lock);
+}
+
+static void transmit_chars(struct uart_omap_port *up)
+{
+       struct circ_buf *xmit = &up->port.state->xmit;
+       int count;
+
+       if (up->port.x_char) {
+               serial_out(up, UART_TX, up->port.x_char);
+               up->port.icount.tx++;
+               up->port.x_char = 0;
+               return;
+       }
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+               serial_omap_stop_tx(&up->port);
+               return;
+       }
+       count = up->port.fifosize / 4;
+       do {
+               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               up->port.icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       } while (--count > 0);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+
+       if (uart_circ_empty(xmit))
+               serial_omap_stop_tx(&up->port);
+}
+
+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+       if (!(up->ier & UART_IER_THRI)) {
+               up->ier |= UART_IER_THRI;
+               serial_out(up, UART_IER, up->ier);
+       }
+}
+
+static void serial_omap_start_tx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       struct circ_buf *xmit;
+       unsigned int start;
+       int ret = 0;
+
+       if (!up->use_dma) {
+               serial_omap_enable_ier_thri(up);
+               return;
+       }
+
+       if (up->uart_dma.tx_dma_used)
+               return;
+
+       xmit = &up->port.state->xmit;
+
+       if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
+               ret = omap_request_dma(up->uart_dma.uart_dma_tx,
+                               "UART Tx DMA",
+                               (void *)uart_tx_dma_callback, up,
+                               &(up->uart_dma.tx_dma_channel));
+
+               if (ret < 0) {
+                       serial_omap_enable_ier_thri(up);
+                       return;
+               }
+       }
+       spin_lock(&(up->uart_dma.tx_lock));
+       up->uart_dma.tx_dma_used = true;
+       spin_unlock(&(up->uart_dma.tx_lock));
+
+       start = up->uart_dma.tx_buf_dma_phys +
+                               (xmit->tail & (UART_XMIT_SIZE - 1));
+
+       up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+       /*
+        * It is a circular buffer. See if the buffer has wounded back.
+        * If yes it will have to be transferred in two separate dma
+        * transfers
+        */
+       if (start + up->uart_dma.tx_buf_size >=
+                       up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+               up->uart_dma.tx_buf_size =
+                       (up->uart_dma.tx_buf_dma_phys +
+                       UART_XMIT_SIZE) - start;
+
+       omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+       omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+       omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.tx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_tx, 0);
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static unsigned int check_modem_status(struct uart_omap_port *up)
+{
+       unsigned int status;
+
+       status = serial_in(up, UART_MSR);
+       status |= up->msr_saved_flags;
+       up->msr_saved_flags = 0;
+       if ((status & UART_MSR_ANY_DELTA) == 0)
+               return status;
+
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+           up->port.state != NULL) {
+               if (status & UART_MSR_TERI)
+                       up->port.icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       up->port.icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change
+                               (&up->port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change
+                               (&up->port, status & UART_MSR_CTS);
+               wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+       }
+
+       return status;
+}
+
+/**
+ * serial_omap_irq() - This handles the interrupt from one port
+ * @irq: uart port irq number
+ * @dev_id: uart port info
+ */
+static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+{
+       struct uart_omap_port *up = dev_id;
+       unsigned int iir, lsr;
+       unsigned long flags;
+
+       iir = serial_in(up, UART_IIR);
+       if (iir & UART_IIR_NO_INT)
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       lsr = serial_in(up, UART_LSR);
+       if (iir & UART_IIR_RLSI) {
+               if (!up->use_dma) {
+                       if (lsr & UART_LSR_DR)
+                               receive_chars(up, &lsr);
+               } else {
+                       up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+                       if ((serial_omap_start_rxdma(up) != 0) &&
+                                       (lsr & UART_LSR_DR))
+                               receive_chars(up, &lsr);
+               }
+       }
+
+       check_modem_status(up);
+       if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
+               transmit_chars(up);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       up->port_activity = jiffies;
+       return IRQ_HANDLED;
+}
+
+static unsigned int serial_omap_tx_empty(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+       unsigned int ret = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
+       spin_lock_irqsave(&up->port.lock, flags);
+       ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       return ret;
+}
+
+static unsigned int serial_omap_get_mctrl(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char status;
+       unsigned int ret = 0;
+
+       status = check_modem_status(up);
+       dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
+
+       if (status & UART_MSR_DCD)
+               ret |= TIOCM_CAR;
+       if (status & UART_MSR_RI)
+               ret |= TIOCM_RNG;
+       if (status & UART_MSR_DSR)
+               ret |= TIOCM_DSR;
+       if (status & UART_MSR_CTS)
+               ret |= TIOCM_CTS;
+       return ret;
+}
+
+static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char mcr = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+       if (mctrl & TIOCM_RTS)
+               mcr |= UART_MCR_RTS;
+       if (mctrl & TIOCM_DTR)
+               mcr |= UART_MCR_DTR;
+       if (mctrl & TIOCM_OUT1)
+               mcr |= UART_MCR_OUT1;
+       if (mctrl & TIOCM_OUT2)
+               mcr |= UART_MCR_OUT2;
+       if (mctrl & TIOCM_LOOP)
+               mcr |= UART_MCR_LOOP;
+
+       mcr |= up->mcr;
+       serial_out(up, UART_MCR, mcr);
+}
+
+static void serial_omap_break_ctl(struct uart_port *port, int break_state)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+       spin_lock_irqsave(&up->port.lock, flags);
+       if (break_state == -1)
+               up->lcr |= UART_LCR_SBC;
+       else
+               up->lcr &= ~UART_LCR_SBC;
+       serial_out(up, UART_LCR, up->lcr);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial_omap_startup(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+       int retval;
+
+       /*
+        * Allocate the IRQ
+        */
+       retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
+                               up->name, up);
+       if (retval)
+               return retval;
+
+       dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+
+       /*
+        * Clear the FIFO buffers and disable them.
+        * (they will be reenabled in set_termios())
+        */
+       serial_omap_clear_fifos(up);
+       /* For Hardware flow control */
+       serial_out(up, UART_MCR, UART_MCR_RTS);
+
+       /*
+        * Clear the interrupt registers.
+        */
+       (void) serial_in(up, UART_LSR);
+       if (serial_in(up, UART_LSR) & UART_LSR_DR)
+               (void) serial_in(up, UART_RX);
+       (void) serial_in(up, UART_IIR);
+       (void) serial_in(up, UART_MSR);
+
+       /*
+        * Now, initialize the UART
+        */
+       serial_out(up, UART_LCR, UART_LCR_WLEN8);
+       spin_lock_irqsave(&up->port.lock, flags);
+       /*
+        * Most PC uarts need OUT2 raised to enable interrupts.
+        */
+       up->port.mctrl |= TIOCM_OUT2;
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       up->msr_saved_flags = 0;
+       if (up->use_dma) {
+               free_page((unsigned long)up->port.state->xmit.buf);
+               up->port.state->xmit.buf = dma_alloc_coherent(NULL,
+                       UART_XMIT_SIZE,
+                       (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
+                       0);
+               init_timer(&(up->uart_dma.rx_timer));
+               up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+               up->uart_dma.rx_timer.data = up->pdev->id;
+               /* Currently the buffer size is 4KB. Can increase it */
+               up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
+                       up->uart_dma.rx_buf_size,
+                       (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
+       }
+       /*
+        * Finally, enable interrupts. Note: Modem status interrupts
+        * are set via set_termios(), which will be occurring imminently
+        * anyway, so we don't enable them here.
+        */
+       up->ier = UART_IER_RLSI | UART_IER_RDI;
+       serial_out(up, UART_IER, up->ier);
+
+       up->port_activity = jiffies;
+       return 0;
+}
+
+static void serial_omap_shutdown(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+       /*
+        * Disable interrupts from this port
+        */
+       up->ier = 0;
+       serial_out(up, UART_IER, 0);
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       up->port.mctrl &= ~TIOCM_OUT2;
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       /*
+        * Disable break condition and FIFOs
+        */
+       serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+       serial_omap_clear_fifos(up);
+
+       /*
+        * Read data port to reset things, and then free the irq
+        */
+       if (serial_in(up, UART_LSR) & UART_LSR_DR)
+               (void) serial_in(up, UART_RX);
+       if (up->use_dma) {
+               dma_free_coherent(up->port.dev,
+                       UART_XMIT_SIZE, up->port.state->xmit.buf,
+                       up->uart_dma.tx_buf_dma_phys);
+               up->port.state->xmit.buf = NULL;
+               serial_omap_stop_rx(port);
+               dma_free_coherent(up->port.dev,
+                       up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
+                       up->uart_dma.rx_buf_dma_phys);
+               up->uart_dma.rx_buf = NULL;
+       }
+       free_irq(up->port.irq, up);
+}
+
+static inline void
+serial_omap_configure_xonxoff
+               (struct uart_omap_port *up, struct ktermios *termios)
+{
+       unsigned char efr = 0;
+
+       up->lcr = serial_in(up, UART_LCR);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
+
+       serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+       serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+       /* clear SW control mode bits */
+       efr = up->efr;
+       efr &= OMAP_UART_SW_CLR;
+
+       /*
+        * IXON Flag:
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
+        */
+       if (termios->c_iflag & IXON)
+               efr |= OMAP_UART_SW_TX;
+
+       /*
+        * IXOFF Flag:
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
+        */
+       if (termios->c_iflag & IXOFF)
+               efr |= OMAP_UART_SW_RX;
+
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+       up->mcr = serial_in(up, UART_MCR);
+
+       /*
+        * IXANY Flag:
+        * Enable any character to restart output.
+        * Operation resumes after receiving any
+        * character after recognition of the XOFF character
+        */
+       if (termios->c_iflag & IXANY)
+               up->mcr |= UART_MCR_XONANY;
+
+       serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+       /* Enable special char function UARTi.EFR_REG[5] and
+        * load the new software flow control mode IXON or IXOFF
+        * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
+        */
+       serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+       serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
+       serial_out(up, UART_LCR, up->lcr);
+}
+
+static void
+serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
+                       struct ktermios *old)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char cval = 0;
+       unsigned char efr = 0;
+       unsigned long flags = 0;
+       unsigned int baud, quot;
+
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               cval = UART_LCR_WLEN5;
+               break;
+       case CS6:
+               cval = UART_LCR_WLEN6;
+               break;
+       case CS7:
+               cval = UART_LCR_WLEN7;
+               break;
+       default:
+       case CS8:
+               cval = UART_LCR_WLEN8;
+               break;
+       }
+
+       if (termios->c_cflag & CSTOPB)
+               cval |= UART_LCR_STOP;
+       if (termios->c_cflag & PARENB)
+               cval |= UART_LCR_PARITY;
+       if (!(termios->c_cflag & PARODD))
+               cval |= UART_LCR_EPAR;
+
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
+       quot = serial_omap_get_divisor(port, baud);
+
+       up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
+                       UART_FCR_ENABLE_FIFO;
+       if (up->use_dma)
+               up->fcr |= UART_FCR_DMA_SELECT;
+
+       /*
+        * Ok, we're now changing the port state. Do it with
+        * interrupts disabled.
+        */
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+       if (termios->c_iflag & INPCK)
+               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               up->port.read_status_mask |= UART_LSR_BI;
+
+       /*
+        * Characters to ignore
+        */
+       up->port.ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+       if (termios->c_iflag & IGNBRK) {
+               up->port.ignore_status_mask |= UART_LSR_BI;
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       up->port.ignore_status_mask |= UART_LSR_OE;
+       }
+
+       /*
+        * ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               up->port.ignore_status_mask |= UART_LSR_DR;
+
+       /*
+        * Modem status interrupts
+        */
+       up->ier &= ~UART_IER_MSI;
+       if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+               up->ier |= UART_IER_MSI;
+       serial_out(up, UART_IER, up->ier);
+       serial_out(up, UART_LCR, cval);         /* reset DLAB */
+
+       /* FIFOs and DMA Settings */
+
+       /* FCR can be changed only when the
+        * baud clock is not running
+        * DLL_REG and DLH_REG set to 0.
+        */
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       serial_out(up, UART_DLL, 0);
+       serial_out(up, UART_DLM, 0);
+       serial_out(up, UART_LCR, 0);
+
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       up->mcr = serial_in(up, UART_MCR);
+       serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+       /* FIFO ENABLE, DMA MODE */
+       serial_out(up, UART_FCR, up->fcr);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       if (up->use_dma) {
+               serial_out(up, UART_TI752_TLR, 0);
+               serial_out(up, UART_OMAP_SCR,
+                       (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8));
+       }
+
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       serial_out(up, UART_MCR, up->mcr);
+
+       /* Protocol, Baud Rate, and Interrupt Settings */
+
+       serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+       serial_out(up, UART_LCR, 0);
+       serial_out(up, UART_IER, 0);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
+       serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+
+       serial_out(up, UART_LCR, 0);
+       serial_out(up, UART_IER, up->ier);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, cval);
+
+       if (baud > 230400 && baud != 3000000)
+               serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X);
+       else
+               serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X);
+
+       /* Hardware Flow Control Configuration */
+
+       if (termios->c_cflag & CRTSCTS) {
+               efr |= (UART_EFR_CTS | UART_EFR_RTS);
+               serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+               up->mcr = serial_in(up, UART_MCR);
+               serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+
+               serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+               up->efr = serial_in(up, UART_EFR);
+               serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+               serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+               serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
+               serial_out(up, UART_LCR, UART_LCR_DLAB);
+               serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
+               serial_out(up, UART_LCR, cval);
+       }
+
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       /* Software Flow Control Configuration */
+       if (termios->c_iflag & (IXON | IXOFF))
+               serial_omap_configure_xonxoff(up, termios);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
+}
+
+static void
+serial_omap_pm(struct uart_port *port, unsigned int state,
+              unsigned int oldstate)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char efr;
+
+       dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+       serial_out(up, UART_LCR, 0);
+
+       serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       serial_out(up, UART_EFR, efr);
+       serial_out(up, UART_LCR, 0);
+       /* Enable module level wake up */
+       serial_out(up, UART_OMAP_WER,
+               (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0);
+}
+
+static void serial_omap_release_port(struct uart_port *port)
+{
+       dev_dbg(port->dev, "serial_omap_release_port+\n");
+}
+
+static int serial_omap_request_port(struct uart_port *port)
+{
+       dev_dbg(port->dev, "serial_omap_request_port+\n");
+       return 0;
+}
+
+static void serial_omap_config_port(struct uart_port *port, int flags)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
+                                                       up->pdev->id);
+       up->port.type = PORT_OMAP;
+}
+
+static int
+serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       /* we don't want the core code to modify any port params */
+       dev_dbg(port->dev, "serial_omap_verify_port+\n");
+       return -EINVAL;
+}
+
+static const char *
+serial_omap_type(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
+       return up->name;
+}
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+
+static struct uart_omap_port *serial_omap_console_ports[4];
+
+static struct uart_driver serial_omap_reg;
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void wait_for_xmitr(struct uart_omap_port *up)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       do {
+               status = serial_in(up, UART_LSR);
+
+               if (status & UART_LSR_BI)
+                       up->lsr_break_flag = UART_LSR_BI;
+
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               tmout = 1000000;
+               for (tmout = 1000000; tmout; tmout--) {
+                       unsigned int msr = serial_in(up, UART_MSR);
+
+                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+                       if (msr & UART_MSR_CTS)
+                               break;
+
+                       udelay(1);
+               }
+       }
+}
+
+static void serial_omap_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       wait_for_xmitr(up);
+       serial_out(up, UART_TX, ch);
+}
+
+static void
+serial_omap_console_write(struct console *co, const char *s,
+               unsigned int count)
+{
+       struct uart_omap_port *up = serial_omap_console_ports[co->index];
+       unsigned long flags;
+       unsigned int ier;
+       int locked = 1;
+
+       local_irq_save(flags);
+       if (up->port.sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock(&up->port.lock);
+       else
+               spin_lock(&up->port.lock);
+
+       /*
+        * First save the IER then disable the interrupts
+        */
+       ier = serial_in(up, UART_IER);
+       serial_out(up, UART_IER, 0);
+
+       uart_console_write(&up->port, s, count, serial_omap_console_putchar);
+
+       /*
+        * Finally, wait for transmitter to become empty
+        * and restore the IER
+        */
+       wait_for_xmitr(up);
+       serial_out(up, UART_IER, ier);
+       /*
+        * The receive handling will happen properly because the
+        * receive ready bit will still be set; it is not cleared
+        * on read.  However, modem control will not, we must
+        * call it if we have saved something in the saved flags
+        * while processing with interrupts off.
+        */
+       if (up->msr_saved_flags)
+               check_modem_status(up);
+
+       if (locked)
+               spin_unlock(&up->port.lock);
+       local_irq_restore(flags);
+}
+
+static int __init
+serial_omap_console_setup(struct console *co, char *options)
+{
+       struct uart_omap_port *up;
+       int baud = 115200;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (serial_omap_console_ports[co->index] == NULL)
+               return -ENODEV;
+       up = serial_omap_console_ports[co->index];
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static struct console serial_omap_console = {
+       .name           = OMAP_SERIAL_NAME,
+       .write          = serial_omap_console_write,
+       .device         = uart_console_device,
+       .setup          = serial_omap_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &serial_omap_reg,
+};
+
+static void serial_omap_add_console_port(struct uart_omap_port *up)
+{
+       serial_omap_console_ports[up->pdev->id] = up;
+}
+
+#define OMAP_CONSOLE   (&serial_omap_console)
+
+#else
+
+#define OMAP_CONSOLE   NULL
+
+static inline void serial_omap_add_console_port(struct uart_omap_port *up)
+{}
+
+#endif
+
+static struct uart_ops serial_omap_pops = {
+       .tx_empty       = serial_omap_tx_empty,
+       .set_mctrl      = serial_omap_set_mctrl,
+       .get_mctrl      = serial_omap_get_mctrl,
+       .stop_tx        = serial_omap_stop_tx,
+       .start_tx       = serial_omap_start_tx,
+       .stop_rx        = serial_omap_stop_rx,
+       .enable_ms      = serial_omap_enable_ms,
+       .break_ctl      = serial_omap_break_ctl,
+       .startup        = serial_omap_startup,
+       .shutdown       = serial_omap_shutdown,
+       .set_termios    = serial_omap_set_termios,
+       .pm             = serial_omap_pm,
+       .type           = serial_omap_type,
+       .release_port   = serial_omap_release_port,
+       .request_port   = serial_omap_request_port,
+       .config_port    = serial_omap_config_port,
+       .verify_port    = serial_omap_verify_port,
+};
+
+static struct uart_driver serial_omap_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "OMAP-SERIAL",
+       .dev_name       = OMAP_SERIAL_NAME,
+       .nr             = OMAP_MAX_HSUART_PORTS,
+       .cons           = OMAP_CONSOLE,
+};
+
+static int
+serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct uart_omap_port *up = platform_get_drvdata(pdev);
+
+       if (up)
+               uart_suspend_port(&serial_omap_reg, &up->port);
+       return 0;
+}
+
+static int serial_omap_resume(struct platform_device *dev)
+{
+       struct uart_omap_port *up = platform_get_drvdata(dev);
+
+       if (up)
+               uart_resume_port(&serial_omap_reg, &up->port);
+       return 0;
+}
+
+static void serial_omap_rx_timeout(unsigned long uart_no)
+{
+       struct uart_omap_port *up = ui[uart_no];
+       unsigned int curr_dma_pos, curr_transmitted_size;
+       int ret = 0;
+
+       curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
+       if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
+                            (curr_dma_pos == 0)) {
+               if (jiffies_to_msecs(jiffies - up->port_activity) <
+                                                       RX_TIMEOUT) {
+                       mod_timer(&up->uart_dma.rx_timer, jiffies +
+                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+               } else {
+                       serial_omap_stop_rxdma(up);
+                       up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+               }
+               return;
+       }
+
+       curr_transmitted_size = curr_dma_pos -
+                                       up->uart_dma.prev_rx_dma_pos;
+       up->port.icount.rx += curr_transmitted_size;
+       tty_insert_flip_string(up->port.state->port.tty,
+                       up->uart_dma.rx_buf +
+                       (up->uart_dma.prev_rx_dma_pos -
+                       up->uart_dma.rx_buf_dma_phys),
+                       curr_transmitted_size);
+       tty_flip_buffer_push(up->port.state->port.tty);
+       up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
+       if (up->uart_dma.rx_buf_size +
+                       up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
+               ret = serial_omap_start_rxdma(up);
+               if (ret < 0) {
+                       serial_omap_stop_rxdma(up);
+                       up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+               }
+       } else  {
+               mod_timer(&up->uart_dma.rx_timer, jiffies +
+                       usecs_to_jiffies(up->uart_dma.rx_timeout));
+       }
+       up->port_activity = jiffies;
+}
+
+static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       return;
+}
+
+static int serial_omap_start_rxdma(struct uart_omap_port *up)
+{
+       int ret = 0;
+
+       if (up->uart_dma.rx_dma_channel == -1) {
+               ret = omap_request_dma(up->uart_dma.uart_dma_rx,
+                               "UART Rx DMA",
+                               (void *)uart_rx_dma_callback, up,
+                               &(up->uart_dma.rx_dma_channel));
+               if (ret < 0)
+                       return ret;
+
+               omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+               omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC,
+                               up->uart_dma.rx_buf_dma_phys, 0, 0);
+               omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.rx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_rx, 0);
+       }
+       up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.rx_dma_channel);
+       mod_timer(&up->uart_dma.rx_timer, jiffies +
+                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+       up->uart_dma.rx_dma_used = true;
+       return ret;
+}
+
+static void serial_omap_continue_tx(struct uart_omap_port *up)
+{
+       struct circ_buf *xmit = &up->port.state->xmit;
+       unsigned int start = up->uart_dma.tx_buf_dma_phys
+                       + (xmit->tail & (UART_XMIT_SIZE - 1));
+
+       if (uart_circ_empty(xmit))
+               return;
+
+       up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+       /*
+        * It is a circular buffer. See if the buffer has wounded back.
+        * If yes it will have to be transferred in two separate dma
+        * transfers
+        */
+       if (start + up->uart_dma.tx_buf_size >=
+                       up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+               up->uart_dma.tx_buf_size =
+                       (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
+       omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+       omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+       omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.tx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_tx, 0);
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)data;
+       struct circ_buf *xmit = &up->port.state->xmit;
+
+       xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
+                       (UART_XMIT_SIZE - 1);
+       up->port.icount.tx += up->uart_dma.tx_buf_size;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+
+       if (uart_circ_empty(xmit)) {
+               spin_lock(&(up->uart_dma.tx_lock));
+               serial_omap_stop_tx(&up->port);
+               up->uart_dma.tx_dma_used = false;
+               spin_unlock(&(up->uart_dma.tx_lock));
+       } else {
+               omap_stop_dma(up->uart_dma.tx_dma_channel);
+               serial_omap_continue_tx(up);
+       }
+       up->port_activity = jiffies;
+       return;
+}
+
+static int serial_omap_probe(struct platform_device *pdev)
+{
+       struct uart_omap_port   *up;
+       struct resource         *mem, *irq, *dma_tx, *dma_rx;
+       struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+       int ret = -ENOSPC;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                                    pdev->dev.driver->name)) {
+               dev_err(&pdev->dev, "memory region already claimed\n");
+               return -EBUSY;
+       }
+
+       dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (!dma_rx) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (!dma_tx) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       up = kzalloc(sizeof(*up), GFP_KERNEL);
+       if (up == NULL) {
+               ret = -ENOMEM;
+               goto do_release_region;
+       }
+       sprintf(up->name, "OMAP UART%d", pdev->id);
+       up->pdev = pdev;
+       up->port.dev = &pdev->dev;
+       up->port.type = PORT_OMAP;
+       up->port.iotype = UPIO_MEM;
+       up->port.irq = irq->start;
+
+       up->port.regshift = 2;
+       up->port.fifosize = 64;
+       up->port.ops = &serial_omap_pops;
+       up->port.line = pdev->id;
+
+       up->port.membase = omap_up_info->membase;
+       up->port.mapbase = omap_up_info->mapbase;
+       up->port.flags = omap_up_info->flags;
+       up->port.irqflags = omap_up_info->irqflags;
+       up->port.uartclk = omap_up_info->uartclk;
+       up->uart_dma.uart_base = mem->start;
+
+       if (omap_up_info->dma_enabled) {
+               up->uart_dma.uart_dma_tx = dma_tx->start;
+               up->uart_dma.uart_dma_rx = dma_rx->start;
+               up->use_dma = 1;
+               up->uart_dma.rx_buf_size = 4096;
+               up->uart_dma.rx_timeout = 2;
+               spin_lock_init(&(up->uart_dma.tx_lock));
+               spin_lock_init(&(up->uart_dma.rx_lock));
+               up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+               up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+       }
+
+       ui[pdev->id] = up;
+       serial_omap_add_console_port(up);
+
+       ret = uart_add_one_port(&serial_omap_reg, &up->port);
+       if (ret != 0)
+               goto do_release_region;
+
+       platform_set_drvdata(pdev, up);
+       return 0;
+err:
+       dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
+                               pdev->id, __func__, ret);
+do_release_region:
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       return ret;
+}
+
+static int serial_omap_remove(struct platform_device *dev)
+{
+       struct uart_omap_port *up = platform_get_drvdata(dev);
+
+       platform_set_drvdata(dev, NULL);
+       if (up) {
+               uart_remove_one_port(&serial_omap_reg, &up->port);
+               kfree(up);
+       }
+       return 0;
+}
+
+static struct platform_driver serial_omap_driver = {
+       .probe          = serial_omap_probe,
+       .remove         = serial_omap_remove,
+
+       .suspend        = serial_omap_suspend,
+       .resume         = serial_omap_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init serial_omap_init(void)
+{
+       int ret;
+
+       ret = uart_register_driver(&serial_omap_reg);
+       if (ret != 0)
+               return ret;
+       ret = platform_driver_register(&serial_omap_driver);
+       if (ret != 0)
+               uart_unregister_driver(&serial_omap_reg);
+       return ret;
+}
+
+static void __exit serial_omap_exit(void)
+{
+       platform_driver_unregister(&serial_omap_driver);
+       uart_unregister_driver(&serial_omap_reg);
+}
+
+module_init(serial_omap_init);
+module_exit(serial_omap_exit);
+
+MODULE_DESCRIPTION("OMAP High Speed UART driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments Inc");
index 9b52f77..d2352ac 100644 (file)
 # define SCSPTR0       0xffe00024      /* 16 bit SCIF */
 # define SCSPTR1       0xffe10024      /* 16 bit SCIF */
 # define SCIF_ORER     0x0001          /* Overrun error bit */
-# define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+
+#if defined(CONFIG_SH_SH2007)
+/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */
+# define SCSCR_INIT(port)      0x38
+#else
+/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */
+# define SCSCR_INIT(port)      0x3a
+#endif
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
       defined(CONFIG_CPU_SUBTYPE_SH7786)
 # define SCSPTR0       0xffea0024      /* 16 bit SCIF */
@@ -616,9 +624,10 @@ static inline int sci_rxd_in(struct uart_port *port)
  * -- Mitch Davis - 15 Jul 2000
  */
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
+#if (defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
+     defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
+     defined(CONFIG_CPU_SUBTYPE_SH7786)) && \
+    !defined(CONFIG_SH_SH2007)
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
index a54de0b..f168a61 100644 (file)
@@ -1,24 +1,5 @@
-config INTC_USERIMASK
-       bool "Userspace interrupt masking support"
-       depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A)
-       help
-         This enables support for hardware-assisted userspace hardirq
-         masking.
+menu "SuperH / SH-Mobile Driver Options"
 
-         SH-4A and newer interrupt blocks all support a special shadowed
-         page with all non-masking registers obscured when mapped in to
-         userspace. This is primarily for use by userspace device
-         drivers that are using special priority levels.
+source "drivers/sh/intc/Kconfig"
 
-         If in doubt, say N.
-
-config INTC_BALANCING
-       bool "Hardware IRQ balancing support"
-       depends on SMP && SUPERH && CPU_SUBTYPE_SH7786
-       help
-         This enables support for IRQ auto-distribution mode on SH-X3
-         SMP parts. All of the balancing and CPU wakeup decisions are
-         taken care of automatically by hardware for distributed
-         vectors.
-
-         If in doubt, say N.
+endmenu
index 08fc653..24e6cec 100644 (file)
@@ -1,10 +1,9 @@
 #
 # Makefile for the SuperH specific drivers.
 #
-obj-y  := clk.o intc.o
+obj-y  := intc/
 
-obj-$(CONFIG_SUPERHYWAY)       += superhyway/
+obj-$(CONFIG_HAVE_CLK)         += clk/
 obj-$(CONFIG_MAPLE)            += maple/
-
+obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_GENERIC_GPIO)     += pfc.o
-obj-$(CONFIG_SH_CLK_CPG)       += clk-cpg.o
diff --git a/drivers/sh/clk/Makefile b/drivers/sh/clk/Makefile
new file mode 100644 (file)
index 0000000..5d15ebf
--- /dev/null
@@ -0,0 +1,3 @@
+obj-y  := core.o
+
+obj-$(CONFIG_SH_CLK_CPG)       += cpg.o
similarity index 74%
rename from drivers/sh/clk.c
rename to drivers/sh/clk/core.c
index 5d84ada..fd0d1b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * drivers/sh/clk.c - SuperH clock framework
+ * SuperH clock framework
  *
- *  Copyright (C) 2005 - 2009  Paul Mundt
+ *  Copyright (C) 2005 - 2010  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
@@ -14,6 +14,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define pr_fmt(fmt) "clock: " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -23,7 +25,7 @@
 #include <linux/sysdev.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/io.h>
 #include <linux/debugfs.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
@@ -43,6 +45,8 @@ void clk_rate_table_build(struct clk *clk,
        unsigned long freq;
        int i;
 
+       clk->nr_freqs = nr_freqs;
+
        for (i = 0; i < nr_freqs; i++) {
                div = 1;
                mult = 1;
@@ -67,29 +71,39 @@ void clk_rate_table_build(struct clk *clk,
        freq_table[i].frequency = CPUFREQ_TABLE_END;
 }
 
-long clk_rate_table_round(struct clk *clk,
-                         struct cpufreq_frequency_table *freq_table,
-                         unsigned long rate)
+struct clk_rate_round_data;
+
+struct clk_rate_round_data {
+       unsigned long rate;
+       unsigned int min, max;
+       long (*func)(unsigned int, struct clk_rate_round_data *);
+       void *arg;
+};
+
+#define for_each_frequency(pos, r, freq)                       \
+       for (pos = r->min, freq = r->func(pos, r);              \
+            pos <= r->max; pos++, freq = r->func(pos, r))      \
+               if (unlikely(freq == 0))                        \
+                       ;                                       \
+               else
+
+static long clk_rate_round_helper(struct clk_rate_round_data *rounder)
 {
        unsigned long rate_error, rate_error_prev = ~0UL;
-       unsigned long rate_best_fit = rate;
-       unsigned long highest, lowest;
+       unsigned long rate_best_fit = rounder->rate;
+       unsigned long highest, lowest, freq;
        int i;
 
-       highest = lowest = 0;
-
-       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-               unsigned long freq = freq_table[i].frequency;
-
-               if (freq == CPUFREQ_ENTRY_INVALID)
-                       continue;
+       highest = 0;
+       lowest = ~0UL;
 
+       for_each_frequency(i, rounder, freq) {
                if (freq > highest)
                        highest = freq;
                if (freq < lowest)
                        lowest = freq;
 
-               rate_error = abs(freq - rate);
+               rate_error = abs(freq - rounder->rate);
                if (rate_error < rate_error_prev) {
                        rate_best_fit = freq;
                        rate_error_prev = rate_error;
@@ -99,14 +113,64 @@ long clk_rate_table_round(struct clk *clk,
                        break;
        }
 
-       if (rate >= highest)
+       if (rounder->rate >= highest)
                rate_best_fit = highest;
-       if (rate <= lowest)
+       if (rounder->rate <= lowest)
                rate_best_fit = lowest;
 
        return rate_best_fit;
 }
 
+static long clk_rate_table_iter(unsigned int pos,
+                               struct clk_rate_round_data *rounder)
+{
+       struct cpufreq_frequency_table *freq_table = rounder->arg;
+       unsigned long freq = freq_table[pos].frequency;
+
+       if (freq == CPUFREQ_ENTRY_INVALID)
+               freq = 0;
+
+       return freq;
+}
+
+long clk_rate_table_round(struct clk *clk,
+                         struct cpufreq_frequency_table *freq_table,
+                         unsigned long rate)
+{
+       struct clk_rate_round_data table_round = {
+               .min    = 0,
+               .max    = clk->nr_freqs - 1,
+               .func   = clk_rate_table_iter,
+               .arg    = freq_table,
+               .rate   = rate,
+       };
+
+       if (clk->nr_freqs < 1)
+               return 0;
+
+       return clk_rate_round_helper(&table_round);
+}
+
+static long clk_rate_div_range_iter(unsigned int pos,
+                                   struct clk_rate_round_data *rounder)
+{
+       return clk_get_rate(rounder->arg) / pos;
+}
+
+long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
+                             unsigned int div_max, unsigned long rate)
+{
+       struct clk_rate_round_data div_range_round = {
+               .min    = div_min,
+               .max    = div_max,
+               .func   = clk_rate_div_range_iter,
+               .arg    = clk_get_parent(clk),
+               .rate   = rate,
+       };
+
+       return clk_rate_round_helper(&div_range_round);
+}
+
 int clk_rate_table_find(struct clk *clk,
                        struct cpufreq_frequency_table *freq_table,
                        unsigned long rate)
@@ -160,8 +224,8 @@ void propagate_rate(struct clk *tclk)
 
 static void __clk_disable(struct clk *clk)
 {
-       if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n",
-                clk->name))
+       if (WARN(!clk->usecount, "Trying to disable clock %p with 0 usecount\n",
+                clk))
                return;
 
        if (!(--clk->usecount)) {
@@ -248,8 +312,88 @@ void recalculate_root_clocks(void)
        }
 }
 
+static struct clk_mapping dummy_mapping;
+
+static struct clk *lookup_root_clock(struct clk *clk)
+{
+       while (clk->parent)
+               clk = clk->parent;
+
+       return clk;
+}
+
+static int clk_establish_mapping(struct clk *clk)
+{
+       struct clk_mapping *mapping = clk->mapping;
+
+       /*
+        * Propagate mappings.
+        */
+       if (!mapping) {
+               struct clk *clkp;
+
+               /*
+                * dummy mapping for root clocks with no specified ranges
+                */
+               if (!clk->parent) {
+                       clk->mapping = &dummy_mapping;
+                       return 0;
+               }
+
+               /*
+                * If we're on a child clock and it provides no mapping of its
+                * own, inherit the mapping from its root clock.
+                */
+               clkp = lookup_root_clock(clk);
+               mapping = clkp->mapping;
+               BUG_ON(!mapping);
+       }
+
+       /*
+        * Establish initial mapping.
+        */
+       if (!mapping->base && mapping->phys) {
+               kref_init(&mapping->ref);
+
+               mapping->base = ioremap_nocache(mapping->phys, mapping->len);
+               if (unlikely(!mapping->base))
+                       return -ENXIO;
+       } else if (mapping->base) {
+               /*
+                * Bump the refcount for an existing mapping
+                */
+               kref_get(&mapping->ref);
+       }
+
+       clk->mapping = mapping;
+       return 0;
+}
+
+static void clk_destroy_mapping(struct kref *kref)
+{
+       struct clk_mapping *mapping;
+
+       mapping = container_of(kref, struct clk_mapping, ref);
+
+       iounmap(mapping->base);
+}
+
+static void clk_teardown_mapping(struct clk *clk)
+{
+       struct clk_mapping *mapping = clk->mapping;
+
+       /* Nothing to do */
+       if (mapping == &dummy_mapping)
+               return;
+
+       kref_put(&mapping->ref, clk_destroy_mapping);
+       clk->mapping = NULL;
+}
+
 int clk_register(struct clk *clk)
 {
+       int ret;
+
        if (clk == NULL || IS_ERR(clk))
                return -EINVAL;
 
@@ -264,6 +408,10 @@ int clk_register(struct clk *clk)
        INIT_LIST_HEAD(&clk->children);
        clk->usecount = 0;
 
+       ret = clk_establish_mapping(clk);
+       if (unlikely(ret))
+               goto out_unlock;
+
        if (clk->parent)
                list_add(&clk->sibling, &clk->parent->children);
        else
@@ -272,9 +420,11 @@ int clk_register(struct clk *clk)
        list_add(&clk->node, &clock_list);
        if (clk->ops && clk->ops->init)
                clk->ops->init(clk);
+
+out_unlock:
        mutex_unlock(&clock_list_sem);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
@@ -283,6 +433,7 @@ void clk_unregister(struct clk *clk)
        mutex_lock(&clock_list_sem);
        list_del(&clk->sibling);
        list_del(&clk->node);
+       clk_teardown_mapping(clk);
        mutex_unlock(&clock_list_sem);
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
@@ -354,10 +505,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
                        ret = clk_reparent(clk, parent);
 
                if (ret == 0) {
-                       pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
-                                clk->name, clk->parent->name, clk->rate);
                        if (clk->ops->recalc)
                                clk->rate = clk->ops->recalc(clk);
+                       pr_debug("set parent of %p to %p (new rate %ld)\n",
+                                clk, clk->parent, clk->rate);
                        propagate_rate(clk);
                }
        } else
@@ -469,9 +620,7 @@ static int clk_debugfs_register_one(struct clk *c)
        char s[255];
        char *p = s;
 
-       p += sprintf(p, "%s", c->name);
-       if (c->id >= 0)
-               sprintf(p, ":%d", c->id);
+       p += sprintf(p, "%p", c);
        d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
        if (!d)
                return -ENOMEM;
@@ -513,7 +662,7 @@ static int clk_debugfs_register(struct clk *c)
                        return err;
        }
 
-       if (!c->dentry && c->name) {
+       if (!c->dentry) {
                err = clk_debugfs_register_one(c);
                if (err)
                        return err;
similarity index 96%
rename from drivers/sh/clk-cpg.c
rename to drivers/sh/clk/cpg.c
index 8c024b9..3aea5f0 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
+ *
+ *  Copyright (C) 2010  Magnus Damm
+ *
+ * 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 <linux/clk.h>
 #include <linux/compiler.h>
 #include <linux/slab.h>
@@ -180,7 +189,6 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
                clkp = clks + k;
 
                clkp->ops = ops;
-               clkp->id = -1;
                clkp->freq_table = freq_table + (k * freq_table_size);
                clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
 
@@ -319,7 +327,6 @@ static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
                clkp = clks + k;
 
                clkp->ops = ops;
-               clkp->id = -1;
                clkp->priv = table;
 
                clkp->freq_table = freq_table + (k * freq_table_size);
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
deleted file mode 100644 (file)
index e91a23e..0000000
+++ /dev/null
@@ -1,1390 +0,0 @@
-/*
- * Shared interrupt handling code for IPR and INTC2 types of IRQs.
- *
- * Copyright (C) 2007, 2008 Magnus Damm
- * Copyright (C) 2009, 2010 Paul Mundt
- *
- * Based on intc2.c and ipr.c
- *
- * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
- * Copyright (C) 2000  Kazumoto Kojima
- * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
- * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * Copyright (C) 2005, 2006  Paul Mundt
- *
- * 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.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/sh_intc.h>
-#include <linux/sysdev.h>
-#include <linux/list.h>
-#include <linux/topology.h>
-#include <linux/bitmap.h>
-#include <linux/cpumask.h>
-#include <asm/sizes.h>
-
-#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
-       ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
-        ((addr_e) << 16) | ((addr_d << 24)))
-
-#define _INTC_SHIFT(h) (h & 0x1f)
-#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
-#define _INTC_FN(h) ((h >> 9) & 0xf)
-#define _INTC_MODE(h) ((h >> 13) & 0x7)
-#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
-#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
-
-struct intc_handle_int {
-       unsigned int irq;
-       unsigned long handle;
-};
-
-struct intc_window {
-       phys_addr_t phys;
-       void __iomem *virt;
-       unsigned long size;
-};
-
-struct intc_desc_int {
-       struct list_head list;
-       struct sys_device sysdev;
-       pm_message_t state;
-       unsigned long *reg;
-#ifdef CONFIG_SMP
-       unsigned long *smp;
-#endif
-       unsigned int nr_reg;
-       struct intc_handle_int *prio;
-       unsigned int nr_prio;
-       struct intc_handle_int *sense;
-       unsigned int nr_sense;
-       struct intc_window *window;
-       unsigned int nr_windows;
-       struct irq_chip chip;
-};
-
-static LIST_HEAD(intc_list);
-
-/*
- * The intc_irq_map provides a global map of bound IRQ vectors for a
- * given platform. Allocation of IRQs are either static through the CPU
- * vector map, or dynamic in the case of board mux vectors or MSI.
- *
- * As this is a central point for all IRQ controllers on the system,
- * each of the available sources are mapped out here. This combined with
- * sparseirq makes it quite trivial to keep the vector map tightly packed
- * when dynamically creating IRQs, as well as tying in to otherwise
- * unused irq_desc positions in the sparse array.
- */
-static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
-static DEFINE_SPINLOCK(vector_lock);
-
-#ifdef CONFIG_SMP
-#define IS_SMP(x) x.smp
-#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
-#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
-#else
-#define IS_SMP(x) 0
-#define INTC_REG(d, x, c) (d->reg[(x)])
-#define SMP_NR(d, x) 1
-#endif
-
-static unsigned int intc_prio_level[NR_IRQS];  /* for now */
-static unsigned int default_prio_level = 2;    /* 2 - 16 */
-static unsigned long ack_handle[NR_IRQS];
-#ifdef CONFIG_INTC_BALANCING
-static unsigned long dist_handle[NR_IRQS];
-#endif
-
-static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
-{
-       struct irq_chip *chip = get_irq_chip(irq);
-       return container_of(chip, struct intc_desc_int, chip);
-}
-
-static unsigned long intc_phys_to_virt(struct intc_desc_int *d,
-                                      unsigned long address)
-{
-       struct intc_window *window;
-       int k;
-
-       /* scan through physical windows and convert address */
-       for (k = 0; k < d->nr_windows; k++) {
-               window = d->window + k;
-
-               if (address < window->phys)
-                       continue;
-
-               if (address >= (window->phys + window->size))
-                       continue;
-
-               address -= window->phys;
-               address += (unsigned long)window->virt;
-
-               return address;
-       }
-
-       /* no windows defined, register must be 1:1 mapped virt:phys */
-       return address;
-}
-
-static unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address)
-{
-       unsigned int k;
-
-       address = intc_phys_to_virt(d, address);
-
-       for (k = 0; k < d->nr_reg; k++) {
-               if (d->reg[k] == address)
-                       return k;
-       }
-
-       BUG();
-       return 0;
-}
-
-static inline unsigned int set_field(unsigned int value,
-                                    unsigned int field_value,
-                                    unsigned int handle)
-{
-       unsigned int width = _INTC_WIDTH(handle);
-       unsigned int shift = _INTC_SHIFT(handle);
-
-       value &= ~(((1 << width) - 1) << shift);
-       value |= field_value << shift;
-       return value;
-}
-
-static void write_8(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writeb(set_field(0, data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
-}
-
-static void write_16(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writew(set_field(0, data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
-}
-
-static void write_32(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writel(set_field(0, data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
-}
-
-static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writew(set_field(__raw_readw(addr), data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writel(set_field(__raw_readl(addr), data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };
-
-static void (*intc_reg_fns[])(unsigned long addr,
-                             unsigned long h,
-                             unsigned long data) = {
-       [REG_FN_WRITE_BASE + 0] = write_8,
-       [REG_FN_WRITE_BASE + 1] = write_16,
-       [REG_FN_WRITE_BASE + 3] = write_32,
-       [REG_FN_MODIFY_BASE + 0] = modify_8,
-       [REG_FN_MODIFY_BASE + 1] = modify_16,
-       [REG_FN_MODIFY_BASE + 3] = modify_32,
-};
-
-enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
-       MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
-       MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
-       MODE_PRIO_REG,       /* Priority value written to enable interrupt */
-       MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
-};
-
-static void intc_mode_field(unsigned long addr,
-                           unsigned long handle,
-                           void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                           unsigned int irq)
-{
-       fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
-}
-
-static void intc_mode_zero(unsigned long addr,
-                          unsigned long handle,
-                          void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                          unsigned int irq)
-{
-       fn(addr, handle, 0);
-}
-
-static void intc_mode_prio(unsigned long addr,
-                          unsigned long handle,
-                          void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                          unsigned int irq)
-{
-       fn(addr, handle, intc_prio_level[irq]);
-}
-
-static void (*intc_enable_fns[])(unsigned long addr,
-                                unsigned long handle,
-                                void (*fn)(unsigned long,
-                                           unsigned long,
-                                           unsigned long),
-                                unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_field,
-       [MODE_MASK_REG] = intc_mode_zero,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_prio,
-       [MODE_PCLR_REG] = intc_mode_prio,
-};
-
-static void (*intc_disable_fns[])(unsigned long addr,
-                                 unsigned long handle,
-                                 void (*fn)(unsigned long,
-                                            unsigned long,
-                                            unsigned long),
-                                 unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_zero,
-       [MODE_MASK_REG] = intc_mode_field,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_zero,
-       [MODE_PCLR_REG] = intc_mode_field,
-};
-
-#ifdef CONFIG_INTC_BALANCING
-static inline void intc_balancing_enable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = dist_handle[irq];
-       unsigned long addr;
-
-       if (irq_balancing_disabled(irq) || !handle)
-               return;
-
-       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-       intc_reg_fns[_INTC_FN(handle)](addr, handle, 1);
-}
-
-static inline void intc_balancing_disable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = dist_handle[irq];
-       unsigned long addr;
-
-       if (irq_balancing_disabled(irq) || !handle)
-               return;
-
-       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-       intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
-}
-
-static unsigned int intc_dist_data(struct intc_desc *desc,
-                                  struct intc_desc_int *d,
-                                  intc_enum enum_id)
-{
-       struct intc_mask_reg *mr = desc->hw.mask_regs;
-       unsigned int i, j, fn, mode;
-       unsigned long reg_e, reg_d;
-
-       for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) {
-               mr = desc->hw.mask_regs + i;
-
-               /*
-                * Skip this entry if there's no auto-distribution
-                * register associated with it.
-                */
-               if (!mr->dist_reg)
-                       continue;
-
-               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
-                       if (mr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       mode = MODE_ENABLE_REG;
-                       reg_e = mr->dist_reg;
-                       reg_d = mr->dist_reg;
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - j);
-               }
-       }
-
-       /*
-        * It's possible we've gotten here with no distribution options
-        * available for the IRQ in question, so we just skip over those.
-        */
-       return 0;
-}
-#else
-static inline void intc_balancing_enable(unsigned int irq)
-{
-}
-
-static inline void intc_balancing_disable(unsigned int irq)
-{
-}
-#endif
-
-static inline void _intc_enable(unsigned int irq, unsigned long handle)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long addr;
-       unsigned int cpu;
-
-       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
-#ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
-                       continue;
-#endif
-               addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
-               intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
-                                                   [_INTC_FN(handle)], irq);
-       }
-
-       intc_balancing_enable(irq);
-}
-
-static void intc_enable(unsigned int irq)
-{
-       _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
-}
-
-static void intc_disable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = (unsigned long)get_irq_chip_data(irq);
-       unsigned long addr;
-       unsigned int cpu;
-
-       intc_balancing_disable(irq);
-
-       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
-#ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
-                       continue;
-#endif
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
-               intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
-                                                    [_INTC_FN(handle)], irq);
-       }
-}
-
-static void (*intc_enable_noprio_fns[])(unsigned long addr,
-                                       unsigned long handle,
-                                       void (*fn)(unsigned long,
-                                                  unsigned long,
-                                                  unsigned long),
-                                       unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_field,
-       [MODE_MASK_REG] = intc_mode_zero,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_field,
-       [MODE_PCLR_REG] = intc_mode_field,
-};
-
-static void intc_enable_disable(struct intc_desc_int *d,
-                               unsigned long handle, int do_enable)
-{
-       unsigned long addr;
-       unsigned int cpu;
-       void (*fn)(unsigned long, unsigned long,
-                  void (*)(unsigned long, unsigned long, unsigned long),
-                  unsigned int);
-
-       if (do_enable) {
-               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
-                       addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
-                       fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
-                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
-               }
-       } else {
-               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
-                       addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
-                       fn = intc_disable_fns[_INTC_MODE(handle)];
-                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
-               }
-       }
-}
-
-static int intc_set_wake(unsigned int irq, unsigned int on)
-{
-       return 0; /* allow wakeup, but setup hardware in intc_suspend() */
-}
-
-#ifdef CONFIG_SMP
-/*
- * This is held with the irq desc lock held, so we don't require any
- * additional locking here at the intc desc level. The affinity mask is
- * later tested in the enable/disable paths.
- */
-static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
-{
-       if (!cpumask_intersects(cpumask, cpu_online_mask))
-               return -1;
-
-       cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
-
-       return 0;
-}
-#endif
-
-static void intc_mask_ack(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = ack_handle[irq];
-       unsigned long addr;
-
-       intc_disable(irq);
-
-       /* read register and write zero only to the associated bit */
-       if (handle) {
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-               switch (_INTC_FN(handle)) {
-               case REG_FN_MODIFY_BASE + 0:    /* 8bit */
-                       __raw_readb(addr);
-                       __raw_writeb(0xff ^ set_field(0, 1, handle), addr);
-                       break;
-               case REG_FN_MODIFY_BASE + 1:    /* 16bit */
-                       __raw_readw(addr);
-                       __raw_writew(0xffff ^ set_field(0, 1, handle), addr);
-                       break;
-               case REG_FN_MODIFY_BASE + 3:    /* 32bit */
-                       __raw_readl(addr);
-                       __raw_writel(0xffffffff ^ set_field(0, 1, handle), addr);
-                       break;
-               default:
-                       BUG();
-                       break;
-               }
-       }
-}
-
-static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
-                                            unsigned int nr_hp,
-                                            unsigned int irq)
-{
-       int i;
-
-       /*
-        * this doesn't scale well, but...
-        *
-        * this function should only be used for cerain uncommon
-        * operations such as intc_set_priority() and intc_set_sense()
-        * and in those rare cases performance doesn't matter that much.
-        * keeping the memory footprint low is more important.
-        *
-        * one rather simple way to speed this up and still keep the
-        * memory footprint down is to make sure the array is sorted
-        * and then perform a bisect to lookup the irq.
-        */
-       for (i = 0; i < nr_hp; i++) {
-               if ((hp + i)->irq != irq)
-                       continue;
-
-               return hp + i;
-       }
-
-       return NULL;
-}
-
-int intc_set_priority(unsigned int irq, unsigned int prio)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       struct intc_handle_int *ihp;
-
-       if (!intc_prio_level[irq] || prio <= 1)
-               return -EINVAL;
-
-       ihp = intc_find_irq(d->prio, d->nr_prio, irq);
-       if (ihp) {
-               if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
-                       return -EINVAL;
-
-               intc_prio_level[irq] = prio;
-
-               /*
-                * only set secondary masking method directly
-                * primary masking method is using intc_prio_level[irq]
-                * priority level will be set during next enable()
-                */
-               if (_INTC_FN(ihp->handle) != REG_FN_ERR)
-                       _intc_enable(irq, ihp->handle);
-       }
-       return 0;
-}
-
-#define VALID(x) (x | 0x80)
-
-static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
-       [IRQ_TYPE_EDGE_FALLING] = VALID(0),
-       [IRQ_TYPE_EDGE_RISING] = VALID(1),
-       [IRQ_TYPE_LEVEL_LOW] = VALID(2),
-       /* SH7706, SH7707 and SH7709 do not support high level triggered */
-#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7709)
-       [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
-#endif
-};
-
-static int intc_set_sense(unsigned int irq, unsigned int type)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
-       struct intc_handle_int *ihp;
-       unsigned long addr;
-
-       if (!value)
-               return -EINVAL;
-
-       ihp = intc_find_irq(d->sense, d->nr_sense, irq);
-       if (ihp) {
-               addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
-               intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
-       }
-       return 0;
-}
-
-static intc_enum __init intc_grp_id(struct intc_desc *desc,
-                                   intc_enum enum_id)
-{
-       struct intc_group *g = desc->hw.groups;
-       unsigned int i, j;
-
-       for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) {
-               g = desc->hw.groups + i;
-
-               for (j = 0; g->enum_ids[j]; j++) {
-                       if (g->enum_ids[j] != enum_id)
-                               continue;
-
-                       return g->enum_id;
-               }
-       }
-
-       return 0;
-}
-
-static unsigned int __init _intc_mask_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id,
-                                          unsigned int *reg_idx,
-                                          unsigned int *fld_idx)
-{
-       struct intc_mask_reg *mr = desc->hw.mask_regs;
-       unsigned int fn, mode;
-       unsigned long reg_e, reg_d;
-
-       while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) {
-               mr = desc->hw.mask_regs + *reg_idx;
-
-               for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) {
-                       if (mr->enum_ids[*fld_idx] != enum_id)
-                               continue;
-
-                       if (mr->set_reg && mr->clr_reg) {
-                               fn = REG_FN_WRITE_BASE;
-                               mode = MODE_DUAL_REG;
-                               reg_e = mr->clr_reg;
-                               reg_d = mr->set_reg;
-                       } else {
-                               fn = REG_FN_MODIFY_BASE;
-                               if (mr->set_reg) {
-                                       mode = MODE_ENABLE_REG;
-                                       reg_e = mr->set_reg;
-                                       reg_d = mr->set_reg;
-                               } else {
-                                       mode = MODE_MASK_REG;
-                                       reg_e = mr->clr_reg;
-                                       reg_d = mr->clr_reg;
-                               }
-                       }
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - *fld_idx);
-               }
-
-               *fld_idx = 0;
-               (*reg_idx)++;
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_mask_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id, int do_grps)
-{
-       unsigned int i = 0;
-       unsigned int j = 0;
-       unsigned int ret;
-
-       ret = _intc_mask_data(desc, d, enum_id, &i, &j);
-       if (ret)
-               return ret;
-
-       if (do_grps)
-               return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
-       return 0;
-}
-
-static unsigned int __init _intc_prio_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id,
-                                          unsigned int *reg_idx,
-                                          unsigned int *fld_idx)
-{
-       struct intc_prio_reg *pr = desc->hw.prio_regs;
-       unsigned int fn, n, mode, bit;
-       unsigned long reg_e, reg_d;
-
-       while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) {
-               pr = desc->hw.prio_regs + *reg_idx;
-
-               for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) {
-                       if (pr->enum_ids[*fld_idx] != enum_id)
-                               continue;
-
-                       if (pr->set_reg && pr->clr_reg) {
-                               fn = REG_FN_WRITE_BASE;
-                               mode = MODE_PCLR_REG;
-                               reg_e = pr->set_reg;
-                               reg_d = pr->clr_reg;
-                       } else {
-                               fn = REG_FN_MODIFY_BASE;
-                               mode = MODE_PRIO_REG;
-                               if (!pr->set_reg)
-                                       BUG();
-                               reg_e = pr->set_reg;
-                               reg_d = pr->set_reg;
-                       }
-
-                       fn += (pr->reg_width >> 3) - 1;
-                       n = *fld_idx + 1;
-
-                       BUG_ON(n * pr->field_width > pr->reg_width);
-
-                       bit = pr->reg_width - (n * pr->field_width);
-
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       pr->field_width, bit);
-               }
-
-               *fld_idx = 0;
-               (*reg_idx)++;
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_prio_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id, int do_grps)
-{
-       unsigned int i = 0;
-       unsigned int j = 0;
-       unsigned int ret;
-
-       ret = _intc_prio_data(desc, d, enum_id, &i, &j);
-       if (ret)
-               return ret;
-
-       if (do_grps)
-               return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
-       return 0;
-}
-
-static void __init intc_enable_disable_enum(struct intc_desc *desc,
-                                           struct intc_desc_int *d,
-                                           intc_enum enum_id, int enable)
-{
-       unsigned int i, j, data;
-
-       /* go through and enable/disable all mask bits */
-       i = j = 0;
-       do {
-               data = _intc_mask_data(desc, d, enum_id, &i, &j);
-               if (data)
-                       intc_enable_disable(d, data, enable);
-               j++;
-       } while (data);
-
-       /* go through and enable/disable all priority fields */
-       i = j = 0;
-       do {
-               data = _intc_prio_data(desc, d, enum_id, &i, &j);
-               if (data)
-                       intc_enable_disable(d, data, enable);
-
-               j++;
-       } while (data);
-}
-
-static unsigned int __init intc_ack_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id)
-{
-       struct intc_mask_reg *mr = desc->hw.ack_regs;
-       unsigned int i, j, fn, mode;
-       unsigned long reg_e, reg_d;
-
-       for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) {
-               mr = desc->hw.ack_regs + i;
-
-               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
-                       if (mr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       mode = MODE_ENABLE_REG;
-                       reg_e = mr->set_reg;
-                       reg_d = mr->set_reg;
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - j);
-               }
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_sense_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id)
-{
-       struct intc_sense_reg *sr = desc->hw.sense_regs;
-       unsigned int i, j, fn, bit;
-
-       for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) {
-               sr = desc->hw.sense_regs + i;
-
-               for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
-                       if (sr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       fn += (sr->reg_width >> 3) - 1;
-
-                       BUG_ON((j + 1) * sr->field_width > sr->reg_width);
-
-                       bit = sr->reg_width - ((j + 1) * sr->field_width);
-
-                       return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
-                                       0, sr->field_width, bit);
-               }
-       }
-
-       return 0;
-}
-
-static void __init intc_register_irq(struct intc_desc *desc,
-                                    struct intc_desc_int *d,
-                                    intc_enum enum_id,
-                                    unsigned int irq)
-{
-       struct intc_handle_int *hp;
-       unsigned int data[2], primary;
-
-       /*
-        * Register the IRQ position with the global IRQ map
-        */
-       set_bit(irq, intc_irq_map);
-
-       /*
-        * Prefer single interrupt source bitmap over other combinations:
-        *
-        * 1. bitmap, single interrupt source
-        * 2. priority, single interrupt source
-        * 3. bitmap, multiple interrupt sources (groups)
-        * 4. priority, multiple interrupt sources (groups)
-        */
-       data[0] = intc_mask_data(desc, d, enum_id, 0);
-       data[1] = intc_prio_data(desc, d, enum_id, 0);
-
-       primary = 0;
-       if (!data[0] && data[1])
-               primary = 1;
-
-       if (!data[0] && !data[1])
-               pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
-                          irq, irq2evt(irq));
-
-       data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
-       data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
-
-       if (!data[primary])
-               primary ^= 1;
-
-       BUG_ON(!data[primary]); /* must have primary masking method */
-
-       disable_irq_nosync(irq);
-       set_irq_chip_and_handler_name(irq, &d->chip,
-                                     handle_level_irq, "level");
-       set_irq_chip_data(irq, (void *)data[primary]);
-
-       /*
-        * set priority level
-        * - this needs to be at least 2 for 5-bit priorities on 7780
-        */
-       intc_prio_level[irq] = default_prio_level;
-
-       /* enable secondary masking method if present */
-       if (data[!primary])
-               _intc_enable(irq, data[!primary]);
-
-       /* add irq to d->prio list if priority is available */
-       if (data[1]) {
-               hp = d->prio + d->nr_prio;
-               hp->irq = irq;
-               hp->handle = data[1];
-
-               if (primary) {
-                       /*
-                        * only secondary priority should access registers, so
-                        * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
-                        */
-                       hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
-                       hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
-               }
-               d->nr_prio++;
-       }
-
-       /* add irq to d->sense list if sense is available */
-       data[0] = intc_sense_data(desc, d, enum_id);
-       if (data[0]) {
-               (d->sense + d->nr_sense)->irq = irq;
-               (d->sense + d->nr_sense)->handle = data[0];
-               d->nr_sense++;
-       }
-
-       /* irq should be disabled by default */
-       d->chip.mask(irq);
-
-       if (desc->hw.ack_regs)
-               ack_handle[irq] = intc_ack_data(desc, d, enum_id);
-
-#ifdef CONFIG_INTC_BALANCING
-       if (desc->hw.mask_regs)
-               dist_handle[irq] = intc_dist_data(desc, d, enum_id);
-#endif
-
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
-#endif
-}
-
-static unsigned int __init save_reg(struct intc_desc_int *d,
-                                   unsigned int cnt,
-                                   unsigned long value,
-                                   unsigned int smp)
-{
-       if (value) {
-               value = intc_phys_to_virt(d, value);
-
-               d->reg[cnt] = value;
-#ifdef CONFIG_SMP
-               d->smp[cnt] = smp;
-#endif
-               return 1;
-       }
-
-       return 0;
-}
-
-static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
-{
-       generic_handle_irq((unsigned int)get_irq_data(irq));
-}
-
-int __init register_intc_controller(struct intc_desc *desc)
-{
-       unsigned int i, k, smp;
-       struct intc_hw_desc *hw = &desc->hw;
-       struct intc_desc_int *d;
-       struct resource *res;
-
-       pr_info("Registered controller '%s' with %u IRQs\n",
-               desc->name, hw->nr_vectors);
-
-       d = kzalloc(sizeof(*d), GFP_NOWAIT);
-       if (!d)
-               goto err0;
-
-       INIT_LIST_HEAD(&d->list);
-       list_add(&d->list, &intc_list);
-
-       if (desc->num_resources) {
-               d->nr_windows = desc->num_resources;
-               d->window = kzalloc(d->nr_windows * sizeof(*d->window),
-                                   GFP_NOWAIT);
-               if (!d->window)
-                       goto err1;
-
-               for (k = 0; k < d->nr_windows; k++) {
-                       res = desc->resource + k;
-                       WARN_ON(resource_type(res) != IORESOURCE_MEM);
-                       d->window[k].phys = res->start;
-                       d->window[k].size = resource_size(res);
-                       d->window[k].virt = ioremap_nocache(res->start,
-                                                        resource_size(res));
-                       if (!d->window[k].virt)
-                               goto err2;
-               }
-       }
-
-       d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
-#ifdef CONFIG_INTC_BALANCING
-       if (d->nr_reg)
-               d->nr_reg += hw->nr_mask_regs;
-#endif
-       d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
-       d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
-       d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
-
-       d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
-       if (!d->reg)
-               goto err2;
-
-#ifdef CONFIG_SMP
-       d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
-       if (!d->smp)
-               goto err3;
-#endif
-       k = 0;
-
-       if (hw->mask_regs) {
-               for (i = 0; i < hw->nr_mask_regs; i++) {
-                       smp = IS_SMP(hw->mask_regs[i]);
-                       k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
-                       k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp);
-#ifdef CONFIG_INTC_BALANCING
-                       k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0);
-#endif
-               }
-       }
-
-       if (hw->prio_regs) {
-               d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
-                                 GFP_NOWAIT);
-               if (!d->prio)
-                       goto err4;
-
-               for (i = 0; i < hw->nr_prio_regs; i++) {
-                       smp = IS_SMP(hw->prio_regs[i]);
-                       k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
-                       k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
-               }
-       }
-
-       if (hw->sense_regs) {
-               d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
-                                  GFP_NOWAIT);
-               if (!d->sense)
-                       goto err5;
-
-               for (i = 0; i < hw->nr_sense_regs; i++)
-                       k += save_reg(d, k, hw->sense_regs[i].reg, 0);
-       }
-
-       d->chip.name = desc->name;
-       d->chip.mask = intc_disable;
-       d->chip.unmask = intc_enable;
-       d->chip.mask_ack = intc_disable;
-       d->chip.enable = intc_enable;
-       d->chip.disable = intc_disable;
-       d->chip.shutdown = intc_disable;
-       d->chip.set_type = intc_set_sense;
-       d->chip.set_wake = intc_set_wake;
-#ifdef CONFIG_SMP
-       d->chip.set_affinity = intc_set_affinity;
-#endif
-
-       if (hw->ack_regs) {
-               for (i = 0; i < hw->nr_ack_regs; i++)
-                       k += save_reg(d, k, hw->ack_regs[i].set_reg, 0);
-
-               d->chip.mask_ack = intc_mask_ack;
-       }
-
-       /* disable bits matching force_disable before registering irqs */
-       if (desc->force_disable)
-               intc_enable_disable_enum(desc, d, desc->force_disable, 0);
-
-       /* disable bits matching force_enable before registering irqs */
-       if (desc->force_enable)
-               intc_enable_disable_enum(desc, d, desc->force_enable, 0);
-
-       BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
-
-       /* register the vectors one by one */
-       for (i = 0; i < hw->nr_vectors; i++) {
-               struct intc_vect *vect = hw->vectors + i;
-               unsigned int irq = evt2irq(vect->vect);
-               struct irq_desc *irq_desc;
-
-               if (!vect->enum_id)
-                       continue;
-
-               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
-               if (unlikely(!irq_desc)) {
-                       pr_err("can't get irq_desc for %d\n", irq);
-                       continue;
-               }
-
-               intc_register_irq(desc, d, vect->enum_id, irq);
-
-               for (k = i + 1; k < hw->nr_vectors; k++) {
-                       struct intc_vect *vect2 = hw->vectors + k;
-                       unsigned int irq2 = evt2irq(vect2->vect);
-
-                       if (vect->enum_id != vect2->enum_id)
-                               continue;
-
-                       /*
-                        * In the case of multi-evt handling and sparse
-                        * IRQ support, each vector still needs to have
-                        * its own backing irq_desc.
-                        */
-                       irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
-                       if (unlikely(!irq_desc)) {
-                               pr_err("can't get irq_desc for %d\n", irq2);
-                               continue;
-                       }
-
-                       vect2->enum_id = 0;
-
-                       /* redirect this interrupts to the first one */
-                       set_irq_chip(irq2, &dummy_irq_chip);
-                       set_irq_chained_handler(irq2, intc_redirect_irq);
-                       set_irq_data(irq2, (void *)irq);
-               }
-       }
-
-       /* enable bits matching force_enable after registering irqs */
-       if (desc->force_enable)
-               intc_enable_disable_enum(desc, d, desc->force_enable, 1);
-
-       return 0;
-err5:
-       kfree(d->prio);
-err4:
-#ifdef CONFIG_SMP
-       kfree(d->smp);
-err3:
-#endif
-       kfree(d->reg);
-err2:
-       for (k = 0; k < d->nr_windows; k++)
-               if (d->window[k].virt)
-                       iounmap(d->window[k].virt);
-
-       kfree(d->window);
-err1:
-       kfree(d);
-err0:
-       pr_err("unable to allocate INTC memory\n");
-
-       return -ENOMEM;
-}
-
-#ifdef CONFIG_INTC_USERIMASK
-static void __iomem *uimask;
-
-int register_intc_userimask(unsigned long addr)
-{
-       if (unlikely(uimask))
-               return -EBUSY;
-
-       uimask = ioremap_nocache(addr, SZ_4K);
-       if (unlikely(!uimask))
-               return -ENOMEM;
-
-       pr_info("userimask support registered for levels 0 -> %d\n",
-               default_prio_level - 1);
-
-       return 0;
-}
-
-static ssize_t
-show_intc_userimask(struct sysdev_class *cls,
-                   struct sysdev_class_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf);
-}
-
-static ssize_t
-store_intc_userimask(struct sysdev_class *cls,
-                    struct sysdev_class_attribute *attr,
-                    const char *buf, size_t count)
-{
-       unsigned long level;
-
-       level = simple_strtoul(buf, NULL, 10);
-
-       /*
-        * Minimal acceptable IRQ levels are in the 2 - 16 range, but
-        * these are chomped so as to not interfere with normal IRQs.
-        *
-        * Level 1 is a special case on some CPUs in that it's not
-        * directly settable, but given that USERIMASK cuts off below a
-        * certain level, we don't care about this limitation here.
-        * Level 0 on the other hand equates to user masking disabled.
-        *
-        * We use default_prio_level as a cut off so that only special
-        * case opt-in IRQs can be mangled.
-        */
-       if (level >= default_prio_level)
-               return -EINVAL;
-
-       __raw_writel(0xa5 << 24 | level << 4, uimask);
-
-       return count;
-}
-
-static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR,
-                        show_intc_userimask, store_intc_userimask);
-#endif
-
-static ssize_t
-show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
-{
-       struct intc_desc_int *d;
-
-       d = container_of(dev, struct intc_desc_int, sysdev);
-
-       return sprintf(buf, "%s\n", d->chip.name);
-}
-
-static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
-
-static int intc_suspend(struct sys_device *dev, pm_message_t state)
-{
-       struct intc_desc_int *d;
-       struct irq_desc *desc;
-       int irq;
-
-       /* get intc controller associated with this sysdev */
-       d = container_of(dev, struct intc_desc_int, sysdev);
-
-       switch (state.event) {
-       case PM_EVENT_ON:
-               if (d->state.event != PM_EVENT_FREEZE)
-                       break;
-               for_each_irq_desc(irq, desc) {
-                       if (desc->handle_irq == intc_redirect_irq)
-                               continue;
-                       if (desc->chip != &d->chip)
-                               continue;
-                       if (desc->status & IRQ_DISABLED)
-                               intc_disable(irq);
-                       else
-                               intc_enable(irq);
-               }
-               break;
-       case PM_EVENT_FREEZE:
-               /* nothing has to be done */
-               break;
-       case PM_EVENT_SUSPEND:
-               /* enable wakeup irqs belonging to this intc controller */
-               for_each_irq_desc(irq, desc) {
-                       if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
-                               intc_enable(irq);
-               }
-               break;
-       }
-       d->state = state;
-
-       return 0;
-}
-
-static int intc_resume(struct sys_device *dev)
-{
-       return intc_suspend(dev, PMSG_ON);
-}
-
-static struct sysdev_class intc_sysdev_class = {
-       .name = "intc",
-       .suspend = intc_suspend,
-       .resume = intc_resume,
-};
-
-/* register this intc as sysdev to allow suspend/resume */
-static int __init register_intc_sysdevs(void)
-{
-       struct intc_desc_int *d;
-       int error;
-       int id = 0;
-
-       error = sysdev_class_register(&intc_sysdev_class);
-#ifdef CONFIG_INTC_USERIMASK
-       if (!error && uimask)
-               error = sysdev_class_create_file(&intc_sysdev_class,
-                                                &attr_userimask);
-#endif
-       if (!error) {
-               list_for_each_entry(d, &intc_list, list) {
-                       d->sysdev.id = id;
-                       d->sysdev.cls = &intc_sysdev_class;
-                       error = sysdev_register(&d->sysdev);
-                       if (error == 0)
-                               error = sysdev_create_file(&d->sysdev,
-                                                          &attr_name);
-                       if (error)
-                               break;
-
-                       id++;
-               }
-       }
-
-       if (error)
-               pr_err("sysdev registration error\n");
-
-       return error;
-}
-device_initcall(register_intc_sysdevs);
-
-/*
- * Dynamic IRQ allocation and deallocation
- */
-unsigned int create_irq_nr(unsigned int irq_want, int node)
-{
-       unsigned int irq = 0, new;
-       unsigned long flags;
-       struct irq_desc *desc;
-
-       spin_lock_irqsave(&vector_lock, flags);
-
-       /*
-        * First try the wanted IRQ
-        */
-       if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
-               new = irq_want;
-       } else {
-               /* .. then fall back to scanning. */
-               new = find_first_zero_bit(intc_irq_map, nr_irqs);
-               if (unlikely(new == nr_irqs))
-                       goto out_unlock;
-
-               __set_bit(new, intc_irq_map);
-       }
-
-       desc = irq_to_desc_alloc_node(new, node);
-       if (unlikely(!desc)) {
-               pr_err("can't get irq_desc for %d\n", new);
-               goto out_unlock;
-       }
-
-       desc = move_irq_desc(desc, node);
-       irq = new;
-
-out_unlock:
-       spin_unlock_irqrestore(&vector_lock, flags);
-
-       if (irq > 0) {
-               dynamic_irq_init(irq);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
-#endif
-       }
-
-       return irq;
-}
-
-int create_irq(void)
-{
-       int nid = cpu_to_node(smp_processor_id());
-       int irq;
-
-       irq = create_irq_nr(NR_IRQS_LEGACY, nid);
-       if (irq == 0)
-               irq = -1;
-
-       return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
-       unsigned long flags;
-
-       dynamic_irq_cleanup(irq);
-
-       spin_lock_irqsave(&vector_lock, flags);
-       __clear_bit(irq, intc_irq_map);
-       spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-int reserve_irq_vector(unsigned int irq)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&vector_lock, flags);
-       if (test_and_set_bit(irq, intc_irq_map))
-               ret = -EBUSY;
-       spin_unlock_irqrestore(&vector_lock, flags);
-
-       return ret;
-}
-
-void reserve_irq_legacy(void)
-{
-       unsigned long flags;
-       int i, j;
-
-       spin_lock_irqsave(&vector_lock, flags);
-       j = find_first_bit(intc_irq_map, nr_irqs);
-       for (i = 0; i < j; i++)
-               __set_bit(i, intc_irq_map);
-       spin_unlock_irqrestore(&vector_lock, flags);
-}
diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
new file mode 100644 (file)
index 0000000..c88cbcc
--- /dev/null
@@ -0,0 +1,35 @@
+comment "Interrupt controller options"
+
+config INTC_USERIMASK
+       bool "Userspace interrupt masking support"
+       depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A)
+       help
+         This enables support for hardware-assisted userspace hardirq
+         masking.
+
+         SH-4A and newer interrupt blocks all support a special shadowed
+         page with all non-masking registers obscured when mapped in to
+         userspace. This is primarily for use by userspace device
+         drivers that are using special priority levels.
+
+         If in doubt, say N.
+
+config INTC_BALANCING
+       bool "Hardware IRQ balancing support"
+       depends on SMP && SUPERH && CPU_SHX3
+       help
+         This enables support for IRQ auto-distribution mode on SH-X3
+         SMP parts. All of the balancing and CPU wakeup decisions are
+         taken care of automatically by hardware for distributed
+         vectors.
+
+         If in doubt, say N.
+
+config INTC_MAPPING_DEBUG
+       bool "Expose IRQ to per-controller id mapping via debugfs"
+       depends on DEBUG_FS
+       help
+         This will create a debugfs entry for showing the relationship
+         between system IRQs and the per-controller id tables.
+
+         If in doubt, say N.
diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile
new file mode 100644 (file)
index 0000000..bb5df86
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y  := access.o chip.o core.o dynamic.o handle.o virq.o
+
+obj-$(CONFIG_INTC_BALANCING)           += balancing.o
+obj-$(CONFIG_INTC_USERIMASK)           += userimask.o
+obj-$(CONFIG_INTC_MAPPING_DEBUG)       += virq-debugfs.o
diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c
new file mode 100644 (file)
index 0000000..f892ae1
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Common INTC2 register accessors
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * 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 <linux/io.h>
+#include "internals.h"
+
+unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address)
+{
+       struct intc_window *window;
+       int k;
+
+       /* scan through physical windows and convert address */
+       for (k = 0; k < d->nr_windows; k++) {
+               window = d->window + k;
+
+               if (address < window->phys)
+                       continue;
+
+               if (address >= (window->phys + window->size))
+                       continue;
+
+               address -= window->phys;
+               address += (unsigned long)window->virt;
+
+               return address;
+       }
+
+       /* no windows defined, register must be 1:1 mapped virt:phys */
+       return address;
+}
+
+unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address)
+{
+       unsigned int k;
+
+       address = intc_phys_to_virt(d, address);
+
+       for (k = 0; k < d->nr_reg; k++) {
+               if (d->reg[k] == address)
+                       return k;
+       }
+
+       BUG();
+       return 0;
+}
+
+unsigned int intc_set_field_from_handle(unsigned int value,
+                                       unsigned int field_value,
+                                       unsigned int handle)
+{
+       unsigned int width = _INTC_WIDTH(handle);
+       unsigned int shift = _INTC_SHIFT(handle);
+
+       value &= ~(((1 << width) - 1) << shift);
+       value |= field_value << shift;
+       return value;
+}
+
+unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle)
+{
+       unsigned int width = _INTC_WIDTH(handle);
+       unsigned int shift = _INTC_SHIFT(handle);
+       unsigned int mask = ((1 << width) - 1) << shift;
+
+       return (value & mask) >> shift;
+}
+
+static unsigned long test_8(unsigned long addr, unsigned long h,
+                           unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readb(addr), h);
+}
+
+static unsigned long test_16(unsigned long addr, unsigned long h,
+                            unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readw(addr), h);
+}
+
+static unsigned long test_32(unsigned long addr, unsigned long h,
+                            unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readl(addr), h);
+}
+
+static unsigned long write_8(unsigned long addr, unsigned long h,
+                            unsigned long data)
+{
+       __raw_writeb(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long write_16(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       __raw_writew(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long write_32(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       __raw_writel(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long modify_8(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readb(addr), data, h);
+       __raw_writeb(value, addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long modify_16(unsigned long addr, unsigned long h,
+                              unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readw(addr), data, h);
+       __raw_writew(value, addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long modify_32(unsigned long addr, unsigned long h,
+                              unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readl(addr), data, h);
+       __raw_writel(value, addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long intc_mode_field(unsigned long addr,
+                                    unsigned long handle,
+                                    unsigned long (*fn)(unsigned long,
+                                               unsigned long,
+                                               unsigned long),
+                                    unsigned int irq)
+{
+       return fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
+}
+
+static unsigned long intc_mode_zero(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                              unsigned long,
+                                              unsigned long),
+                                   unsigned int irq)
+{
+       return fn(addr, handle, 0);
+}
+
+static unsigned long intc_mode_prio(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                              unsigned long,
+                                              unsigned long),
+                                   unsigned int irq)
+{
+       return fn(addr, handle, intc_get_prio_level(irq));
+}
+
+unsigned long (*intc_reg_fns[])(unsigned long addr,
+                               unsigned long h,
+                               unsigned long data) = {
+       [REG_FN_TEST_BASE + 0] = test_8,
+       [REG_FN_TEST_BASE + 1] = test_16,
+       [REG_FN_TEST_BASE + 3] = test_32,
+       [REG_FN_WRITE_BASE + 0] = write_8,
+       [REG_FN_WRITE_BASE + 1] = write_16,
+       [REG_FN_WRITE_BASE + 3] = write_32,
+       [REG_FN_MODIFY_BASE + 0] = modify_8,
+       [REG_FN_MODIFY_BASE + 1] = modify_16,
+       [REG_FN_MODIFY_BASE + 3] = modify_32,
+};
+
+unsigned long (*intc_enable_fns[])(unsigned long addr,
+                                  unsigned long handle,
+                                  unsigned long (*fn)(unsigned long,
+                                           unsigned long,
+                                           unsigned long),
+                                  unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_field,
+       [MODE_MASK_REG] = intc_mode_zero,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_prio,
+       [MODE_PCLR_REG] = intc_mode_prio,
+};
+
+unsigned long (*intc_disable_fns[])(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                            unsigned long,
+                                            unsigned long),
+                                   unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_zero,
+       [MODE_MASK_REG] = intc_mode_field,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_zero,
+       [MODE_PCLR_REG] = intc_mode_field,
+};
+
+unsigned long (*intc_enable_noprio_fns[])(unsigned long addr,
+                                         unsigned long handle,
+                                         unsigned long (*fn)(unsigned long,
+                                               unsigned long,
+                                               unsigned long),
+                                         unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_field,
+       [MODE_MASK_REG] = intc_mode_zero,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_field,
+       [MODE_PCLR_REG] = intc_mode_field,
+};
diff --git a/drivers/sh/intc/balancing.c b/drivers/sh/intc/balancing.c
new file mode 100644 (file)
index 0000000..cec7a96
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Support for hardware-managed IRQ auto-distribution.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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 "internals.h"
+
+static unsigned long dist_handle[NR_IRQS];
+
+void intc_balancing_enable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = dist_handle[irq];
+       unsigned long addr;
+
+       if (irq_balancing_disabled(irq) || !handle)
+               return;
+
+       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+       intc_reg_fns[_INTC_FN(handle)](addr, handle, 1);
+}
+
+void intc_balancing_disable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = dist_handle[irq];
+       unsigned long addr;
+
+       if (irq_balancing_disabled(irq) || !handle)
+               return;
+
+       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+       intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
+}
+
+static unsigned int intc_dist_data(struct intc_desc *desc,
+                                  struct intc_desc_int *d,
+                                  intc_enum enum_id)
+{
+       struct intc_mask_reg *mr = desc->hw.mask_regs;
+       unsigned int i, j, fn, mode;
+       unsigned long reg_e, reg_d;
+
+       for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) {
+               mr = desc->hw.mask_regs + i;
+
+               /*
+                * Skip this entry if there's no auto-distribution
+                * register associated with it.
+                */
+               if (!mr->dist_reg)
+                       continue;
+
+               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+                       if (mr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       mode = MODE_ENABLE_REG;
+                       reg_e = mr->dist_reg;
+                       reg_d = mr->dist_reg;
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - j);
+               }
+       }
+
+       /*
+        * It's possible we've gotten here with no distribution options
+        * available for the IRQ in question, so we just skip over those.
+        */
+       return 0;
+}
+
+void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                         struct intc_desc_int *d, intc_enum id)
+{
+       unsigned long flags;
+
+       /*
+        * Nothing to do for this IRQ.
+        */
+       if (!desc->hw.mask_regs)
+               return;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       dist_handle[irq] = intc_dist_data(desc, d, id);
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c
new file mode 100644 (file)
index 0000000..35c0370
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * IRQ chip definitions for INTC IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * 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 <linux/cpumask.h>
+#include <linux/io.h>
+#include "internals.h"
+
+void _intc_enable(unsigned int irq, unsigned long handle)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long addr;
+       unsigned int cpu;
+
+       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+#ifdef CONFIG_SMP
+               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
+                       continue;
+#endif
+               addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+               intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
+                                                   [_INTC_FN(handle)], irq);
+       }
+
+       intc_balancing_enable(irq);
+}
+
+static void intc_enable(unsigned int irq)
+{
+       _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
+}
+
+static void intc_disable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = (unsigned long)get_irq_chip_data(irq);
+       unsigned long addr;
+       unsigned int cpu;
+
+       intc_balancing_disable(irq);
+
+       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+#ifdef CONFIG_SMP
+               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
+                       continue;
+#endif
+               addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+               intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
+                                                    [_INTC_FN(handle)], irq);
+       }
+}
+
+static int intc_set_wake(unsigned int irq, unsigned int on)
+{
+       return 0; /* allow wakeup, but setup hardware in intc_suspend() */
+}
+
+#ifdef CONFIG_SMP
+/*
+ * This is held with the irq desc lock held, so we don't require any
+ * additional locking here at the intc desc level. The affinity mask is
+ * later tested in the enable/disable paths.
+ */
+static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+       if (!cpumask_intersects(cpumask, cpu_online_mask))
+               return -1;
+
+       cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
+
+       return 0;
+}
+#endif
+
+static void intc_mask_ack(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = intc_get_ack_handle(irq);
+       unsigned long addr;
+
+       intc_disable(irq);
+
+       /* read register and write zero only to the associated bit */
+       if (handle) {
+               unsigned int value;
+
+               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+               value = intc_set_field_from_handle(0, 1, handle);
+
+               switch (_INTC_FN(handle)) {
+               case REG_FN_MODIFY_BASE + 0:    /* 8bit */
+                       __raw_readb(addr);
+                       __raw_writeb(0xff ^ value, addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 1:    /* 16bit */
+                       __raw_readw(addr);
+                       __raw_writew(0xffff ^ value, addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 3:    /* 32bit */
+                       __raw_readl(addr);
+                       __raw_writel(0xffffffff ^ value, addr);
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
+       }
+}
+
+static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
+                                            unsigned int nr_hp,
+                                            unsigned int irq)
+{
+       int i;
+
+       /*
+        * this doesn't scale well, but...
+        *
+        * this function should only be used for cerain uncommon
+        * operations such as intc_set_priority() and intc_set_type()
+        * and in those rare cases performance doesn't matter that much.
+        * keeping the memory footprint low is more important.
+        *
+        * one rather simple way to speed this up and still keep the
+        * memory footprint down is to make sure the array is sorted
+        * and then perform a bisect to lookup the irq.
+        */
+       for (i = 0; i < nr_hp; i++) {
+               if ((hp + i)->irq != irq)
+                       continue;
+
+               return hp + i;
+       }
+
+       return NULL;
+}
+
+int intc_set_priority(unsigned int irq, unsigned int prio)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       struct intc_handle_int *ihp;
+
+       if (!intc_get_prio_level(irq) || prio <= 1)
+               return -EINVAL;
+
+       ihp = intc_find_irq(d->prio, d->nr_prio, irq);
+       if (ihp) {
+               if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
+                       return -EINVAL;
+
+               intc_set_prio_level(irq, prio);
+
+               /*
+                * only set secondary masking method directly
+                * primary masking method is using intc_prio_level[irq]
+                * priority level will be set during next enable()
+                */
+               if (_INTC_FN(ihp->handle) != REG_FN_ERR)
+                       _intc_enable(irq, ihp->handle);
+       }
+       return 0;
+}
+
+#define VALID(x) (x | 0x80)
+
+static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
+       [IRQ_TYPE_EDGE_FALLING] = VALID(0),
+       [IRQ_TYPE_EDGE_RISING] = VALID(1),
+       [IRQ_TYPE_LEVEL_LOW] = VALID(2),
+       /* SH7706, SH7707 and SH7709 do not support high level triggered */
+#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7709)
+       [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
+#endif
+};
+
+static int intc_set_type(unsigned int irq, unsigned int type)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
+       struct intc_handle_int *ihp;
+       unsigned long addr;
+
+       if (!value)
+               return -EINVAL;
+
+       ihp = intc_find_irq(d->sense, d->nr_sense, irq);
+       if (ihp) {
+               addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
+               intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
+       }
+
+       return 0;
+}
+
+struct irq_chip intc_irq_chip  = {
+       .mask           = intc_disable,
+       .unmask         = intc_enable,
+       .mask_ack       = intc_mask_ack,
+       .enable         = intc_enable,
+       .disable        = intc_disable,
+       .shutdown       = intc_disable,
+       .set_type       = intc_set_type,
+       .set_wake       = intc_set_wake,
+#ifdef CONFIG_SMP
+       .set_affinity   = intc_set_affinity,
+#endif
+};
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
new file mode 100644 (file)
index 0000000..306ed28
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * Based on intc2.c and ipr.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
+ * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 2005, 2006  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/sh_intc.h>
+#include <linux/sysdev.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/radix-tree.h>
+#include "internals.h"
+
+LIST_HEAD(intc_list);
+DEFINE_RAW_SPINLOCK(intc_big_lock);
+unsigned int nr_intc_controllers;
+
+/*
+ * Default priority level
+ * - this needs to be at least 2 for 5-bit priorities on 7780
+ */
+static unsigned int default_prio_level = 2;    /* 2 - 16 */
+static unsigned int intc_prio_level[NR_IRQS];  /* for now */
+
+unsigned int intc_get_dfl_prio_level(void)
+{
+       return default_prio_level;
+}
+
+unsigned int intc_get_prio_level(unsigned int irq)
+{
+       return intc_prio_level[irq];
+}
+
+void intc_set_prio_level(unsigned int irq, unsigned int level)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       intc_prio_level[irq] = level;
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
+{
+       generic_handle_irq((unsigned int)get_irq_data(irq));
+}
+
+static void __init intc_register_irq(struct intc_desc *desc,
+                                    struct intc_desc_int *d,
+                                    intc_enum enum_id,
+                                    unsigned int irq)
+{
+       struct intc_handle_int *hp;
+       unsigned int data[2], primary;
+       unsigned long flags;
+
+       /*
+        * Register the IRQ position with the global IRQ map, then insert
+        * it in to the radix tree.
+        */
+       reserve_irq_vector(irq);
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+
+       /*
+        * Prefer single interrupt source bitmap over other combinations:
+        *
+        * 1. bitmap, single interrupt source
+        * 2. priority, single interrupt source
+        * 3. bitmap, multiple interrupt sources (groups)
+        * 4. priority, multiple interrupt sources (groups)
+        */
+       data[0] = intc_get_mask_handle(desc, d, enum_id, 0);
+       data[1] = intc_get_prio_handle(desc, d, enum_id, 0);
+
+       primary = 0;
+       if (!data[0] && data[1])
+               primary = 1;
+
+       if (!data[0] && !data[1])
+               pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
+                          irq, irq2evt(irq));
+
+       data[0] = data[0] ? data[0] : intc_get_mask_handle(desc, d, enum_id, 1);
+       data[1] = data[1] ? data[1] : intc_get_prio_handle(desc, d, enum_id, 1);
+
+       if (!data[primary])
+               primary ^= 1;
+
+       BUG_ON(!data[primary]); /* must have primary masking method */
+
+       disable_irq_nosync(irq);
+       set_irq_chip_and_handler_name(irq, &d->chip,
+                                     handle_level_irq, "level");
+       set_irq_chip_data(irq, (void *)data[primary]);
+
+       /*
+        * set priority level
+        */
+       intc_set_prio_level(irq, intc_get_dfl_prio_level());
+
+       /* enable secondary masking method if present */
+       if (data[!primary])
+               _intc_enable(irq, data[!primary]);
+
+       /* add irq to d->prio list if priority is available */
+       if (data[1]) {
+               hp = d->prio + d->nr_prio;
+               hp->irq = irq;
+               hp->handle = data[1];
+
+               if (primary) {
+                       /*
+                        * only secondary priority should access registers, so
+                        * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
+                        */
+                       hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
+                       hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
+               }
+               d->nr_prio++;
+       }
+
+       /* add irq to d->sense list if sense is available */
+       data[0] = intc_get_sense_handle(desc, d, enum_id);
+       if (data[0]) {
+               (d->sense + d->nr_sense)->irq = irq;
+               (d->sense + d->nr_sense)->handle = data[0];
+               d->nr_sense++;
+       }
+
+       /* irq should be disabled by default */
+       d->chip.mask(irq);
+
+       intc_set_ack_handle(irq, desc, d, enum_id);
+       intc_set_dist_handle(irq, desc, d, enum_id);
+
+       activate_irq(irq);
+}
+
+static unsigned int __init save_reg(struct intc_desc_int *d,
+                                   unsigned int cnt,
+                                   unsigned long value,
+                                   unsigned int smp)
+{
+       if (value) {
+               value = intc_phys_to_virt(d, value);
+
+               d->reg[cnt] = value;
+#ifdef CONFIG_SMP
+               d->smp[cnt] = smp;
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+int __init register_intc_controller(struct intc_desc *desc)
+{
+       unsigned int i, k, smp;
+       struct intc_hw_desc *hw = &desc->hw;
+       struct intc_desc_int *d;
+       struct resource *res;
+
+       pr_info("Registered controller '%s' with %u IRQs\n",
+               desc->name, hw->nr_vectors);
+
+       d = kzalloc(sizeof(*d), GFP_NOWAIT);
+       if (!d)
+               goto err0;
+
+       INIT_LIST_HEAD(&d->list);
+       list_add_tail(&d->list, &intc_list);
+
+       raw_spin_lock_init(&d->lock);
+
+       d->index = nr_intc_controllers;
+
+       if (desc->num_resources) {
+               d->nr_windows = desc->num_resources;
+               d->window = kzalloc(d->nr_windows * sizeof(*d->window),
+                                   GFP_NOWAIT);
+               if (!d->window)
+                       goto err1;
+
+               for (k = 0; k < d->nr_windows; k++) {
+                       res = desc->resource + k;
+                       WARN_ON(resource_type(res) != IORESOURCE_MEM);
+                       d->window[k].phys = res->start;
+                       d->window[k].size = resource_size(res);
+                       d->window[k].virt = ioremap_nocache(res->start,
+                                                        resource_size(res));
+                       if (!d->window[k].virt)
+                               goto err2;
+               }
+       }
+
+       d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
+#ifdef CONFIG_INTC_BALANCING
+       if (d->nr_reg)
+               d->nr_reg += hw->nr_mask_regs;
+#endif
+       d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
+       d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
+       d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
+       d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0;
+
+       d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
+       if (!d->reg)
+               goto err2;
+
+#ifdef CONFIG_SMP
+       d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
+       if (!d->smp)
+               goto err3;
+#endif
+       k = 0;
+
+       if (hw->mask_regs) {
+               for (i = 0; i < hw->nr_mask_regs; i++) {
+                       smp = IS_SMP(hw->mask_regs[i]);
+                       k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
+                       k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp);
+#ifdef CONFIG_INTC_BALANCING
+                       k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0);
+#endif
+               }
+       }
+
+       if (hw->prio_regs) {
+               d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
+                                 GFP_NOWAIT);
+               if (!d->prio)
+                       goto err4;
+
+               for (i = 0; i < hw->nr_prio_regs; i++) {
+                       smp = IS_SMP(hw->prio_regs[i]);
+                       k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
+                       k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
+               }
+       }
+
+       if (hw->sense_regs) {
+               d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
+                                  GFP_NOWAIT);
+               if (!d->sense)
+                       goto err5;
+
+               for (i = 0; i < hw->nr_sense_regs; i++)
+                       k += save_reg(d, k, hw->sense_regs[i].reg, 0);
+       }
+
+       if (hw->subgroups)
+               for (i = 0; i < hw->nr_subgroups; i++)
+                       if (hw->subgroups[i].reg)
+                               k+= save_reg(d, k, hw->subgroups[i].reg, 0);
+
+       memcpy(&d->chip, &intc_irq_chip, sizeof(struct irq_chip));
+       d->chip.name = desc->name;
+
+       if (hw->ack_regs)
+               for (i = 0; i < hw->nr_ack_regs; i++)
+                       k += save_reg(d, k, hw->ack_regs[i].set_reg, 0);
+       else
+               d->chip.mask_ack = d->chip.disable;
+
+       /* disable bits matching force_disable before registering irqs */
+       if (desc->force_disable)
+               intc_enable_disable_enum(desc, d, desc->force_disable, 0);
+
+       /* disable bits matching force_enable before registering irqs */
+       if (desc->force_enable)
+               intc_enable_disable_enum(desc, d, desc->force_enable, 0);
+
+       BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
+
+       /* register the vectors one by one */
+       for (i = 0; i < hw->nr_vectors; i++) {
+               struct intc_vect *vect = hw->vectors + i;
+               unsigned int irq = evt2irq(vect->vect);
+               struct irq_desc *irq_desc;
+
+               if (!vect->enum_id)
+                       continue;
+
+               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
+               if (unlikely(!irq_desc)) {
+                       pr_err("can't get irq_desc for %d\n", irq);
+                       continue;
+               }
+
+               intc_irq_xlate_set(irq, vect->enum_id, d);
+               intc_register_irq(desc, d, vect->enum_id, irq);
+
+               for (k = i + 1; k < hw->nr_vectors; k++) {
+                       struct intc_vect *vect2 = hw->vectors + k;
+                       unsigned int irq2 = evt2irq(vect2->vect);
+
+                       if (vect->enum_id != vect2->enum_id)
+                               continue;
+
+                       /*
+                        * In the case of multi-evt handling and sparse
+                        * IRQ support, each vector still needs to have
+                        * its own backing irq_desc.
+                        */
+                       irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
+                       if (unlikely(!irq_desc)) {
+                               pr_err("can't get irq_desc for %d\n", irq2);
+                               continue;
+                       }
+
+                       vect2->enum_id = 0;
+
+                       /* redirect this interrupts to the first one */
+                       set_irq_chip(irq2, &dummy_irq_chip);
+                       set_irq_chained_handler(irq2, intc_redirect_irq);
+                       set_irq_data(irq2, (void *)irq);
+               }
+       }
+
+       intc_subgroup_init(desc, d);
+
+       /* enable bits matching force_enable after registering irqs */
+       if (desc->force_enable)
+               intc_enable_disable_enum(desc, d, desc->force_enable, 1);
+
+       nr_intc_controllers++;
+
+       return 0;
+err5:
+       kfree(d->prio);
+err4:
+#ifdef CONFIG_SMP
+       kfree(d->smp);
+err3:
+#endif
+       kfree(d->reg);
+err2:
+       for (k = 0; k < d->nr_windows; k++)
+               if (d->window[k].virt)
+                       iounmap(d->window[k].virt);
+
+       kfree(d->window);
+err1:
+       kfree(d);
+err0:
+       pr_err("unable to allocate INTC memory\n");
+
+       return -ENOMEM;
+}
+
+static ssize_t
+show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
+{
+       struct intc_desc_int *d;
+
+       d = container_of(dev, struct intc_desc_int, sysdev);
+
+       return sprintf(buf, "%s\n", d->chip.name);
+}
+
+static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
+
+static int intc_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct intc_desc_int *d;
+       struct irq_desc *desc;
+       int irq;
+
+       /* get intc controller associated with this sysdev */
+       d = container_of(dev, struct intc_desc_int, sysdev);
+
+       switch (state.event) {
+       case PM_EVENT_ON:
+               if (d->state.event != PM_EVENT_FREEZE)
+                       break;
+
+               for_each_irq_desc(irq, desc) {
+                       /*
+                        * This will catch the redirect and VIRQ cases
+                        * due to the dummy_irq_chip being inserted.
+                        */
+                       if (desc->chip != &d->chip)
+                               continue;
+                       if (desc->status & IRQ_DISABLED)
+                               desc->chip->disable(irq);
+                       else
+                               desc->chip->enable(irq);
+               }
+               break;
+       case PM_EVENT_FREEZE:
+               /* nothing has to be done */
+               break;
+       case PM_EVENT_SUSPEND:
+               /* enable wakeup irqs belonging to this intc controller */
+               for_each_irq_desc(irq, desc) {
+                       if (desc->chip != &d->chip)
+                               continue;
+                       if ((desc->status & IRQ_WAKEUP))
+                               desc->chip->enable(irq);
+               }
+               break;
+       }
+
+       d->state = state;
+
+       return 0;
+}
+
+static int intc_resume(struct sys_device *dev)
+{
+       return intc_suspend(dev, PMSG_ON);
+}
+
+struct sysdev_class intc_sysdev_class = {
+       .name           = "intc",
+       .suspend        = intc_suspend,
+       .resume         = intc_resume,
+};
+
+/* register this intc as sysdev to allow suspend/resume */
+static int __init register_intc_sysdevs(void)
+{
+       struct intc_desc_int *d;
+       int error;
+
+       error = sysdev_class_register(&intc_sysdev_class);
+       if (!error) {
+               list_for_each_entry(d, &intc_list, list) {
+                       d->sysdev.id = d->index;
+                       d->sysdev.cls = &intc_sysdev_class;
+                       error = sysdev_register(&d->sysdev);
+                       if (error == 0)
+                               error = sysdev_create_file(&d->sysdev,
+                                                          &attr_name);
+                       if (error)
+                               break;
+               }
+       }
+
+       if (error)
+               pr_err("sysdev registration error\n");
+
+       return error;
+}
+device_initcall(register_intc_sysdevs);
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
new file mode 100644 (file)
index 0000000..6caecdf
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Dynamic IRQ management
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * Modelled after arch/x86/kernel/apic/io_apic.c
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/irq.h>
+#include <linux/bitmap.h>
+#include <linux/spinlock.h>
+#include "internals.h" /* only for activate_irq() damage.. */
+
+/*
+ * The intc_irq_map provides a global map of bound IRQ vectors for a
+ * given platform. Allocation of IRQs are either static through the CPU
+ * vector map, or dynamic in the case of board mux vectors or MSI.
+ *
+ * As this is a central point for all IRQ controllers on the system,
+ * each of the available sources are mapped out here. This combined with
+ * sparseirq makes it quite trivial to keep the vector map tightly packed
+ * when dynamically creating IRQs, as well as tying in to otherwise
+ * unused irq_desc positions in the sparse array.
+ */
+static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
+static DEFINE_RAW_SPINLOCK(vector_lock);
+
+/*
+ * Dynamic IRQ allocation and deallocation
+ */
+unsigned int create_irq_nr(unsigned int irq_want, int node)
+{
+       unsigned int irq = 0, new;
+       unsigned long flags;
+       struct irq_desc *desc;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+
+       /*
+        * First try the wanted IRQ
+        */
+       if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
+               new = irq_want;
+       } else {
+               /* .. then fall back to scanning. */
+               new = find_first_zero_bit(intc_irq_map, nr_irqs);
+               if (unlikely(new == nr_irqs))
+                       goto out_unlock;
+
+               __set_bit(new, intc_irq_map);
+       }
+
+       desc = irq_to_desc_alloc_node(new, node);
+       if (unlikely(!desc)) {
+               pr_err("can't get irq_desc for %d\n", new);
+               goto out_unlock;
+       }
+
+       desc = move_irq_desc(desc, node);
+       irq = new;
+
+out_unlock:
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+
+       if (irq > 0) {
+               dynamic_irq_init(irq);
+               activate_irq(irq);
+       }
+
+       return irq;
+}
+
+int create_irq(void)
+{
+       int nid = cpu_to_node(smp_processor_id());
+       int irq;
+
+       irq = create_irq_nr(NR_IRQS_LEGACY, nid);
+       if (irq == 0)
+               irq = -1;
+
+       return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+       unsigned long flags;
+
+       dynamic_irq_cleanup(irq);
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       __clear_bit(irq, intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
+
+int reserve_irq_vector(unsigned int irq)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       if (test_and_set_bit(irq, intc_irq_map))
+               ret = -EBUSY;
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+
+       return ret;
+}
+
+void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
+{
+       unsigned long flags;
+       int i;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       for (i = 0; i < nr_vecs; i++)
+               __set_bit(evt2irq(vectors[i].vect), intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
+
+void reserve_irq_legacy(void)
+{
+       unsigned long flags;
+       int i, j;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       j = find_first_bit(intc_irq_map, nr_irqs);
+       for (i = 0; i < j; i++)
+               __set_bit(i, intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
diff --git a/drivers/sh/intc/handle.c b/drivers/sh/intc/handle.c
new file mode 100644 (file)
index 0000000..057ce56
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * 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 <linux/init.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include "internals.h"
+
+static unsigned long ack_handle[NR_IRQS];
+
+static intc_enum __init intc_grp_id(struct intc_desc *desc,
+                                   intc_enum enum_id)
+{
+       struct intc_group *g = desc->hw.groups;
+       unsigned int i, j;
+
+       for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) {
+               g = desc->hw.groups + i;
+
+               for (j = 0; g->enum_ids[j]; j++) {
+                       if (g->enum_ids[j] != enum_id)
+                               continue;
+
+                       return g->enum_id;
+               }
+       }
+
+       return 0;
+}
+
+static unsigned int __init _intc_mask_data(struct intc_desc *desc,
+                                          struct intc_desc_int *d,
+                                          intc_enum enum_id,
+                                          unsigned int *reg_idx,
+                                          unsigned int *fld_idx)
+{
+       struct intc_mask_reg *mr = desc->hw.mask_regs;
+       unsigned int fn, mode;
+       unsigned long reg_e, reg_d;
+
+       while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) {
+               mr = desc->hw.mask_regs + *reg_idx;
+
+               for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) {
+                       if (mr->enum_ids[*fld_idx] != enum_id)
+                               continue;
+
+                       if (mr->set_reg && mr->clr_reg) {
+                               fn = REG_FN_WRITE_BASE;
+                               mode = MODE_DUAL_REG;
+                               reg_e = mr->clr_reg;
+                               reg_d = mr->set_reg;
+                       } else {
+                               fn = REG_FN_MODIFY_BASE;
+                               if (mr->set_reg) {
+                                       mode = MODE_ENABLE_REG;
+                                       reg_e = mr->set_reg;
+                                       reg_d = mr->set_reg;
+                               } else {
+                                       mode = MODE_MASK_REG;
+                                       reg_e = mr->clr_reg;
+                                       reg_d = mr->clr_reg;
+                               }
+                       }
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - *fld_idx);
+               }
+
+               *fld_idx = 0;
+               (*reg_idx)++;
+       }
+
+       return 0;
+}
+
+unsigned int __init
+intc_get_mask_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                    intc_enum enum_id, int do_grps)
+{
+       unsigned int i = 0;
+       unsigned int j = 0;
+       unsigned int ret;
+
+       ret = _intc_mask_data(desc, d, enum_id, &i, &j);
+       if (ret)
+               return ret;
+
+       if (do_grps)
+               return intc_get_mask_handle(desc, d, intc_grp_id(desc, enum_id), 0);
+
+       return 0;
+}
+
+static unsigned int __init _intc_prio_data(struct intc_desc *desc,
+                                          struct intc_desc_int *d,
+                                          intc_enum enum_id,
+                                          unsigned int *reg_idx,
+                                          unsigned int *fld_idx)
+{
+       struct intc_prio_reg *pr = desc->hw.prio_regs;
+       unsigned int fn, n, mode, bit;
+       unsigned long reg_e, reg_d;
+
+       while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) {
+               pr = desc->hw.prio_regs + *reg_idx;
+
+               for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) {
+                       if (pr->enum_ids[*fld_idx] != enum_id)
+                               continue;
+
+                       if (pr->set_reg && pr->clr_reg) {
+                               fn = REG_FN_WRITE_BASE;
+                               mode = MODE_PCLR_REG;
+                               reg_e = pr->set_reg;
+                               reg_d = pr->clr_reg;
+                       } else {
+                               fn = REG_FN_MODIFY_BASE;
+                               mode = MODE_PRIO_REG;
+                               if (!pr->set_reg)
+                                       BUG();
+                               reg_e = pr->set_reg;
+                               reg_d = pr->set_reg;
+                       }
+
+                       fn += (pr->reg_width >> 3) - 1;
+                       n = *fld_idx + 1;
+
+                       BUG_ON(n * pr->field_width > pr->reg_width);
+
+                       bit = pr->reg_width - (n * pr->field_width);
+
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       pr->field_width, bit);
+               }
+
+               *fld_idx = 0;
+               (*reg_idx)++;
+       }
+
+       return 0;
+}
+
+unsigned int __init
+intc_get_prio_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                    intc_enum enum_id, int do_grps)
+{
+       unsigned int i = 0;
+       unsigned int j = 0;
+       unsigned int ret;
+
+       ret = _intc_prio_data(desc, d, enum_id, &i, &j);
+       if (ret)
+               return ret;
+
+       if (do_grps)
+               return intc_get_prio_handle(desc, d, intc_grp_id(desc, enum_id), 0);
+
+       return 0;
+}
+
+static unsigned int __init intc_ack_data(struct intc_desc *desc,
+                                         struct intc_desc_int *d,
+                                         intc_enum enum_id)
+{
+       struct intc_mask_reg *mr = desc->hw.ack_regs;
+       unsigned int i, j, fn, mode;
+       unsigned long reg_e, reg_d;
+
+       for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) {
+               mr = desc->hw.ack_regs + i;
+
+               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+                       if (mr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       mode = MODE_ENABLE_REG;
+                       reg_e = mr->set_reg;
+                       reg_d = mr->set_reg;
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - j);
+               }
+       }
+
+       return 0;
+}
+
+static void intc_enable_disable(struct intc_desc_int *d,
+                               unsigned long handle, int do_enable)
+{
+       unsigned long addr;
+       unsigned int cpu;
+       unsigned long (*fn)(unsigned long, unsigned long,
+                  unsigned long (*)(unsigned long, unsigned long,
+                                    unsigned long),
+                  unsigned int);
+
+       if (do_enable) {
+               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+                       addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+                       fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
+                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+               }
+       } else {
+               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+                       addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+                       fn = intc_disable_fns[_INTC_MODE(handle)];
+                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+               }
+       }
+}
+
+void __init intc_enable_disable_enum(struct intc_desc *desc,
+                                    struct intc_desc_int *d,
+                                    intc_enum enum_id, int enable)
+{
+       unsigned int i, j, data;
+
+       /* go through and enable/disable all mask bits */
+       i = j = 0;
+       do {
+               data = _intc_mask_data(desc, d, enum_id, &i, &j);
+               if (data)
+                       intc_enable_disable(d, data, enable);
+               j++;
+       } while (data);
+
+       /* go through and enable/disable all priority fields */
+       i = j = 0;
+       do {
+               data = _intc_prio_data(desc, d, enum_id, &i, &j);
+               if (data)
+                       intc_enable_disable(d, data, enable);
+
+               j++;
+       } while (data);
+}
+
+unsigned int __init
+intc_get_sense_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                     intc_enum enum_id)
+{
+       struct intc_sense_reg *sr = desc->hw.sense_regs;
+       unsigned int i, j, fn, bit;
+
+       for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) {
+               sr = desc->hw.sense_regs + i;
+
+               for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
+                       if (sr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       fn += (sr->reg_width >> 3) - 1;
+
+                       BUG_ON((j + 1) * sr->field_width > sr->reg_width);
+
+                       bit = sr->reg_width - ((j + 1) * sr->field_width);
+
+                       return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
+                                       0, sr->field_width, bit);
+               }
+       }
+
+       return 0;
+}
+
+
+void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
+                        struct intc_desc_int *d, intc_enum id)
+{
+       unsigned long flags;
+
+       /*
+        * Nothing to do for this IRQ.
+        */
+       if (!desc->hw.ack_regs)
+               return;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       ack_handle[irq] = intc_ack_data(desc, d, id);
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+unsigned long intc_get_ack_handle(unsigned int irq)
+{
+       return ack_handle[irq];
+}
diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
new file mode 100644 (file)
index 0000000..d49482c
--- /dev/null
@@ -0,0 +1,186 @@
+#include <linux/sh_intc.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/radix-tree.h>
+#include <linux/sysdev.h>
+
+#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
+       ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
+        ((addr_e) << 16) | ((addr_d << 24)))
+
+#define _INTC_SHIFT(h)         (h & 0x1f)
+#define _INTC_WIDTH(h)         ((h >> 5) & 0xf)
+#define _INTC_FN(h)            ((h >> 9) & 0xf)
+#define _INTC_MODE(h)          ((h >> 13) & 0x7)
+#define _INTC_ADDR_E(h)                ((h >> 16) & 0xff)
+#define _INTC_ADDR_D(h)                ((h >> 24) & 0xff)
+
+#ifdef CONFIG_SMP
+#define IS_SMP(x)              (x.smp)
+#define INTC_REG(d, x, c)      (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
+#define SMP_NR(d, x)           ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
+#else
+#define IS_SMP(x)              0
+#define INTC_REG(d, x, c)      (d->reg[(x)])
+#define SMP_NR(d, x)           1
+#endif
+
+struct intc_handle_int {
+       unsigned int irq;
+       unsigned long handle;
+};
+
+struct intc_window {
+       phys_addr_t phys;
+       void __iomem *virt;
+       unsigned long size;
+};
+
+struct intc_map_entry {
+       intc_enum enum_id;
+       struct intc_desc_int *desc;
+};
+
+struct intc_subgroup_entry {
+       unsigned int pirq;
+       intc_enum enum_id;
+       unsigned long handle;
+};
+
+struct intc_desc_int {
+       struct list_head list;
+       struct sys_device sysdev;
+       struct radix_tree_root tree;
+       pm_message_t state;
+       raw_spinlock_t lock;
+       unsigned int index;
+       unsigned long *reg;
+#ifdef CONFIG_SMP
+       unsigned long *smp;
+#endif
+       unsigned int nr_reg;
+       struct intc_handle_int *prio;
+       unsigned int nr_prio;
+       struct intc_handle_int *sense;
+       unsigned int nr_sense;
+       struct intc_window *window;
+       unsigned int nr_windows;
+       struct irq_chip chip;
+};
+
+
+enum {
+       REG_FN_ERR = 0,
+       REG_FN_TEST_BASE = 1,
+       REG_FN_WRITE_BASE = 5,
+       REG_FN_MODIFY_BASE = 9
+};
+
+enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
+       MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
+       MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
+       MODE_PRIO_REG,       /* Priority value written to enable interrupt */
+       MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
+};
+
+static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
+{
+       struct irq_chip *chip = get_irq_chip(irq);
+
+       return container_of(chip, struct intc_desc_int, chip);
+}
+
+/*
+ * Grumble.
+ */
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+       /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+        * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
+        */
+       set_irq_flags(irq, IRQF_VALID);
+#else
+       /* same effect on other architectures */
+       set_irq_noprobe(irq);
+#endif
+}
+
+/* access.c */
+extern unsigned long
+(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data);
+
+extern unsigned long
+(*intc_enable_fns[])(unsigned long addr, unsigned long handle,
+                    unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                    unsigned int irq);
+extern unsigned long
+(*intc_disable_fns[])(unsigned long addr, unsigned long handle,
+                     unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                     unsigned int irq);
+extern unsigned long
+(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle,
+                           unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                           unsigned int irq);
+
+unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address);
+unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address);
+unsigned int intc_set_field_from_handle(unsigned int value,
+                           unsigned int field_value,
+                           unsigned int handle);
+unsigned long intc_get_field_from_handle(unsigned int value,
+                                        unsigned int handle);
+
+/* balancing.c */
+#ifdef CONFIG_INTC_BALANCING
+void intc_balancing_enable(unsigned int irq);
+void intc_balancing_disable(unsigned int irq);
+void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                         struct intc_desc_int *d, intc_enum id);
+#else
+static inline void intc_balancing_enable(unsigned int irq) { }
+static inline void intc_balancing_disable(unsigned int irq) { }
+static inline void
+intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                    struct intc_desc_int *d, intc_enum id) { }
+#endif
+
+/* chip.c */
+extern struct irq_chip intc_irq_chip;
+void _intc_enable(unsigned int irq, unsigned long handle);
+
+/* core.c */
+extern struct list_head intc_list;
+extern raw_spinlock_t intc_big_lock;
+extern unsigned int nr_intc_controllers;
+extern struct sysdev_class intc_sysdev_class;
+
+unsigned int intc_get_dfl_prio_level(void);
+unsigned int intc_get_prio_level(unsigned int irq);
+void intc_set_prio_level(unsigned int irq, unsigned int level);
+
+/* handle.c */
+unsigned int intc_get_mask_handle(struct intc_desc *desc,
+                                 struct intc_desc_int *d,
+                                 intc_enum enum_id, int do_grps);
+unsigned int intc_get_prio_handle(struct intc_desc *desc,
+                                 struct intc_desc_int *d,
+                                 intc_enum enum_id, int do_grps);
+unsigned int intc_get_sense_handle(struct intc_desc *desc,
+                                  struct intc_desc_int *d,
+                                  intc_enum enum_id);
+void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
+                        struct intc_desc_int *d, intc_enum id);
+unsigned long intc_get_ack_handle(unsigned int irq);
+void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
+                             intc_enum enum_id, int enable);
+
+/* virq.c */
+void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
+void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
+struct intc_map_entry *intc_irq_xlate_get(unsigned int irq);
diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c
new file mode 100644 (file)
index 0000000..e32304b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Support for hardware-assisted userspace interrupt masking.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/errno.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/sizes.h>
+#include "internals.h"
+
+static void __iomem *uimask;
+
+static ssize_t
+show_intc_userimask(struct sysdev_class *cls,
+                   struct sysdev_class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf);
+}
+
+static ssize_t
+store_intc_userimask(struct sysdev_class *cls,
+                    struct sysdev_class_attribute *attr,
+                    const char *buf, size_t count)
+{
+       unsigned long level;
+
+       level = simple_strtoul(buf, NULL, 10);
+
+       /*
+        * Minimal acceptable IRQ levels are in the 2 - 16 range, but
+        * these are chomped so as to not interfere with normal IRQs.
+        *
+        * Level 1 is a special case on some CPUs in that it's not
+        * directly settable, but given that USERIMASK cuts off below a
+        * certain level, we don't care about this limitation here.
+        * Level 0 on the other hand equates to user masking disabled.
+        *
+        * We use the default priority level as a cut off so that only
+        * special case opt-in IRQs can be mangled.
+        */
+       if (level >= intc_get_dfl_prio_level())
+               return -EINVAL;
+
+       __raw_writel(0xa5 << 24 | level << 4, uimask);
+
+       return count;
+}
+
+static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR,
+                        show_intc_userimask, store_intc_userimask);
+
+
+static int __init userimask_sysdev_init(void)
+{
+       if (unlikely(!uimask))
+               return -ENXIO;
+
+       return sysdev_class_create_file(&intc_sysdev_class, &attr_userimask);
+}
+late_initcall(userimask_sysdev_init);
+
+int register_intc_userimask(unsigned long addr)
+{
+       if (unlikely(uimask))
+               return -EBUSY;
+
+       uimask = ioremap_nocache(addr, SZ_4K);
+       if (unlikely(!uimask))
+               return -ENOMEM;
+
+       pr_info("userimask support registered for levels 0 -> %d\n",
+               intc_get_dfl_prio_level() - 1);
+
+       return 0;
+}
diff --git a/drivers/sh/intc/virq-debugfs.c b/drivers/sh/intc/virq-debugfs.c
new file mode 100644 (file)
index 0000000..9e62ba9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Support for virtual IRQ subgroups debugfs mapping.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * Modelled after arch/powerpc/kernel/irq.c.
+ *
+ * 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 <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include "internals.h"
+
+static int intc_irq_xlate_debug(struct seq_file *m, void *priv)
+{
+       int i;
+
+       seq_printf(m, "%-5s  %-7s  %-15s\n", "irq", "enum", "chip name");
+
+       for (i = 1; i < nr_irqs; i++) {
+               struct intc_map_entry *entry = intc_irq_xlate_get(i);
+               struct intc_desc_int *desc = entry->desc;
+
+               if (!desc)
+                       continue;
+
+               seq_printf(m, "%5d  ", i);
+               seq_printf(m, "0x%05x  ", entry->enum_id);
+               seq_printf(m, "%-15s\n", desc->chip.name);
+       }
+
+       return 0;
+}
+
+static int intc_irq_xlate_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, intc_irq_xlate_debug, inode->i_private);
+}
+
+static const struct file_operations intc_irq_xlate_fops = {
+       .open = intc_irq_xlate_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int __init intc_irq_xlate_init(void)
+{
+       /*
+        * XXX.. use arch_debugfs_dir here when all of the intc users are
+        * converted.
+        */
+       if (debugfs_create_file("intc_irq_xlate", S_IRUGO, NULL, NULL,
+                               &intc_irq_xlate_fops) == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+fs_initcall(intc_irq_xlate_init);
diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
new file mode 100644 (file)
index 0000000..643dfd4
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Support for virtual IRQ subgroups.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/radix-tree.h>
+#include <linux/spinlock.h>
+#include "internals.h"
+
+static struct intc_map_entry intc_irq_xlate[NR_IRQS];
+
+struct intc_virq_list {
+       unsigned int irq;
+       struct intc_virq_list *next;
+};
+
+#define for_each_virq(entry, head) \
+       for (entry = head; entry; entry = entry->next)
+
+/*
+ * Tags for the radix tree
+ */
+#define INTC_TAG_VIRQ_NEEDS_ALLOC      0
+
+void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       intc_irq_xlate[irq].enum_id = id;
+       intc_irq_xlate[irq].desc = d;
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+struct intc_map_entry *intc_irq_xlate_get(unsigned int irq)
+{
+       return intc_irq_xlate + irq;
+}
+
+int intc_irq_lookup(const char *chipname, intc_enum enum_id)
+{
+       struct intc_map_entry *ptr;
+       struct intc_desc_int *d;
+       int irq = -1;
+
+       list_for_each_entry(d, &intc_list, list) {
+               int tagged;
+
+               if (strcmp(d->chip.name, chipname) != 0)
+                       continue;
+
+               /*
+                * Catch early lookups for subgroup VIRQs that have not
+                * yet been allocated an IRQ. This already includes a
+                * fast-path out if the tree is untagged, so there is no
+                * need to explicitly test the root tree.
+                */
+               tagged = radix_tree_tag_get(&d->tree, enum_id,
+                                           INTC_TAG_VIRQ_NEEDS_ALLOC);
+               if (unlikely(tagged))
+                       break;
+
+               ptr = radix_tree_lookup(&d->tree, enum_id);
+               if (ptr) {
+                       irq = ptr - intc_irq_xlate;
+                       break;
+               }
+       }
+
+       return irq;
+}
+EXPORT_SYMBOL_GPL(intc_irq_lookup);
+
+static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
+{
+       struct intc_virq_list **last, *entry;
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       /* scan for duplicates */
+       last = (struct intc_virq_list **)&desc->handler_data;
+       for_each_virq(entry, desc->handler_data) {
+               if (entry->irq == virq)
+                       return 0;
+               last = &entry->next;
+       }
+
+       entry = kzalloc(sizeof(struct intc_virq_list), GFP_ATOMIC);
+       if (!entry) {
+               pr_err("can't allocate VIRQ mapping for %d\n", virq);
+               return -ENOMEM;
+       }
+
+       entry->irq = virq;
+
+       *last = entry;
+
+       return 0;
+}
+
+static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct intc_virq_list *entry, *vlist = get_irq_data(irq);
+       struct intc_desc_int *d = get_intc_desc(irq);
+
+       desc->chip->mask_ack(irq);
+
+       for_each_virq(entry, vlist) {
+               unsigned long addr, handle;
+
+               handle = (unsigned long)get_irq_data(entry->irq);
+               addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
+
+               if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
+                       generic_handle_irq(entry->irq);
+       }
+
+       desc->chip->unmask(irq);
+}
+
+static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup,
+                                              struct intc_desc_int *d,
+                                              unsigned int index)
+{
+       unsigned int fn = REG_FN_TEST_BASE + (subgroup->reg_width >> 3) - 1;
+
+       return _INTC_MK(fn, MODE_ENABLE_REG, intc_get_reg(d, subgroup->reg),
+                       0, 1, (subgroup->reg_width - 1) - index);
+}
+
+static void __init intc_subgroup_init_one(struct intc_desc *desc,
+                                         struct intc_desc_int *d,
+                                         struct intc_subgroup *subgroup)
+{
+       struct intc_map_entry *mapped;
+       unsigned int pirq;
+       unsigned long flags;
+       int i;
+
+       mapped = radix_tree_lookup(&d->tree, subgroup->parent_id);
+       if (!mapped) {
+               WARN_ON(1);
+               return;
+       }
+
+       pirq = mapped - intc_irq_xlate;
+
+       raw_spin_lock_irqsave(&d->lock, flags);
+
+       for (i = 0; i < ARRAY_SIZE(subgroup->enum_ids); i++) {
+               struct intc_subgroup_entry *entry;
+               int err;
+
+               if (!subgroup->enum_ids[i])
+                       continue;
+
+               entry = kmalloc(sizeof(*entry), GFP_NOWAIT);
+               if (!entry)
+                       break;
+
+               entry->pirq = pirq;
+               entry->enum_id = subgroup->enum_ids[i];
+               entry->handle = intc_subgroup_data(subgroup, d, i);
+
+               err = radix_tree_insert(&d->tree, entry->enum_id, entry);
+               if (unlikely(err < 0))
+                       break;
+
+               radix_tree_tag_set(&d->tree, entry->enum_id,
+                                  INTC_TAG_VIRQ_NEEDS_ALLOC);
+       }
+
+       raw_spin_unlock_irqrestore(&d->lock, flags);
+}
+
+void __init intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d)
+{
+       int i;
+
+       if (!desc->hw.subgroups)
+               return;
+
+       for (i = 0; i < desc->hw.nr_subgroups; i++)
+               intc_subgroup_init_one(desc, d, desc->hw.subgroups + i);
+}
+
+static void __init intc_subgroup_map(struct intc_desc_int *d)
+{
+       struct intc_subgroup_entry *entries[32];
+       unsigned long flags;
+       unsigned int nr_found;
+       int i;
+
+       raw_spin_lock_irqsave(&d->lock, flags);
+
+restart:
+       nr_found = radix_tree_gang_lookup_tag_slot(&d->tree,
+                       (void ***)entries, 0, ARRAY_SIZE(entries),
+                       INTC_TAG_VIRQ_NEEDS_ALLOC);
+
+       for (i = 0; i < nr_found; i++) {
+               struct intc_subgroup_entry *entry;
+               int irq;
+
+               entry = radix_tree_deref_slot((void **)entries[i]);
+               if (unlikely(!entry))
+                       continue;
+               if (unlikely(entry == RADIX_TREE_RETRY))
+                       goto restart;
+
+               irq = create_irq();
+               if (unlikely(irq < 0)) {
+                       pr_err("no more free IRQs, bailing..\n");
+                       break;
+               }
+
+               pr_info("Setting up a chained VIRQ from %d -> %d\n",
+                       irq, entry->pirq);
+
+               intc_irq_xlate_set(irq, entry->enum_id, d);
+
+               set_irq_chip_and_handler_name(irq, get_irq_chip(entry->pirq),
+                                             handle_simple_irq, "virq");
+               set_irq_chip_data(irq, get_irq_chip_data(entry->pirq));
+
+               set_irq_data(irq, (void *)entry->handle);
+
+               set_irq_chained_handler(entry->pirq, intc_virq_handler);
+               add_virq_to_pirq(entry->pirq, irq);
+
+               radix_tree_tag_clear(&d->tree, entry->enum_id,
+                                    INTC_TAG_VIRQ_NEEDS_ALLOC);
+               radix_tree_replace_slot((void **)entries[i],
+                                       &intc_irq_xlate[irq]);
+       }
+
+       raw_spin_unlock_irqrestore(&d->lock, flags);
+}
+
+void __init intc_finalize(void)
+{
+       struct intc_desc_int *d;
+
+       list_for_each_entry(d, &intc_list, list)
+               if (radix_tree_tagged(&d->tree, INTC_TAG_VIRQ_NEEDS_ALLOC))
+                       intc_subgroup_map(d);
+}
index cf0303a..75934e3 100644 (file)
@@ -7,6 +7,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -559,10 +561,8 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
        struct pinmux_data_reg *dr = NULL;
        int bit = 0;
 
-       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) {
-               BUG();
-               return 0;
-       }
+       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+               return -EINVAL;
 
        return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
 }
@@ -581,7 +581,7 @@ int register_pinmux(struct pinmux_info *pip)
 {
        struct gpio_chip *chip = &pip->chip;
 
-       pr_info("sh pinmux: %s handling gpio %d -> %d\n",
+       pr_info("%s handling gpio %d -> %d\n",
                pip->name, pip->first_gpio, pip->last_gpio);
 
        setup_data_regs(pip);
@@ -602,3 +602,10 @@ int register_pinmux(struct pinmux_info *pip)
 
        return gpiochip_add(chip);
 }
+
+int unregister_pinmux(struct pinmux_info *pip)
+{
+       pr_info("%s deregistering\n", pip->name);
+
+       return gpiochip_remove(&pip->chip);
+}
index 4b9eec6..78f9fd0 100644 (file)
@@ -329,6 +329,13 @@ config SPI_STMP3XXX
        help
          SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
+config SPI_TEGRA
+       tristate "Nvidia Tegra SPI controller"
+       depends on ARCH_TEGRA
+       select TEGRA_SYSTEM_DMA
+       help
+         SPI driver for NVidia Tegra SoCs
+
 config SPI_TOPCLIFF_PCH
        tristate "Topcliff PCH SPI Controller"
        depends on PCI
index 557aaad..8bc1a5a 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_SPI_PPC4xx)              += spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)              += spi_s3c64xx.o
+obj-$(CONFIG_SPI_TEGRA)                        += spi_tegra.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)         += spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
new file mode 100644 (file)
index 0000000..bb7df02
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * Driver for Nvidia TEGRA spi controller.
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+
+#define SLINK_COMMAND          0x000
+#define   SLINK_BIT_LENGTH(x)          (((x) & 0x1f) << 0)
+#define   SLINK_WORD_SIZE(x)           (((x) & 0x1f) << 5)
+#define   SLINK_BOTH_EN                        (1 << 10)
+#define   SLINK_CS_SW                  (1 << 11)
+#define   SLINK_CS_VALUE               (1 << 12)
+#define   SLINK_CS_POLARITY            (1 << 13)
+#define   SLINK_IDLE_SDA_DRIVE_LOW     (0 << 16)
+#define   SLINK_IDLE_SDA_DRIVE_HIGH    (1 << 16)
+#define   SLINK_IDLE_SDA_PULL_LOW      (2 << 16)
+#define   SLINK_IDLE_SDA_PULL_HIGH     (3 << 16)
+#define   SLINK_IDLE_SDA_MASK          (3 << 16)
+#define   SLINK_CS_POLARITY1           (1 << 20)
+#define   SLINK_CK_SDA                 (1 << 21)
+#define   SLINK_CS_POLARITY2           (1 << 22)
+#define   SLINK_CS_POLARITY3           (1 << 23)
+#define   SLINK_IDLE_SCLK_DRIVE_LOW    (0 << 24)
+#define   SLINK_IDLE_SCLK_DRIVE_HIGH   (1 << 24)
+#define   SLINK_IDLE_SCLK_PULL_LOW     (2 << 24)
+#define   SLINK_IDLE_SCLK_PULL_HIGH    (3 << 24)
+#define   SLINK_IDLE_SCLK_MASK         (3 << 24)
+#define   SLINK_M_S                    (1 << 28)
+#define   SLINK_WAIT                   (1 << 29)
+#define   SLINK_GO                     (1 << 30)
+#define   SLINK_ENB                    (1 << 31)
+
+#define SLINK_COMMAND2         0x004
+#define   SLINK_LSBFE                  (1 << 0)
+#define   SLINK_SSOE                   (1 << 1)
+#define   SLINK_SPIE                   (1 << 4)
+#define   SLINK_BIDIROE                        (1 << 6)
+#define   SLINK_MODFEN                 (1 << 7)
+#define   SLINK_INT_SIZE(x)            (((x) & 0x1f) << 8)
+#define   SLINK_CS_ACTIVE_BETWEEN      (1 << 17)
+#define   SLINK_SS_EN_CS(x)            (((x) & 0x3) << 18)
+#define   SLINK_SS_SETUP(x)            (((x) & 0x3) << 20)
+#define   SLINK_FIFO_REFILLS_0         (0 << 22)
+#define   SLINK_FIFO_REFILLS_1         (1 << 22)
+#define   SLINK_FIFO_REFILLS_2         (2 << 22)
+#define   SLINK_FIFO_REFILLS_3         (3 << 22)
+#define   SLINK_FIFO_REFILLS_MASK      (3 << 22)
+#define   SLINK_WAIT_PACK_INT(x)       (((x) & 0x7) << 26)
+#define   SLINK_SPC0                   (1 << 29)
+#define   SLINK_TXEN                   (1 << 30)
+#define   SLINK_RXEN                   (1 << 31)
+
+#define SLINK_STATUS           0x008
+#define   SLINK_COUNT(val)             (((val) >> 0) & 0x1f)
+#define   SLINK_WORD(val)              (((val) >> 5) & 0x1f)
+#define   SLINK_BLK_CNT(val)           (((val) >> 0) & 0xffff)
+#define   SLINK_MODF                   (1 << 16)
+#define   SLINK_RX_UNF                 (1 << 18)
+#define   SLINK_TX_OVF                 (1 << 19)
+#define   SLINK_TX_FULL                        (1 << 20)
+#define   SLINK_TX_EMPTY               (1 << 21)
+#define   SLINK_RX_FULL                        (1 << 22)
+#define   SLINK_RX_EMPTY               (1 << 23)
+#define   SLINK_TX_UNF                 (1 << 24)
+#define   SLINK_RX_OVF                 (1 << 25)
+#define   SLINK_TX_FLUSH               (1 << 26)
+#define   SLINK_RX_FLUSH               (1 << 27)
+#define   SLINK_SCLK                   (1 << 28)
+#define   SLINK_ERR                    (1 << 29)
+#define   SLINK_RDY                    (1 << 30)
+#define   SLINK_BSY                    (1 << 31)
+
+#define SLINK_MAS_DATA         0x010
+#define SLINK_SLAVE_DATA       0x014
+
+#define SLINK_DMA_CTL          0x018
+#define   SLINK_DMA_BLOCK_SIZE(x)      (((x) & 0xffff) << 0)
+#define   SLINK_TX_TRIG_1              (0 << 16)
+#define   SLINK_TX_TRIG_4              (1 << 16)
+#define   SLINK_TX_TRIG_8              (2 << 16)
+#define   SLINK_TX_TRIG_16             (3 << 16)
+#define   SLINK_TX_TRIG_MASK           (3 << 16)
+#define   SLINK_RX_TRIG_1              (0 << 18)
+#define   SLINK_RX_TRIG_4              (1 << 18)
+#define   SLINK_RX_TRIG_8              (2 << 18)
+#define   SLINK_RX_TRIG_16             (3 << 18)
+#define   SLINK_RX_TRIG_MASK           (3 << 18)
+#define   SLINK_PACKED                 (1 << 20)
+#define   SLINK_PACK_SIZE_4            (0 << 21)
+#define   SLINK_PACK_SIZE_8            (1 << 21)
+#define   SLINK_PACK_SIZE_16           (2 << 21)
+#define   SLINK_PACK_SIZE_32           (3 << 21)
+#define   SLINK_PACK_SIZE_MASK         (3 << 21)
+#define   SLINK_IE_TXC                 (1 << 26)
+#define   SLINK_IE_RXC                 (1 << 27)
+#define   SLINK_DMA_EN                 (1 << 31)
+
+#define SLINK_STATUS2          0x01c
+#define   SLINK_TX_FIFO_EMPTY_COUNT(val)       (((val) & 0x3f) >> 0)
+#define   SLINK_RX_FIFO_FULL_COUNT(val)                (((val) & 0x3f) >> 16)
+
+#define SLINK_TX_FIFO          0x100
+#define SLINK_RX_FIFO          0x180
+
+static const unsigned long spi_tegra_req_sels[] = {
+       TEGRA_DMA_REQ_SEL_SL2B1,
+       TEGRA_DMA_REQ_SEL_SL2B2,
+       TEGRA_DMA_REQ_SEL_SL2B3,
+       TEGRA_DMA_REQ_SEL_SL2B4,
+};
+
+#define BB_LEN                 32
+
+struct spi_tegra_data {
+       struct spi_master       *master;
+       struct platform_device  *pdev;
+       spinlock_t              lock;
+
+       struct clk              *clk;
+       void __iomem            *base;
+       unsigned long           phys;
+
+       u32                     cur_speed;
+
+       struct list_head        queue;
+       struct spi_transfer     *cur;
+       unsigned                cur_pos;
+       unsigned                cur_len;
+       unsigned                cur_bytes_per_word;
+
+       /* The tegra spi controller has a bug which causes the first word
+        * in PIO transactions to be garbage.  Since packed DMA transactions
+        * require transfers to be 4 byte aligned we need a bounce buffer
+        * for the generic case.
+        */
+       struct tegra_dma_req    rx_dma_req;
+       struct tegra_dma_channel *rx_dma;
+       u32                     *rx_bb;
+       dma_addr_t              rx_bb_phys;
+};
+
+
+static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
+                                           unsigned long reg)
+{
+       return readl(tspi->base + reg);
+}
+
+static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
+                                   unsigned long val,
+                                   unsigned long reg)
+{
+       writel(val, tspi->base + reg);
+}
+
+static void spi_tegra_go(struct spi_tegra_data *tspi)
+{
+       unsigned long val;
+
+       wmb();
+
+       val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
+       val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
+       val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
+       spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+
+       tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
+
+       val |= SLINK_DMA_EN;
+       spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+}
+
+static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
+                                 struct spi_transfer *t)
+{
+       unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
+                          tspi->cur_bytes_per_word);
+       u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
+       int i, j;
+       unsigned long val;
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       val &= ~SLINK_WORD_SIZE(~0);
+       val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+               val = 0;
+               for (j = 0; j < tspi->cur_bytes_per_word; j++)
+                       val |= tx_buf[i + j] << j * 8;
+
+               spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
+       }
+
+       tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
+
+       return len;
+}
+
+static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
+                                 struct spi_transfer *t)
+{
+       unsigned len = tspi->cur_len;
+       u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
+       int i, j;
+       unsigned long val;
+
+       for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+               val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
+               for (j = 0; j < tspi->cur_bytes_per_word; j++)
+                       rx_buf[i + j] = (val >> (j * 8)) & 0xff;
+       }
+
+       return len;
+}
+
+static void spi_tegra_start_transfer(struct spi_device *spi,
+                                   struct spi_transfer *t)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       u32 speed;
+       u8 bits_per_word;
+       unsigned long val;
+
+       speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+       bits_per_word = t->bits_per_word ? t->bits_per_word  :
+               spi->bits_per_word;
+
+       tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+       if (speed != tspi->cur_speed)
+               clk_set_rate(tspi->clk, speed);
+
+       if (tspi->cur_speed == 0)
+               clk_enable(tspi->clk);
+
+       tspi->cur_speed = speed;
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND2);
+       val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
+       if (t->rx_buf)
+               val |= SLINK_RXEN;
+       if (t->tx_buf)
+               val |= SLINK_TXEN;
+       val |= SLINK_SS_EN_CS(spi->chip_select);
+       val |= SLINK_SPIE;
+       spi_tegra_writel(tspi, val, SLINK_COMMAND2);
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       val &= ~SLINK_BIT_LENGTH(~0);
+       val |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+       /* FIXME: should probably control CS manually so that we can be sure
+        * it does not go low between transfer and to support delay_usecs
+        * correctly.
+        */
+       val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
+
+       if (spi->mode & SPI_CPHA)
+               val |= SLINK_CK_SDA;
+
+       if (spi->mode & SPI_CPOL)
+               val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+       else
+               val |= SLINK_IDLE_SCLK_DRIVE_LOW;
+
+       val |= SLINK_M_S;
+
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
+
+       tspi->cur = t;
+       tspi->cur_pos = 0;
+       tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
+
+       spi_tegra_go(tspi);
+}
+
+static void spi_tegra_start_message(struct spi_device *spi,
+                                   struct spi_message *m)
+{
+       struct spi_transfer *t;
+
+       m->actual_length = 0;
+       m->status = 0;
+
+       t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
+       spi_tegra_start_transfer(spi, t);
+}
+
+static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
+{
+       struct spi_tegra_data *tspi = req->dev;
+       unsigned long flags;
+       struct spi_message *m;
+       struct spi_device *spi;
+       int timeout = 0;
+       unsigned long val;
+
+       /* the SPI controller may come back with both the BSY and RDY bits
+        * set.  In this case we need to wait for the BSY bit to clear so
+        * that we are sure the DMA is finished.  1000 reads was empirically
+        * determined to be long enough.
+        */
+       while (timeout++ < 1000) {
+               if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
+                       break;
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+
+       val = spi_tegra_readl(tspi, SLINK_STATUS);
+       val |= SLINK_RDY;
+       spi_tegra_writel(tspi, val, SLINK_STATUS);
+
+       m = list_first_entry(&tspi->queue, struct spi_message, queue);
+
+       if (timeout >= 1000)
+               m->status = -EIO;
+
+       spi = m->state;
+
+       tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
+       m->actual_length += tspi->cur_pos;
+
+       if (tspi->cur_pos < tspi->cur->len) {
+               tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
+               spi_tegra_go(tspi);
+       } else if (!list_is_last(&tspi->cur->transfer_list,
+                                &m->transfers)) {
+               tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
+                                             struct spi_transfer,
+                                             transfer_list);
+               spi_tegra_start_transfer(spi, tspi->cur);
+       } else {
+               list_del(&m->queue);
+
+               m->complete(m->context);
+
+               if (!list_empty(&tspi->queue)) {
+                       m = list_first_entry(&tspi->queue, struct spi_message,
+                                            queue);
+                       spi = m->state;
+                       spi_tegra_start_message(spi, m);
+               } else {
+                       clk_disable(tspi->clk);
+                       tspi->cur_speed = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+}
+
+static int spi_tegra_setup(struct spi_device *spi)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       unsigned long cs_bit;
+       unsigned long val;
+       unsigned long flags;
+
+       dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+               spi->bits_per_word,
+               spi->mode & SPI_CPOL ? "" : "~",
+               spi->mode & SPI_CPHA ? "" : "~",
+               spi->max_speed_hz);
+
+
+       switch (spi->chip_select) {
+       case 0:
+               cs_bit = SLINK_CS_POLARITY;
+               break;
+
+       case 1:
+               cs_bit = SLINK_CS_POLARITY1;
+               break;
+
+       case 2:
+               cs_bit = SLINK_CS_POLARITY2;
+               break;
+
+       case 4:
+               cs_bit = SLINK_CS_POLARITY3;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       if (spi->mode & SPI_CS_HIGH)
+               val |= cs_bit;
+       else
+               val &= ~cs_bit;
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+
+       return 0;
+}
+
+static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       struct spi_transfer *t;
+       unsigned long flags;
+       int was_empty;
+
+       if (list_empty(&m->transfers) || !m->complete)
+               return -EINVAL;
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->bits_per_word < 0 || t->bits_per_word > 32)
+                       return -EINVAL;
+
+               if (t->len == 0)
+                       return -EINVAL;
+
+               if (!t->rx_buf && !t->tx_buf)
+                       return -EINVAL;
+       }
+
+       m->state = spi;
+
+       spin_lock_irqsave(&tspi->lock, flags);
+       was_empty = list_empty(&tspi->queue);
+       list_add_tail(&m->queue, &tspi->queue);
+
+       if (was_empty)
+               spi_tegra_start_message(spi, m);
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+
+       return 0;
+}
+
+static int __init spi_tegra_probe(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct spi_tegra_data   *tspi;
+       struct resource         *r;
+       int ret;
+
+       master = spi_alloc_master(&pdev->dev, sizeof *tspi);
+       if (master == NULL) {
+               dev_err(&pdev->dev, "master allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+       master->bus_num = pdev->id;
+
+       master->setup = spi_tegra_setup;
+       master->transfer = spi_tegra_transfer;
+       master->num_chipselect = 4;
+
+       dev_set_drvdata(&pdev->dev, master);
+       tspi = spi_master_get_devdata(master);
+       tspi->master = master;
+       tspi->pdev = pdev;
+       spin_lock_init(&tspi->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
+       if (!request_mem_region(r->start, (r->end - r->start) + 1,
+                               dev_name(&pdev->dev))) {
+               ret = -EBUSY;
+               goto err0;
+       }
+
+       tspi->phys = r->start;
+       tspi->base = ioremap(r->start, r->end - r->start + 1);
+       if (!tspi->base) {
+               dev_err(&pdev->dev, "can't ioremap iomem\n");
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       tspi->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR_OR_NULL(tspi->clk)) {
+               dev_err(&pdev->dev, "can not get clock\n");
+               ret = PTR_ERR(tspi->clk);
+               goto err2;
+       }
+
+       INIT_LIST_HEAD(&tspi->queue);
+
+       tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
+       if (!tspi->rx_dma) {
+               dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+               ret = -ENODEV;
+               goto err3;
+       }
+
+       tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                                        &tspi->rx_bb_phys, GFP_KERNEL);
+       if (!tspi->rx_bb) {
+               dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
+               ret = -ENOMEM;
+               goto err4;
+       }
+
+       tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
+       tspi->rx_dma_req.to_memory = 1;
+       tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
+       tspi->rx_dma_req.dest_bus_width = 32;
+       tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
+       tspi->rx_dma_req.source_bus_width = 32;
+       tspi->rx_dma_req.source_wrap = 4;
+       tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
+       tspi->rx_dma_req.dev = tspi;
+
+       ret = spi_register_master(master);
+
+       if (ret < 0)
+               goto err5;
+
+       return ret;
+
+err5:
+       dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                         tspi->rx_bb, tspi->rx_bb_phys);
+err4:
+       tegra_dma_free_channel(tspi->rx_dma);
+err3:
+       clk_put(tspi->clk);
+err2:
+       iounmap(tspi->base);
+err1:
+       release_mem_region(r->start, (r->end - r->start) + 1);
+err0:
+       spi_master_put(master);
+       return ret;
+}
+
+static int __devexit spi_tegra_remove(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct spi_tegra_data   *tspi;
+       struct resource         *r;
+
+       master = dev_get_drvdata(&pdev->dev);
+       tspi = spi_master_get_devdata(master);
+
+       tegra_dma_free_channel(tspi->rx_dma);
+
+       dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                         tspi->rx_bb, tspi->rx_bb_phys);
+
+       clk_put(tspi->clk);
+       iounmap(tspi->base);
+
+       spi_master_put(master);
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(r->start, (r->end - r->start) + 1);
+
+       return 0;
+}
+
+MODULE_ALIAS("platform:spi_tegra");
+
+static struct platform_driver spi_tegra_driver = {
+       .driver = {
+               .name =         "spi_tegra",
+               .owner =        THIS_MODULE,
+       },
+       .remove =       __devexit_p(spi_tegra_remove),
+};
+
+static int __init spi_tegra_init(void)
+{
+       return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
+}
+module_init(spi_tegra_init);
+
+static void __exit spi_tegra_exit(void)
+{
+       platform_driver_unregister(&spi_tegra_driver);
+}
+module_exit(spi_tegra_exit);
+
+MODULE_LICENSE("GPL");
index 335311a..8e03e76 100644 (file)
@@ -139,8 +139,6 @@ source "drivers/staging/adis16255/Kconfig"
 
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/mrst-touchscreen/Kconfig"
-
 source "drivers/staging/msm/Kconfig"
 
 source "drivers/staging/lirc/Kconfig"
index e3f1e1b..0e7d755 100644 (file)
@@ -51,7 +51,6 @@ obj-$(CONFIG_CXT1E1)          += cxt1e1/
 obj-$(CONFIG_TI_ST)            += ti-st/
 obj-$(CONFIG_ADIS16255)                += adis16255/
 obj-$(CONFIG_FB_XGI)           += xgifb/
-obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)     += mrst-touchscreen/
 obj-$(CONFIG_MSM_STAGING)      += msm/
 obj-$(CONFIG_EASYCAP)          += easycap/
 obj-$(CONFIG_SOLO6X10)         += solo6x10/
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
deleted file mode 100644 (file)
index c2af492..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-config TOUCHSCREEN_INTEL_MID
-       tristate "Intel MID platform resistive touchscreen"
-       depends on INTEL_SCU_IPC
-       default y
-       help
-         Say Y here if you have a Intel MID based touchscreen
-         If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
deleted file mode 100644 (file)
index 2d638b0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
-
-
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
deleted file mode 100644 (file)
index 7157028..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-- Move the driver to not think it is SPI (requires fixing some of the SFI
-  and firmware side)
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
deleted file mode 100644 (file)
index abba22f..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
- *
- * Copyright (C) 2008 Intel Corp
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; ifnot, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
- *                         Ramesh Agarwal (ramesh.agarwal@intel.com)
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * TODO:
- *     kill off mrstouch_debug eventually
- *     review conversion of r/m/w sequences
- *     Replace interrupt mutex abuse
- *     Kill of mrstouchdevp pointer
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/param.h>
-#include <linux/spi/spi.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/intel_scu_ipc.h>
-
-
-#if defined(MRSTOUCH_DEBUG)
-#define mrstouch_debug(fmt, args...)\
-       do { \
-               printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
-               printk(KERN_DEBUG fmt, ##args); \
-       } while (0);
-#else
-#define mrstouch_debug(fmt, args...)
-#endif
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_ID1   0x00 /*PMIC ID1 register */
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_INT   0x04 /*PMIC interrupt register */
-#define PMIC_REG_MINT  0x05 /*PMIC interrupt mask register */
-
-/* ADC Interrupt registers */
-#define PMIC_REG_ADCINT   0x5F /*ADC interrupt register */
-#define PMIC_REG_MADCINT  0x60 /*ADC interrupt mask register */
-
-/* ADC Control registers */
-#define PMIC_REG_ADCCNTL1    0x61 /*ADC control register */
-
-/* ADC Channel Selection registers */
-#define PMICADDR0     0xA4
-#define END_OF_CHANNEL 0x1F
-
-/* ADC Result register */
-#define PMIC_REG_ADCSNS0H   0x64
-
-/* ADC channels for touch screen */
-#define MRST_TS_CHAN10   0xA /* Touch screen X+ connection */
-#define MRST_TS_CHAN11   0xB /* Touch screen X- connection */
-#define MRST_TS_CHAN12   0xC /* Touch screen Y+ connection */
-#define MRST_TS_CHAN13   0xD /* Touch screen Y- connection */
-
-/* Touch screen coordinate constants */
-#define TOUCH_PRESSURE         50
-#define TOUCH_PRESSURE_FS      100
-
-#define XMOVE_LIMIT    5
-#define YMOVE_LIMIT    5
-#define XYMOVE_CNT     3
-
-#define MAX_10BIT      ((1<<10)-1)
-
-/* Touch screen channel BIAS constants */
-#define XBIAS          0x20
-#define YBIAS          0x40
-#define ZBIAS          0x80
-
-/* Touch screen coordinates */
-#define MIN_X          10
-#define MAX_X          1024
-#define MIN_Y          10
-#define MAX_Y          1024
-#define WAIT_ADC_COMPLETION 10
-
-/* PMIC ADC round robin delays */
-#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
-#define ADC_LOOP_DELAY1 0x1 /* 4.5  ms approximate */
-
-/* PMIC Vendor Identifiers */
-#define PMIC_VENDOR_FS  0 /* PMIC vendor FreeScale */
-#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
-#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
-#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
-
-/* Touch screen device structure */
-struct mrstouch_dev {
-       struct spi_device *spi; /* SPI device associated with touch screen */
-       struct input_dev *input; /* input device for touchscreen*/
-       char            phys[32]; /* Device name */
-       struct task_struct *pendet_thrd; /* PENDET interrupt handler */
-       struct mutex lock; /* Sync between interrupt and PENDET handler */
-       bool            busy; /* Busy flag */
-       u16             asr; /* Address selection register */
-       int             irq;    /* Touch screen IRQ # */
-       uint            vendor;  /* PMIC vendor */
-       uint            rev;  /* PMIC revision */
-       bool            suspended; /* Device suspended status */
-       bool            disabled;  /* Device disabled status */
-       u16             x;  /* X coordinate */
-       u16             y;  /* Y coordinate */
-       bool            pendown;  /* PEN position */
-} ;
-
-
-/* Global Pointer to Touch screen device */
-static struct mrstouch_dev *mrstouchdevp;
-
-/* Utility to read PMIC ID */
-static int mrstouch_pmic_id(uint *vendor, uint *rev)
-{
-       int err;
-       u8 r;
-
-       err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
-       if (err)
-               return err;
-
-       *vendor = r & 0x7;
-       *rev = (r >> 3) & 0x7;
-
-       return 0;
-}
-
-/*
- * Parse ADC channels to find end of the channel configured by other ADC user
- * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
- */
-static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
-{
-       int err, i, j, found;
-       u32 r32;
-
-       found = -1;
-
-       for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
-               if (found >= 0)
-                       break;
-
-               err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
-               if (err)
-                       return err;
-
-               for (j = 0; j < 32; j+= 8) {
-                       if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
-                               found = i;
-                               break;
-                       }
-               }
-       }
-       if (found < 0)
-               return 0;
-
-       if (tsdev->vendor == PMIC_VENDOR_FS) {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
-                       return -ENOSPC;
-       } else {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
-                       return -ENOSPC;
-       }
-       return found;
-}
-
-/* Utility to enable/disable pendet.
- * pendet set to true enables PENDET interrupt
- * pendet set to false disables PENDET interrupt
- * Also clears RND mask bit
-*/
-static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
-{
-       u16 reg;
-       u8 r;
-       u8 pendet_enabled = 0;
-       int retry = 0;
-       int err;
-
-       err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
-       if (err)
-               return err;
-
-       if (pendet) {
-               reg &= ~0x0005;
-               reg |= 0x2000; /* Enable pendet */
-       } else
-               reg &= 0xDFFF; /* Disable pendet */
-
-       /* Set MADCINT and update ADCCNTL1 (next reg byte) */
-       err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
-       if (!pendet || err)
-               return err;
-
-       /*
-        * Sometimes even after the register write succeeds
-        * the PMIC register value is not updated. Retry few iterations
-        * to enable pendet.
-        */
-
-       err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-       pendet_enabled = (r >> 5) & 0x01;
-
-       retry = 0;
-       while (!err && !pendet_enabled) {
-               retry++;
-               msleep(10);
-               err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
-               if (err)
-                       break;
-               err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-               if (err == 0)
-                       pendet_enabled = (r >> 5) & 0x01;
-               if (retry >= 10) {
-                       dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-/* To read PMIC ADC touch screen result
- * Reads ADC storage registers for higher 7 and lower 3 bits
- * converts the two readings to single value and turns off gain bit
- */
-static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
-{
-       int err;
-       u16 result;
-       u32 res;
-
-       result = PMIC_REG_ADCSNS0H + offset;
-
-       if (chan == MRST_TS_CHAN12)
-               result += 4;
-
-       err = intel_scu_ipc_ioread32(result, &res);
-       if (err)
-               return err;
-
-       /* Mash the bits up */
-
-       *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
-       *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
-       *vp &= 0x3FF;
-
-       res >>= 16;
-
-       *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
-       *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
-       *vm &= 0x3FF;
-
-       return 0;
-}
-
-/* To configure touch screen channels
- * Writes touch screen channels to ADC address selection registers
- */
-static int mrstouch_ts_chan_set(uint offset)
-{
-       int count;
-       u16 chan;
-       u16 reg[5];
-       u8 data[5];
-
-       chan = PMICADDR0 + offset;
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = MRST_TS_CHAN10 + count;
-       }
-       reg[count] = chan;
-       data[count] = END_OF_CHANNEL;
-
-       return intel_scu_ipc_writev(reg, data, 5);
-}
-
-/* Initialize ADC */
-static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
-{
-       int err, start;
-       u8 ra, rm;
-
-       err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
-               return err;
-       }
-
-       start = mrstouch_chan_parse(tsdev);
-       if (start < 0) {
-               dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
-               return start;
-       }
-
-       tsdev->asr = start;
-
-       mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
-
-       /* ADC power on, start, enable PENDET and set loop delay
-        * ADC loop delay is set to 4.5 ms approximately
-        * Loop delay more than this results in jitter in adc readings
-        * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
-        * interrupt generation sometimes.
-        */
-
-       if (tsdev->vendor == PMIC_VENDOR_FS) {
-               ra = 0xE0 | ADC_LOOP_DELAY0;
-               rm = 0x5;
-       } else {
-               /* NEC and MAXIm not consistent with loop delay 0 */
-               ra = 0xE0 | ADC_LOOP_DELAY1;
-               rm = 0x0;
-
-               /* configure touch screen channels */
-               err = mrstouch_ts_chan_set(tsdev->asr);
-               if (err)
-                       return err;
-       }
-       err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
-       if (err == 0)
-               err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
-       return err;
-}
-
-/* Reports x,y coordinates to event subsystem */
-static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
-{
-       int xdiff, ydiff;
-
-       if (tsdev->pendown && z <= TOUCH_PRESSURE) {
-               /* Pen removed, report button release */
-               mrstouch_debug("BTN REL(%d)", z);
-               input_report_key(tsdev->input, BTN_TOUCH, 0);
-               tsdev->pendown = false;
-       }
-
-       xdiff = abs(x - tsdev->x);
-       ydiff = abs(y - tsdev->y);
-
-       /*
-       if x and y values changes for XYMOVE_CNT readings it is considered
-       as stylus is moving. This is required to differentiate between stylus
-       movement and jitter
-       */
-       if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
-               /* Spurious values, release button if touched and return */
-               if (tsdev->pendown) {
-                       mrstouch_debug("BTN REL(%d)", z);
-                       input_report_key(tsdev->input, BTN_TOUCH, 0);
-                       tsdev->pendown = false;
-               }
-               return;
-       } else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
-               tsdev->x = x;
-               tsdev->y = y;
-
-               input_report_abs(tsdev->input, ABS_X, x);
-               input_report_abs(tsdev->input, ABS_Y, y);
-               input_sync(tsdev->input);
-       }
-
-
-       if (!tsdev->pendown && z > TOUCH_PRESSURE) {
-               /* Pen touched, report button touch */
-               mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
-               input_report_key(tsdev->input, BTN_TOUCH, 1);
-               tsdev->pendown = true;
-       }
-}
-
-
-/* Utility to start ADC, used by freescale handler */
-static int pendet_mask(void)
-{
-       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
-}
-
-/* Utility to stop ADC, used by freescale handler */
-static int pendet_umask(void)
-{
-       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
-}
-
-/* Utility to read ADC, used by freescale handler */
-static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
-{
-       int err;
-       u16 x, y, z, result;
-       u16 reg[4];
-       u8 data[4];
-
-       result = PMIC_REG_ADCSNS0H + tsdev->asr;
-
-       reg[0] = result + 4;
-       reg[1] = result + 5;
-       reg[2] = result + 16;
-       reg[3] = result + 17;
-
-       err = intel_scu_ipc_readv(reg, data, 4);
-       if (err)
-               goto ipc_error;
-
-       x = data[0] << 3; /* Higher 7 bits */
-       x |= data[1] & 0x7; /* Lower 3 bits */
-       x &= 0x3FF;
-
-       y = data[2] << 3; /* Higher 7 bits */
-       y |= data[3] & 0x7; /* Lower 3 bits */
-       y &= 0x3FF;
-
-       /* Read Z value */
-       reg[0] = result + 28;
-       reg[1] = result + 29;
-
-       err = intel_scu_ipc_readv(reg, data, 4);
-       if (err)
-               goto ipc_error;
-
-       z = data[0] << 3; /* Higher 7 bits */
-       z |= data[1] & 0x7; /* Lower 3 bits */
-       z &= 0x3FF;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-       mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
-#endif
-
-       if (z >= TOUCH_PRESSURE_FS) {
-               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
-               return TOUCH_PRESSURE - 1;
-       } else {
-               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
-               return TOUCH_PRESSURE + 1;
-       }
-
-       return 0;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
-       return err;
-}
-
-/* To handle free scale pmic pendet interrupt */
-static int pmic0_pendet(void *dev_id)
-{
-       int err, count;
-       u16 chan;
-       unsigned int touched;
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
-       u16 reg[5];
-       u8 data[5];
-
-       chan = PMICADDR0 + tsdev->asr;
-
-       /* Set X BIAS */
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = 0x2A;
-       }
-       reg[count] =  chan++; /* Dummy */
-       data[count] = 0;
-
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* Set Y BIAS */
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = 0x4A;
-       }
-       reg[count] = chan++; /* Dummy */
-       data[count] = 0;
-
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* Set Z BIAS */
-       err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /*Read touch screen channels till pen removed
-        * Freescale reports constant value of z for all points
-        * z is high when screen is not touched and low when touched
-        * Map high z value to not touched and low z value to pen touched
-        */
-       touched = mrstouch_pmic_fs_adc_read(tsdev);
-       while (touched > TOUCH_PRESSURE) {
-               touched = mrstouch_pmic_fs_adc_read(tsdev);
-               msleep(WAIT_ADC_COMPLETION);
-       }
-
-       /* Clear all TS channels */
-       chan = PMICADDR0 + tsdev->asr;
-       for (count = 0; count <= 4; count++) {
-               reg[count] = chan++;
-               data[count] = 0;
-       }
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       for (count = 0; count <= 4; count++) {
-               reg[count] = chan++;
-               data[count] = 0;
-       }
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
-       if (err)
-               goto ipc_error;
-
-       return 0;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
-       return err;
-}
-
-
-/* To enable X, Y and Z bias values
- * Enables YPYM for X channels and XPXM for Y channels
- */
-static int mrstouch_ts_bias_set(uint offset, uint bias)
-{
-       int count;
-       u16 chan, start;
-       u16 reg[4];
-       u8 data[4];
-
-       chan = PMICADDR0 + offset;
-       start = MRST_TS_CHAN10;
-
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = bias | (start + count);
-       }
-       return intel_scu_ipc_writev(reg, data, 4);
-}
-
-/* To read touch screen channel values */
-static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
-{
-       int err;
-       u16 xp, xm, yp, ym, zp, zm;
-
-       /* configure Y bias for X channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read x+ and x- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
-       if (err)
-               goto ipc_error;
-
-       /* configure x bias for y channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read y+ and y- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
-       if (err)
-               goto ipc_error;
-
-       /* configure z bias for x and y channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read z+ and z- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
-       if (err)
-               goto ipc_error;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-       printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
-#endif
-
-#if defined(MRSTOUCH_PRINT_XYZM)
-       printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
-#endif
-
-       mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
-
-       return zp;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
-       return err;
-}
-
-/* PENDET interrupt handler function for NEC and MAXIM */
-static void pmic12_pendet(void *data)
-{
-       unsigned int touched;
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-
-       /* read touch screen channels till pen removed */
-       do {
-               touched = mrstouch_adc_read(tsdev);
-       } while (touched > TOUCH_PRESSURE);
-}
-
-/* Handler to process PENDET interrupt */
-int mrstouch_pendet(void *data)
-{
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-       while (1) {
-               /* Wait for PENDET interrupt */
-               if (mutex_lock_interruptible(&tsdev->lock)) {
-                       msleep(WAIT_ADC_COMPLETION);
-                       continue;
-               }
-
-               if (tsdev->busy)
-                       return 0;
-
-               tsdev->busy = true;
-
-               if (tsdev->vendor == PMIC_VENDOR_NEC ||
-                       tsdev->vendor == PMIC_VENDOR_MAXIM) {
-                       /* PENDET must be disabled in NEC before reading ADC */
-                       pendet_enable(tsdev,false); /* Disbale PENDET */
-                       pmic12_pendet(tsdev);
-                       pendet_enable(tsdev, true); /*Enable PENDET */
-               } else if (tsdev->vendor == PMIC_VENDOR_FS) {
-                       pendet_umask(); /* Stop ADC */
-                       pmic0_pendet(tsdev);
-                       pendet_mask(); /* Stop ADC */
-               } else
-               dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
-                               tsdev->vendor);
-
-               tsdev->busy = false;
-
-       }
-       return 0;
-}
-
-/* PENDET interrupt handler */
-static irqreturn_t pendet_intr_handler(int irq, void *handle)
-{
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
-
-       mutex_unlock(&tsdev->lock);
-       return IRQ_HANDLED;
-}
-
-/* Intializes input device and registers with input subsystem */
-static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
-{
-       int err = 0;
-
-       mrstouch_debug("%s", __func__);
-
-       tsdev->input = input_allocate_device();
-       if (!tsdev->input) {
-               dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
-               return -EINVAL;
-       }
-
-       tsdev->input->name = "mrst_touchscreen";
-       snprintf(tsdev->phys, sizeof(tsdev->phys),
-                       "%s/input0", dev_name(&spi->dev));
-       tsdev->input->phys = tsdev->phys;
-       tsdev->input->dev.parent = &spi->dev;
-
-       tsdev->input->id.vendor = tsdev->vendor;
-       tsdev->input->id.version = tsdev->rev;
-
-       tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-       input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
-       input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
-
-       err = input_register_device(tsdev->input);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "unable to register input device\n");
-               input_free_device(tsdev->input);
-               return err;
-       }
-
-       mrstouch_debug("%s", "mrstouch initialized");
-
-       return 0;
-
-}
-
-/* Probe function for touch screen driver */
-static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
-{
-       int err;
-       unsigned int myirq;
-       struct mrstouch_dev *tsdev;
-
-       mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
-
-       mrstouchdevp = NULL;
-       myirq = mrstouch_spi->irq;
-
-       if (!mrstouch_spi->irq) {
-               dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
-               return -EINVAL;
-       }
-
-       tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
-       if (!tsdev) {
-               dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
-               return -ENOMEM;
-       }
-
-       tsdev->irq = myirq;
-       mrstouchdevp = tsdev;
-
-       err = mrstouch_adc_init(tsdev);
-       if (err) {
-               dev_err(&mrstouch_spi->dev, "ADC init failed\n");
-               goto mrstouch_err_free_mem;
-       }
-
-       dev_set_drvdata(&mrstouch_spi->dev, tsdev);
-       tsdev->spi = mrstouch_spi;
-
-       err = ts_input_dev_init(tsdev, mrstouch_spi);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
-               goto mrstouch_err_free_mem;
-       }
-
-       mutex_init(&tsdev->lock);
-       mutex_lock(&tsdev->lock)
-
-       mrstouch_debug("Requesting IRQ-%d", myirq);
-       err = request_irq(myirq, pendet_intr_handler,
-                               0, "mrstouch", tsdev);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
-               goto mrstouch_err_free_mem;
-       }
-
-       tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
-                               (void *)tsdev, "pendet handler");
-       if (IS_ERR(tsdev->pendet_thrd)) {
-               dev_err(&tsdev->spi->dev, "kthread_run failed\n");
-               err = PTR_ERR(tsdev->pendet_thrd);
-               goto mrstouch_err_free_mem;
-       }
-       mrstouch_debug("%s", "Driver initialized");
-       return 0;
-
-mrstouch_err_free_mem:
-       kfree(tsdev);
-       return err;
-}
-
-static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
-{
-       mrstouch_debug("%s", __func__);
-       mrstouchdevp->suspended = 1;
-       return 0;
-}
-
-static int mrstouch_resume(struct spi_device *spi)
-{
-       mrstouch_debug("%s", __func__);
-       mrstouchdevp->suspended = 0;
-       return 0;
-}
-
-static int mrstouch_remove(struct spi_device *spi)
-{
-       mrstouch_debug("%s", __func__);
-       free_irq(mrstouchdevp->irq, mrstouchdevp);
-       input_unregister_device(mrstouchdevp->input);
-       input_free_device(mrstouchdevp->input);
-       if (mrstouchdevp->pendet_thrd)
-               kthread_stop(mrstouchdevp->pendet_thrd);
-       kfree(mrstouchdevp);
-       return 0;
-}
-
-static struct spi_driver mrstouch_driver = {
-       .driver = {
-               .name   = "pmic_touch",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = mrstouch_probe,
-       .suspend        = mrstouch_suspend,
-       .resume         = mrstouch_resume,
-       .remove         = mrstouch_remove,
-};
-
-static int __init mrstouch_module_init(void)
-{
-       int err;
-
-       mrstouch_debug("%s", __func__);
-       err = spi_register_driver(&mrstouch_driver);
-       if (err) {
-               mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
-               return -1;
-       }
-
-       return 0;
-}
-
-static void __exit mrstouch_module_exit(void)
-{
-       mrstouch_debug("%s", __func__);
-       spi_unregister_driver(&mrstouch_driver);
-       return;
-}
-
-module_init(mrstouch_module_init);
-module_exit(mrstouch_module_exit);
-
-MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
-MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
-MODULE_LICENSE("GPL");
index 7d71019..c85ff5e 100644 (file)
@@ -12,4 +12,4 @@ TODO:
 - get rid of non-linux related stuff
 
 Please send patches to:
-Arnaud Patard <apatard@mandriva.com>
+Arnaud Patard <arnaud.patard@rtp-net.org>
index 61d3ca6..cb5cd42 100644 (file)
@@ -54,7 +54,6 @@
 
 #include <plat/dma.h>
 #include <plat/usb.h>
-#include <plat/control.h>
 
 #include "omap_udc.h"
 
@@ -2309,21 +2308,12 @@ static char *trx_mode(unsigned m, int enabled)
 static int proc_otg_show(struct seq_file *s)
 {
        u32             tmp;
-       u32             trans;
-       char            *ctrl_name;
+       u32             trans = 0;
+       char            *ctrl_name = "(UNKNOWN)";
 
+       /* XXX This needs major revision for OMAP2+ */
        tmp = omap_readl(OTG_REV);
-       if (cpu_is_omap24xx()) {
-               /*
-                * REVISIT: Not clear how this works on OMAP2.  trans
-                * is ANDed to produce bits 7 and 8, which might make
-                * sense for USB_TRANSCEIVER_CTRL on OMAP1,
-                * but with CONTROL_DEVCONF, these bits have something to
-                * do with the frame adjustment counter and McBSP2.
-                */
-               ctrl_name = "control_devconf";
-               trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       } else {
+       if (cpu_class_is_omap1()) {
                ctrl_name = "tranceiver_ctrl";
                trans = omap_readw(USB_TRANSCEIVER_CTRL);
        }
index 77be3c2..3076b1c 100644 (file)
@@ -2397,7 +2397,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
 #define R8A66597_DEV_PM_OPS    NULL
 #endif
 
-static int __init_or_module r8a66597_remove(struct platform_device *pdev)
+static int __devexit r8a66597_remove(struct platform_device *pdev)
 {
        struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
        struct usb_hcd          *hcd = r8a66597_to_hcd(r8a66597);
@@ -2542,7 +2542,7 @@ clean_up:
 
 static struct platform_driver r8a66597_driver = {
        .probe =        r8a66597_probe,
-       .remove =       r8a66597_remove,
+       .remove =       __devexit_p(r8a66597_remove),
        .driver         = {
                .name = (char *) hcd_name,
                .owner  = THIS_MODULE,
index bac8e7a..d100f54 100644 (file)
@@ -12,8 +12,7 @@ menuconfig UWB
          technology using a wide spectrum (3.1-10.6GHz). It is
          optimized for in-room use (480Mbps at 2 meters, 110Mbps at
          10m). It serves as the transport layer for other protocols,
-         such as Wireless USB (WUSB), IP (WLP) and upcoming
-         Bluetooth and 1394
+         such as Wireless USB (WUSB).
 
          The topology is peer to peer; however, higher level
          protocols (such as WUSB) might impose a master/slave
@@ -58,13 +57,6 @@ config UWB_WHCI
           To compile this driver select Y (built in) or M (module). It
           is safe to select any even if you do not have the hardware.
 
-config UWB_WLP
-       tristate "Support WiMedia Link Protocol (Ethernet/IP over UWB)"
-       depends on UWB && NET
-       help
-         This is a common library for drivers that implement
-         networking over UWB.
-
 config UWB_I1480U
         tristate "Support for Intel Wireless UWB Link 1480 HWA"
         depends on UWB_HWA
@@ -77,14 +69,4 @@ config UWB_I1480U
          To compile this driver select Y (built in) or M (module). It
          is safe to select any even if you do not have the hardware.
 
-config UWB_I1480U_WLP
-        tristate "Support for Intel Wireless UWB Link 1480 HWA's WLP interface"
-        depends on UWB_I1480U &&  UWB_WLP && NET
-        help
-         This driver enables WLP support for the i1480 when connected via
-         USB. WLP is the WiMedia Link Protocol, or IP over UWB.
-
-         To compile this driver select Y (built in) or M (module). It
-         is safe to select any even if you don't have the hardware.
-
 endif # UWB
index 2f98d08..d47dd6e 100644 (file)
@@ -1,5 +1,4 @@
 obj-$(CONFIG_UWB)              += uwb.o
-obj-$(CONFIG_UWB_WLP)          += wlp/
 obj-$(CONFIG_UWB_WHCI)         += umc.o whci.o whc-rc.o
 obj-$(CONFIG_UWB_HWA)          += hwa-rc.o
 obj-$(CONFIG_UWB_I1480U)       += i1480/
index 212bbc7..d69da16 100644 (file)
@@ -1,2 +1 @@
 obj-$(CONFIG_UWB_I1480U)       += dfu/ i1480-est.o
-obj-$(CONFIG_UWB_I1480U_WLP)   += i1480u-wlp/
diff --git a/drivers/uwb/i1480/i1480-wlp.h b/drivers/uwb/i1480/i1480-wlp.h
deleted file mode 100644 (file)
index 18a8b0e..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Intel 1480 Wireless UWB Link
- * WLP specific definitions
- *
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- */
-
-#ifndef __i1480_wlp_h__
-#define __i1480_wlp_h__
-
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/uwb.h>
-#include <linux/if_ether.h>
-#include <asm/byteorder.h>
-
-/* New simplified header format? */
-#undef WLP_HDR_FMT_2           /* FIXME: rename */
-
-/**
- * Values of the Delivery ID & Type field when PCA or DRP
- *
- * The Delivery ID & Type field in the WLP TX header indicates whether
- * the frame is PCA or DRP. This is done based on the high level bit of
- * this field.
- * We use this constant to test if the traffic is PCA or DRP as follows:
- * if (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)
- *     this is DRP traffic
- * else
- *     this is PCA traffic
- */
-enum deliver_id_type_bit {
-       WLP_DRP = 8,
-};
-
-/**
- * WLP TX header
- *
- * Indicates UWB/WLP-specific transmission parameters for a network
- * packet.
- */
-struct wlp_tx_hdr {
-       /* dword 0 */
-       struct uwb_dev_addr dstaddr;
-       u8                  key_index;
-       u8                  mac_params;
-       /* dword 1 */
-       u8                  phy_params;
-#ifndef WLP_HDR_FMT_2
-       u8                  reserved;
-       __le16              oui01;              /* FIXME: not so sure if __le16 or u8[2] */
-       /* dword 2 */
-       u8                  oui2;               /*        if all LE, it could be merged */
-       __le16              prid;
-#endif
-} __attribute__((packed));
-
-static inline int wlp_tx_hdr_delivery_id_type(const struct wlp_tx_hdr *hdr)
-{
-       return hdr->mac_params & 0x0f;
-}
-
-static inline int wlp_tx_hdr_ack_policy(const struct wlp_tx_hdr *hdr)
-{
-       return (hdr->mac_params >> 4) & 0x07;
-}
-
-static inline int wlp_tx_hdr_rts_cts(const struct wlp_tx_hdr *hdr)
-{
-       return (hdr->mac_params >> 7) & 0x01;
-}
-
-static inline void wlp_tx_hdr_set_delivery_id_type(struct wlp_tx_hdr *hdr, int id)
-{
-       hdr->mac_params = (hdr->mac_params & ~0x0f) | id;
-}
-
-static inline void wlp_tx_hdr_set_ack_policy(struct wlp_tx_hdr *hdr,
-                                            enum uwb_ack_pol policy)
-{
-       hdr->mac_params = (hdr->mac_params & ~0x70) | (policy << 4);
-}
-
-static inline void wlp_tx_hdr_set_rts_cts(struct wlp_tx_hdr *hdr, int rts_cts)
-{
-       hdr->mac_params = (hdr->mac_params & ~0x80) | (rts_cts << 7);
-}
-
-static inline enum uwb_phy_rate wlp_tx_hdr_phy_rate(const struct wlp_tx_hdr *hdr)
-{
-       return hdr->phy_params & 0x0f;
-}
-
-static inline int wlp_tx_hdr_tx_power(const struct wlp_tx_hdr *hdr)
-{
-       return (hdr->phy_params >> 4) & 0x0f;
-}
-
-static inline void wlp_tx_hdr_set_phy_rate(struct wlp_tx_hdr *hdr, enum uwb_phy_rate rate)
-{
-       hdr->phy_params = (hdr->phy_params & ~0x0f) | rate;
-}
-
-static inline void wlp_tx_hdr_set_tx_power(struct wlp_tx_hdr *hdr, int pwr)
-{
-       hdr->phy_params = (hdr->phy_params & ~0xf0) | (pwr << 4);
-}
-
-
-/**
- * WLP RX header
- *
- * Provides UWB/WLP-specific transmission data for a received
- * network packet.
- */
-struct wlp_rx_hdr {
-       /* dword 0 */
-       struct uwb_dev_addr dstaddr;
-       struct uwb_dev_addr srcaddr;
-       /* dword 1 */
-       u8                  LQI;
-       s8                  RSSI;
-       u8                  reserved3;
-#ifndef WLP_HDR_FMT_2
-       u8                  oui0;
-       /* dword 2 */
-       __le16              oui12;
-       __le16              prid;
-#endif
-} __attribute__((packed));
-
-
-/** User configurable options for WLP */
-struct wlp_options {
-       struct mutex mutex; /* access to user configurable options*/
-       struct wlp_tx_hdr def_tx_hdr;   /* default tx hdr */
-       u8 pca_base_priority;
-       u8 bw_alloc; /*index into bw_allocs[] for PCA/DRP reservations*/
-};
-
-
-static inline
-void wlp_options_init(struct wlp_options *options)
-{
-       mutex_init(&options->mutex);
-       wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, UWB_ACK_INM);
-       wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, 1);
-       /* FIXME: default to phy caps */
-       wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, UWB_PHY_RATE_480);
-#ifndef WLP_HDR_FMT_2
-       options->def_tx_hdr.prid = cpu_to_le16(0x0000);
-#endif
-}
-
-
-/* sysfs helpers */
-
-extern ssize_t uwb_pca_base_priority_store(struct wlp_options *,
-                                          const char *, size_t);
-extern ssize_t uwb_pca_base_priority_show(const struct wlp_options *, char *);
-extern ssize_t uwb_bw_alloc_store(struct wlp_options *, const char *, size_t);
-extern ssize_t uwb_bw_alloc_show(const struct wlp_options *, char *);
-extern ssize_t uwb_ack_policy_store(struct wlp_options *,
-                                   const char *, size_t);
-extern ssize_t uwb_ack_policy_show(const struct wlp_options *, char *);
-extern ssize_t uwb_rts_cts_store(struct wlp_options *, const char *, size_t);
-extern ssize_t uwb_rts_cts_show(const struct wlp_options *, char *);
-extern ssize_t uwb_phy_rate_store(struct wlp_options *, const char *, size_t);
-extern ssize_t uwb_phy_rate_show(const struct wlp_options *, char *);
-
-
-/** Simple bandwidth allocation (temporary and too simple) */
-struct wlp_bw_allocs {
-       const char *name;
-       struct {
-               u8 mask, stream;
-       } tx, rx;
-};
-
-
-#endif /* #ifndef __i1480_wlp_h__ */
diff --git a/drivers/uwb/i1480/i1480u-wlp/Makefile b/drivers/uwb/i1480/i1480u-wlp/Makefile
deleted file mode 100644 (file)
index fe6709b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-obj-$(CONFIG_UWB_I1480U_WLP) += i1480u-wlp.o
-
-i1480u-wlp-objs :=     \
-       lc.o            \
-       netdev.o        \
-       rx.o            \
-       sysfs.o         \
-       tx.o
diff --git a/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h b/drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h
deleted file mode 100644 (file)
index 2e31f53..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Intel 1480 Wireless UWB Link USB
- * Header formats, constants, general internal interfaces
- *
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * This is not an standard interface.
- *
- * FIXME: docs
- *
- * i1480u-wlp is pretty simple: two endpoints, one for tx, one for
- * rx. rx is polled. Network packets (ethernet, whatever) are wrapped
- * in i1480 TX or RX headers (for sending over the air), and these
- * packets are wrapped in UNTD headers (for sending to the WLP UWB
- * controller).
- *
- * UNTD packets (UNTD hdr + i1480 hdr + network packet) packets
- * cannot be bigger than i1480u_MAX_FRG_SIZE. When this happens, the
- * i1480 packet is broken in chunks/packets:
- *
- * UNTD-1st.hdr + i1480.hdr + payload
- * UNTD-next.hdr + payload
- * ...
- * UNTD-last.hdr + payload
- *
- * so that each packet is smaller or equal than i1480u_MAX_FRG_SIZE.
- *
- * All HW structures and bitmaps are little endian, so we need to play
- * ugly tricks when defining bitfields. Hoping for the day GCC
- * implements __attribute__((endian(1234))).
- *
- * FIXME: ROADMAP to the whole implementation
- */
-
-#ifndef __i1480u_wlp_h__
-#define __i1480u_wlp_h__
-
-#include <linux/usb.h>
-#include <linux/netdevice.h>
-#include <linux/uwb.h>         /* struct uwb_rc, struct uwb_notifs_handler */
-#include <linux/wlp.h>
-#include "../i1480-wlp.h"
-
-#undef i1480u_FLOW_CONTROL     /* Enable flow control code */
-
-/**
- * Basic flow control
- */
-enum {
-       i1480u_TX_INFLIGHT_MAX = 1000,
-       i1480u_TX_INFLIGHT_THRESHOLD = 100,
-};
-
-/** Maximum size of a transaction that we can tx/rx */
-enum {
-       /* Maximum packet size computed as follows: max UNTD header (8) +
-        * i1480 RX header (8) + max Ethernet header and payload (4096) +
-        * Padding added by skb_reserve (2) to make post Ethernet payload
-        * start on 16 byte boundary*/
-       i1480u_MAX_RX_PKT_SIZE = 4114,
-       i1480u_MAX_FRG_SIZE = 512,
-       i1480u_RX_BUFS = 9,
-};
-
-
-/**
- * UNTD packet type
- *
- * We need to fragment any payload whose UNTD packet is going to be
- * bigger than i1480u_MAX_FRG_SIZE.
- */
-enum i1480u_pkt_type {
-       i1480u_PKT_FRAG_1ST = 0x1,
-       i1480u_PKT_FRAG_NXT = 0x0,
-       i1480u_PKT_FRAG_LST = 0x2,
-       i1480u_PKT_FRAG_CMP = 0x3
-};
-enum {
-       i1480u_PKT_NONE = 0x4,
-};
-
-/** USB Network Transfer Descriptor - common */
-struct untd_hdr {
-       u8     type;
-       __le16 len;
-} __attribute__((packed));
-
-static inline enum i1480u_pkt_type untd_hdr_type(const struct untd_hdr *hdr)
-{
-       return hdr->type & 0x03;
-}
-
-static inline int untd_hdr_rx_tx(const struct untd_hdr *hdr)
-{
-       return (hdr->type >> 2) & 0x01;
-}
-
-static inline void untd_hdr_set_type(struct untd_hdr *hdr, enum i1480u_pkt_type type)
-{
-       hdr->type = (hdr->type & ~0x03) | type;
-}
-
-static inline void untd_hdr_set_rx_tx(struct untd_hdr *hdr, int rx_tx)
-{
-       hdr->type = (hdr->type & ~0x04) | (rx_tx << 2);
-}
-
-
-/**
- * USB Network Transfer Descriptor - Complete Packet
- *
- * This is for a packet that is smaller (header + payload) than
- * i1480u_MAX_FRG_SIZE.
- *
- * @hdr.total_len is the size of the payload; the payload doesn't
- * count this header nor the padding, but includes the size of i1480
- * header.
- */
-struct untd_hdr_cmp {
-       struct untd_hdr hdr;
-       u8              padding;
-} __attribute__((packed));
-
-
-/**
- * USB Network Transfer Descriptor - First fragment
- *
- * @hdr.len is the size of the *whole packet* (excluding UNTD
- * headers); @fragment_len is the size of the payload (excluding UNTD
- * headers, but including i1480 headers).
- */
-struct untd_hdr_1st {
-       struct untd_hdr hdr;
-       __le16          fragment_len;
-       u8              padding[3];
-} __attribute__((packed));
-
-
-/**
- * USB Network Transfer Descriptor - Next / Last [Rest]
- *
- * @hdr.len is the size of the payload, not including headrs.
- */
-struct untd_hdr_rst {
-       struct untd_hdr hdr;
-       u8              padding;
-} __attribute__((packed));
-
-
-/**
- * Transmission context
- *
- * Wraps all the stuff needed to track a pending/active tx
- * operation.
- */
-struct i1480u_tx {
-       struct list_head list_node;
-       struct i1480u *i1480u;
-       struct urb *urb;
-
-       struct sk_buff *skb;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-
-       void *buf;      /* if NULL, no new buf was used */
-       size_t buf_size;
-};
-
-/**
- * Basic flow control
- *
- * We maintain a basic flow control counter. "count" how many TX URBs are
- * outstanding. Only allow "max"
- * TX URBs to be outstanding. If this value is reached the queue will be
- * stopped. The queue will be restarted when there are
- * "threshold" URBs outstanding.
- * Maintain a counter of how many time the TX queue needed to be restarted
- * due to the "max" being exceeded and the "threshold" reached again. The
- * timestamp "restart_ts" is to keep track from when the counter was last
- * queried (see sysfs handling of file wlp_tx_inflight).
- */
-struct i1480u_tx_inflight {
-       atomic_t count;
-       unsigned long max;
-       unsigned long threshold;
-       unsigned long restart_ts;
-       atomic_t restart_count;
-};
-
-/**
- * Instance of a i1480u WLP interface
- *
- * Keeps references to the USB device that wraps it, as well as it's
- * interface and associated UWB host controller. As well, it also
- * keeps a link to the netdevice for integration into the networking
- * stack.
- * We maintian separate error history for the tx and rx endpoints because
- * the implementation does not rely on locking - having one shared
- * structure between endpoints may cause problems. Adding locking to the
- * implementation will have higher cost than adding a separate structure.
- */
-struct i1480u {
-       struct usb_device *usb_dev;
-       struct usb_interface *usb_iface;
-       struct net_device *net_dev;
-
-       spinlock_t lock;
-
-       /* RX context handling */
-       struct sk_buff *rx_skb;
-       struct uwb_dev_addr rx_srcaddr;
-       size_t rx_untd_pkt_size;
-       struct i1480u_rx_buf {
-               struct i1480u *i1480u;  /* back pointer */
-               struct urb *urb;
-               struct sk_buff *data;   /* i1480u_MAX_RX_PKT_SIZE each */
-       } rx_buf[i1480u_RX_BUFS];       /* N bufs */
-
-       spinlock_t tx_list_lock;        /* TX context */
-       struct list_head tx_list;
-       u8 tx_stream;
-
-       struct stats lqe_stats, rssi_stats;     /* radio statistics */
-
-       /* Options we can set from sysfs */
-       struct wlp_options options;
-       struct uwb_notifs_handler uwb_notifs_handler;
-       struct edc tx_errors;
-       struct edc rx_errors;
-       struct wlp wlp;
-#ifdef i1480u_FLOW_CONTROL
-       struct urb *notif_urb;
-       struct edc notif_edc;           /* error density counter */
-       u8 notif_buffer[1];
-#endif
-       struct i1480u_tx_inflight tx_inflight;
-};
-
-/* Internal interfaces */
-extern void i1480u_rx_cb(struct urb *urb);
-extern int i1480u_rx_setup(struct i1480u *);
-extern void i1480u_rx_release(struct i1480u *);
-extern void i1480u_tx_release(struct i1480u *);
-extern int i1480u_xmit_frame(struct wlp *, struct sk_buff *,
-                            struct uwb_dev_addr *);
-extern void i1480u_stop_queue(struct wlp *);
-extern void i1480u_start_queue(struct wlp *);
-extern int i1480u_sysfs_setup(struct i1480u *);
-extern void i1480u_sysfs_release(struct i1480u *);
-
-/* netdev interface */
-extern int i1480u_open(struct net_device *);
-extern int i1480u_stop(struct net_device *);
-extern netdev_tx_t i1480u_hard_start_xmit(struct sk_buff *,
-                                               struct net_device *);
-extern void i1480u_tx_timeout(struct net_device *);
-extern int i1480u_set_config(struct net_device *, struct ifmap *);
-extern int i1480u_change_mtu(struct net_device *, int);
-extern void i1480u_uwb_notifs_cb(void *, struct uwb_dev *, enum uwb_notifs);
-
-/* bandwidth allocation callback */
-extern void  i1480u_bw_alloc_cb(struct uwb_rsv *);
-
-/* Sys FS */
-extern struct attribute_group i1480u_wlp_attr_group;
-
-#endif /* #ifndef __i1480u_wlp_h__ */
diff --git a/drivers/uwb/i1480/i1480u-wlp/lc.c b/drivers/uwb/i1480/i1480u-wlp/lc.c
deleted file mode 100644 (file)
index def778c..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Driver for the Linux Network stack.
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- *
- * This implements a very simple network driver for the WLP USB
- * device that is associated to a UWB (Ultra Wide Band) host.
- *
- * This is seen as an interface of a composite device. Once the UWB
- * host has an association to another WLP capable device, the
- * networking interface (aka WLP) can start to send packets back and
- * forth.
- *
- * Limitations:
- *
- *  - Hand cranked; can't ifup the interface until there is an association
- *
- *  - BW allocation very simplistic [see i1480u_mas_set() and callees].
- *
- *
- * ROADMAP:
- *
- *   ENTRY POINTS (driver model):
- *
- *     i1480u_driver_{exit,init}(): initialization of the driver.
- *
- *     i1480u_probe(): called by the driver code when a device
- *                     matching 'i1480u_id_table' is connected.
- *
- *                     This allocs a netdev instance, inits with
- *                     i1480u_add(), then registers_netdev().
- *         i1480u_init()
- *         i1480u_add()
- *
- *     i1480u_disconnect(): device has been disconnected/module
- *                          is being removed.
- *         i1480u_rm()
- */
-#include <linux/gfp.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-
-#include "i1480u-wlp.h"
-
-
-
-static inline
-void i1480u_init(struct i1480u *i1480u)
-{
-       /* nothing so far... doesn't it suck? */
-       spin_lock_init(&i1480u->lock);
-       INIT_LIST_HEAD(&i1480u->tx_list);
-       spin_lock_init(&i1480u->tx_list_lock);
-       wlp_options_init(&i1480u->options);
-       edc_init(&i1480u->tx_errors);
-       edc_init(&i1480u->rx_errors);
-#ifdef i1480u_FLOW_CONTROL
-       edc_init(&i1480u->notif_edc);
-#endif
-       stats_init(&i1480u->lqe_stats);
-       stats_init(&i1480u->rssi_stats);
-       wlp_init(&i1480u->wlp);
-}
-
-/**
- * Fill WLP device information structure
- *
- * The structure will contain a few character arrays, each ending with a
- * null terminated string. Each string has to fit (excluding terminating
- * character) into a specified range obtained from the WLP substack.
- *
- * It is still not clear exactly how this device information should be
- * obtained. Until we find out we use the USB device descriptor as backup, some
- * information elements have intuitive mappings, other not.
- */
-static
-void i1480u_fill_device_info(struct wlp *wlp, struct wlp_device_info *dev_info)
-{
-       struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
-       struct usb_device *usb_dev = i1480u->usb_dev;
-       /* Treat device name and model name the same */
-       if (usb_dev->descriptor.iProduct) {
-               usb_string(usb_dev, usb_dev->descriptor.iProduct,
-                          dev_info->name, sizeof(dev_info->name));
-               usb_string(usb_dev, usb_dev->descriptor.iProduct,
-                          dev_info->model_name, sizeof(dev_info->model_name));
-       }
-       if (usb_dev->descriptor.iManufacturer)
-               usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
-                          dev_info->manufacturer,
-                          sizeof(dev_info->manufacturer));
-       scnprintf(dev_info->model_nr, sizeof(dev_info->model_nr), "%04x",
-                 __le16_to_cpu(usb_dev->descriptor.bcdDevice));
-       if (usb_dev->descriptor.iSerialNumber)
-               usb_string(usb_dev, usb_dev->descriptor.iSerialNumber,
-                          dev_info->serial, sizeof(dev_info->serial));
-       /* FIXME: where should we obtain category? */
-       dev_info->prim_dev_type.category = cpu_to_le16(WLP_DEV_CAT_OTHER);
-       /* FIXME: Complete OUI and OUIsubdiv attributes */
-}
-
-#ifdef i1480u_FLOW_CONTROL
-/**
- * Callback for the notification endpoint
- *
- * This mostly controls the xon/xoff protocol. In case of hard error,
- * we stop the queue. If not, we always retry.
- */
-static
-void i1480u_notif_cb(struct urb *urb, struct pt_regs *regs)
-{
-       struct i1480u *i1480u = urb->context;
-       struct usb_interface *usb_iface = i1480u->usb_iface;
-       struct device *dev = &usb_iface->dev;
-       int result;
-
-       switch (urb->status) {
-       case 0:                         /* Got valid data, do xon/xoff */
-               switch (i1480u->notif_buffer[0]) {
-               case 'N':
-                       dev_err(dev, "XOFF STOPPING queue at %lu\n", jiffies);
-                       netif_stop_queue(i1480u->net_dev);
-                       break;
-               case 'A':
-                       dev_err(dev, "XON STARTING queue at %lu\n", jiffies);
-                       netif_start_queue(i1480u->net_dev);
-                       break;
-               default:
-                       dev_err(dev, "NEP: unknown data 0x%02hhx\n",
-                               i1480u->notif_buffer[0]);
-               }
-               break;
-       case -ECONNRESET:               /* Controlled situation ... */
-       case -ENOENT:                   /* we killed the URB... */
-               dev_err(dev, "NEP: URB reset/noent %d\n", urb->status);
-               goto error;
-       case -ESHUTDOWN:                /* going away! */
-               dev_err(dev, "NEP: URB down %d\n", urb->status);
-               goto error;
-       default:                        /* Retry unless it gets ugly */
-               if (edc_inc(&i1480u->notif_edc, EDC_MAX_ERRORS,
-                           EDC_ERROR_TIMEFRAME)) {
-                       dev_err(dev, "NEP: URB max acceptable errors "
-                               "exceeded; resetting device\n");
-                       goto error_reset;
-               }
-               dev_err(dev, "NEP: URB error %d\n", urb->status);
-               break;
-       }
-       result = usb_submit_urb(urb, GFP_ATOMIC);
-       if (result < 0) {
-               dev_err(dev, "NEP: Can't resubmit URB: %d; resetting device\n",
-                       result);
-               goto error_reset;
-       }
-       return;
-
-error_reset:
-       wlp_reset_all(&i1480-wlp);
-error:
-       netif_stop_queue(i1480u->net_dev);
-       return;
-}
-#endif
-
-static const struct net_device_ops i1480u_netdev_ops = {
-       .ndo_open       = i1480u_open,
-       .ndo_stop       = i1480u_stop,
-       .ndo_start_xmit = i1480u_hard_start_xmit,
-       .ndo_tx_timeout = i1480u_tx_timeout,
-       .ndo_set_config = i1480u_set_config,
-       .ndo_change_mtu = i1480u_change_mtu,
-};
-
-static
-int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface)
-{
-       int result = -ENODEV;
-       struct wlp *wlp = &i1480u->wlp;
-       struct usb_device *usb_dev = interface_to_usbdev(iface);
-       struct net_device *net_dev = i1480u->net_dev;
-       struct uwb_rc *rc;
-       struct uwb_dev *uwb_dev;
-#ifdef i1480u_FLOW_CONTROL
-       struct usb_endpoint_descriptor *epd;
-#endif
-
-       i1480u->usb_dev = usb_get_dev(usb_dev);
-       i1480u->usb_iface = iface;
-       rc = uwb_rc_get_by_grandpa(&i1480u->usb_dev->dev);
-       if (rc == NULL) {
-               dev_err(&iface->dev, "Cannot get associated UWB Radio "
-                       "Controller\n");
-               goto out;
-       }
-       wlp->xmit_frame = i1480u_xmit_frame;
-       wlp->fill_device_info = i1480u_fill_device_info;
-       wlp->stop_queue = i1480u_stop_queue;
-       wlp->start_queue = i1480u_start_queue;
-       result = wlp_setup(wlp, rc, net_dev);
-       if (result < 0) {
-               dev_err(&iface->dev, "Cannot setup WLP\n");
-               goto error_wlp_setup;
-       }
-       result = 0;
-       ether_setup(net_dev);                   /* make it an etherdevice */
-       uwb_dev = &rc->uwb_dev;
-       /* FIXME: hookup address change notifications? */
-
-       memcpy(net_dev->dev_addr, uwb_dev->mac_addr.data,
-              sizeof(net_dev->dev_addr));
-
-       net_dev->hard_header_len = sizeof(struct untd_hdr_cmp)
-               + sizeof(struct wlp_tx_hdr)
-               + WLP_DATA_HLEN
-               + ETH_HLEN;
-       net_dev->mtu = 3500;
-       net_dev->tx_queue_len = 20;             /* FIXME: maybe use 1000? */
-
-/*     net_dev->flags &= ~IFF_BROADCAST;       FIXME: BUG in firmware */
-       /* FIXME: multicast disabled */
-       net_dev->flags &= ~IFF_MULTICAST;
-       net_dev->features &= ~NETIF_F_SG;
-       net_dev->features &= ~NETIF_F_FRAGLIST;
-       /* All NETIF_F_*_CSUM disabled */
-       net_dev->features |= NETIF_F_HIGHDMA;
-       net_dev->watchdog_timeo = 5*HZ;         /* FIXME: a better default? */
-
-       net_dev->netdev_ops = &i1480u_netdev_ops;
-
-#ifdef i1480u_FLOW_CONTROL
-       /* Notification endpoint setup (submitted when we open the device) */
-       i1480u->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (i1480u->notif_urb == NULL) {
-               dev_err(&iface->dev, "Unable to allocate notification URB\n");
-               result = -ENOMEM;
-               goto error_urb_alloc;
-       }
-       epd = &iface->cur_altsetting->endpoint[0].desc;
-       usb_fill_int_urb(i1480u->notif_urb, usb_dev,
-                        usb_rcvintpipe(usb_dev, epd->bEndpointAddress),
-                        i1480u->notif_buffer, sizeof(i1480u->notif_buffer),
-                        i1480u_notif_cb, i1480u, epd->bInterval);
-
-#endif
-
-       i1480u->tx_inflight.max = i1480u_TX_INFLIGHT_MAX;
-       i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD;
-       i1480u->tx_inflight.restart_ts = jiffies;
-       usb_set_intfdata(iface, i1480u);
-       return result;
-
-#ifdef i1480u_FLOW_CONTROL
-error_urb_alloc:
-#endif
-       wlp_remove(wlp);
-error_wlp_setup:
-       uwb_rc_put(rc);
-out:
-       usb_put_dev(i1480u->usb_dev);
-       return result;
-}
-
-static void i1480u_rm(struct i1480u *i1480u)
-{
-       struct uwb_rc *rc = i1480u->wlp.rc;
-       usb_set_intfdata(i1480u->usb_iface, NULL);
-#ifdef i1480u_FLOW_CONTROL
-       usb_kill_urb(i1480u->notif_urb);
-       usb_free_urb(i1480u->notif_urb);
-#endif
-       wlp_remove(&i1480u->wlp);
-       uwb_rc_put(rc);
-       usb_put_dev(i1480u->usb_dev);
-}
-
-/** Just setup @net_dev's i1480u private data */
-static void i1480u_netdev_setup(struct net_device *net_dev)
-{
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       /* Initialize @i1480u */
-       memset(i1480u, 0, sizeof(*i1480u));
-       i1480u_init(i1480u);
-}
-
-/**
- * Probe a i1480u interface and register it
- *
- * @iface:   USB interface to link to
- * @id:      USB class/subclass/protocol id
- * @returns: 0 if ok, < 0 errno code on error.
- *
- * Does basic housekeeping stuff and then allocs a netdev with space
- * for the i1480u  data. Initializes, registers in i1480u, registers in
- * netdev, ready to go.
- */
-static int i1480u_probe(struct usb_interface *iface,
-                       const struct usb_device_id *id)
-{
-       int result;
-       struct net_device *net_dev;
-       struct device *dev = &iface->dev;
-       struct i1480u *i1480u;
-
-       /* Allocate instance [calls i1480u_netdev_setup() on it] */
-       result = -ENOMEM;
-       net_dev = alloc_netdev(sizeof(*i1480u), "wlp%d", i1480u_netdev_setup);
-       if (net_dev == NULL) {
-               dev_err(dev, "no memory for network device instance\n");
-               goto error_alloc_netdev;
-       }
-       SET_NETDEV_DEV(net_dev, dev);
-       i1480u = netdev_priv(net_dev);
-       i1480u->net_dev = net_dev;
-       result = i1480u_add(i1480u, iface);     /* Now setup all the wlp stuff */
-       if (result < 0) {
-               dev_err(dev, "cannot add i1480u device: %d\n", result);
-               goto error_i1480u_add;
-       }
-       result = register_netdev(net_dev);      /* Okey dokey, bring it up */
-       if (result < 0) {
-               dev_err(dev, "cannot register network device: %d\n", result);
-               goto error_register_netdev;
-       }
-       i1480u_sysfs_setup(i1480u);
-       if (result < 0)
-               goto error_sysfs_init;
-       return 0;
-
-error_sysfs_init:
-       unregister_netdev(net_dev);
-error_register_netdev:
-       i1480u_rm(i1480u);
-error_i1480u_add:
-       free_netdev(net_dev);
-error_alloc_netdev:
-       return result;
-}
-
-
-/**
- * Disconect a i1480u from the system.
- *
- * i1480u_stop() has been called before, so al the rx and tx contexts
- * have been taken down already. Make sure the queue is stopped,
- * unregister netdev and i1480u, free and kill.
- */
-static void i1480u_disconnect(struct usb_interface *iface)
-{
-       struct i1480u *i1480u;
-       struct net_device *net_dev;
-
-       i1480u = usb_get_intfdata(iface);
-       net_dev = i1480u->net_dev;
-       netif_stop_queue(net_dev);
-#ifdef i1480u_FLOW_CONTROL
-       usb_kill_urb(i1480u->notif_urb);
-#endif
-       i1480u_sysfs_release(i1480u);
-       unregister_netdev(net_dev);
-       i1480u_rm(i1480u);
-       free_netdev(net_dev);
-}
-
-static struct usb_device_id i1480u_id_table[] = {
-       {
-               .match_flags = USB_DEVICE_ID_MATCH_DEVICE \
-                               |  USB_DEVICE_ID_MATCH_DEV_INFO \
-                               |  USB_DEVICE_ID_MATCH_INT_INFO,
-               .idVendor = 0x8086,
-               .idProduct = 0x0c3b,
-               .bDeviceClass = 0xef,
-               .bDeviceSubClass = 0x02,
-               .bDeviceProtocol = 0x02,
-               .bInterfaceClass = 0xff,
-               .bInterfaceSubClass = 0xff,
-               .bInterfaceProtocol = 0xff,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(usb, i1480u_id_table);
-
-static struct usb_driver i1480u_driver = {
-       .name =         KBUILD_MODNAME,
-       .probe =        i1480u_probe,
-       .disconnect =   i1480u_disconnect,
-       .id_table =     i1480u_id_table,
-};
-
-static int __init i1480u_driver_init(void)
-{
-       return usb_register(&i1480u_driver);
-}
-module_init(i1480u_driver_init);
-
-
-static void __exit i1480u_driver_exit(void)
-{
-       usb_deregister(&i1480u_driver);
-}
-module_exit(i1480u_driver_exit);
-
-MODULE_AUTHOR("Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>");
-MODULE_DESCRIPTION("i1480 Wireless UWB Link WLP networking for USB");
-MODULE_LICENSE("GPL");
diff --git a/drivers/uwb/i1480/i1480u-wlp/netdev.c b/drivers/uwb/i1480/i1480u-wlp/netdev.c
deleted file mode 100644 (file)
index f98f6ce..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Driver for the Linux Network stack.
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- *
- * Implementation of the netdevice linkage (except tx and rx related stuff).
- *
- * ROADMAP:
- *
- *   ENTRY POINTS (Net device):
- *
- *     i1480u_open(): Called when we ifconfig up the interface;
- *                    associates to a UWB host controller, reserves
- *                    bandwidth (MAS), sets up RX USB URB and starts
- *                    the queue.
- *
- *     i1480u_stop(): Called when we ifconfig down a interface;
- *                    reverses _open().
- *
- *     i1480u_set_config():
- */
-
-#include <linux/slab.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-
-#include "i1480u-wlp.h"
-
-struct i1480u_cmd_set_ip_mas {
-       struct uwb_rccb     rccb;
-       struct uwb_dev_addr addr;
-       u8                  stream;
-       u8                  owner;
-       u8                  type;       /* enum uwb_drp_type */
-       u8                  baMAS[32];
-} __attribute__((packed));
-
-
-static
-int i1480u_set_ip_mas(
-       struct uwb_rc *rc,
-       const struct uwb_dev_addr *dstaddr,
-       u8 stream, u8 owner, u8 type, unsigned long *mas)
-{
-
-       int result;
-       struct i1480u_cmd_set_ip_mas *cmd;
-       struct uwb_rc_evt_confirm reply;
-
-       result = -ENOMEM;
-       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-       if (cmd == NULL)
-               goto error_kzalloc;
-       cmd->rccb.bCommandType = 0xfd;
-       cmd->rccb.wCommand = cpu_to_le16(0x000e);
-       cmd->addr = *dstaddr;
-       cmd->stream = stream;
-       cmd->owner = owner;
-       cmd->type = type;
-       if (mas == NULL)
-               memset(cmd->baMAS, 0x00, sizeof(cmd->baMAS));
-       else
-               memcpy(cmd->baMAS, mas, sizeof(cmd->baMAS));
-       reply.rceb.bEventType = 0xfd;
-       reply.rceb.wEvent = cpu_to_le16(0x000e);
-       result = uwb_rc_cmd(rc, "SET-IP-MAS", &cmd->rccb, sizeof(*cmd),
-                           &reply.rceb, sizeof(reply));
-       if (result < 0)
-               goto error_cmd;
-       if (reply.bResultCode != UWB_RC_RES_FAIL) {
-               dev_err(&rc->uwb_dev.dev,
-                       "SET-IP-MAS: command execution failed: %d\n",
-                       reply.bResultCode);
-               result = -EIO;
-       }
-error_cmd:
-       kfree(cmd);
-error_kzalloc:
-       return result;
-}
-
-/*
- * Inform a WLP interface of a MAS reservation
- *
- * @rc is assumed refcnted.
- */
-/* FIXME: detect if remote device is WLP capable? */
-static int i1480u_mas_set_dev(struct uwb_dev *uwb_dev, struct uwb_rc *rc,
-                             u8 stream, u8 owner, u8 type, unsigned long *mas)
-{
-       int result = 0;
-       struct device *dev = &rc->uwb_dev.dev;
-
-       result = i1480u_set_ip_mas(rc, &uwb_dev->dev_addr, stream, owner,
-                                  type, mas);
-       if (result < 0) {
-               char rcaddrbuf[UWB_ADDR_STRSIZE], devaddrbuf[UWB_ADDR_STRSIZE];
-               uwb_dev_addr_print(rcaddrbuf, sizeof(rcaddrbuf),
-                                  &rc->uwb_dev.dev_addr);
-               uwb_dev_addr_print(devaddrbuf, sizeof(devaddrbuf),
-                                  &uwb_dev->dev_addr);
-               dev_err(dev, "Set IP MAS (%s to %s) failed: %d\n",
-                       rcaddrbuf, devaddrbuf, result);
-       }
-       return result;
-}
-
-/**
- * Called by bandwidth allocator when change occurs in reservation.
- *
- * @rsv:     The reservation that is being established, modified, or
- *           terminated.
- *
- * When a reservation is established, modified, or terminated the upper layer
- * (WLP here) needs set/update the currently available Media Access Slots
- * that can be use for IP traffic.
- *
- * Our action taken during failure depends on how the reservation is being
- * changed:
- * - if reservation is being established we do nothing if we cannot set the
- *   new MAS to be used
- * - if reservation is being terminated we revert back to PCA whether the
- *   SET IP MAS command succeeds or not.
- */
-void i1480u_bw_alloc_cb(struct uwb_rsv *rsv)
-{
-       int result = 0;
-       struct i1480u *i1480u = rsv->pal_priv;
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct uwb_dev *target_dev = rsv->target.dev;
-       struct uwb_rc *rc = i1480u->wlp.rc;
-       u8 stream = rsv->stream;
-       int type = rsv->type;
-       int is_owner = rsv->owner == &rc->uwb_dev;
-       unsigned long *bmp = rsv->mas.bm;
-
-       dev_err(dev, "WLP callback called - sending set ip mas\n");
-       /*user cannot change options while setting configuration*/
-       mutex_lock(&i1480u->options.mutex);
-       switch (rsv->state) {
-       case UWB_RSV_STATE_T_ACCEPTED:
-       case UWB_RSV_STATE_O_ESTABLISHED:
-               result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner,
-                                       type, bmp);
-               if (result < 0) {
-                       dev_err(dev, "MAS reservation failed: %d\n", result);
-                       goto out;
-               }
-               if (is_owner) {
-                       wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr,
-                                                       WLP_DRP | stream);
-                       wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 0);
-               }
-               break;
-       case UWB_RSV_STATE_NONE:
-               /* revert back to PCA */
-               result = i1480u_mas_set_dev(target_dev, rc, stream, is_owner,
-                                           type, bmp);
-               if (result < 0)
-                       dev_err(dev, "MAS reservation failed: %d\n", result);
-               /* Revert to PCA even though SET IP MAS failed. */
-               wlp_tx_hdr_set_delivery_id_type(&i1480u->options.def_tx_hdr,
-                                               i1480u->options.pca_base_priority);
-               wlp_tx_hdr_set_rts_cts(&i1480u->options.def_tx_hdr, 1);
-               break;
-       default:
-               dev_err(dev, "unexpected WLP reservation state: %s (%d).\n",
-                       uwb_rsv_state_str(rsv->state), rsv->state);
-               break;
-       }
-out:
-       mutex_unlock(&i1480u->options.mutex);
-       return;
-}
-
-/**
- *
- * Called on 'ifconfig up'
- */
-int i1480u_open(struct net_device *net_dev)
-{
-       int result;
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       struct wlp *wlp = &i1480u->wlp;
-       struct uwb_rc *rc;
-       struct device *dev = &i1480u->usb_iface->dev;
-
-       rc = wlp->rc;
-       result = i1480u_rx_setup(i1480u);               /* Alloc RX stuff */
-       if (result < 0)
-               goto error_rx_setup;
-
-       result = uwb_radio_start(&wlp->pal);
-       if (result < 0)
-               goto error_radio_start;
-
-       netif_wake_queue(net_dev);
-#ifdef i1480u_FLOW_CONTROL
-       result = usb_submit_urb(i1480u->notif_urb, GFP_KERNEL);
-       if (result < 0) {
-               dev_err(dev, "Can't submit notification URB: %d\n", result);
-               goto error_notif_urb_submit;
-       }
-#endif
-       /* Interface is up with an address, now we can create WSS */
-       result = wlp_wss_setup(net_dev, &wlp->wss);
-       if (result < 0) {
-               dev_err(dev, "Can't create WSS: %d. \n", result);
-               goto error_wss_setup;
-       }
-       return 0;
-error_wss_setup:
-#ifdef i1480u_FLOW_CONTROL
-       usb_kill_urb(i1480u->notif_urb);
-error_notif_urb_submit:
-#endif
-       uwb_radio_stop(&wlp->pal);
-error_radio_start:
-       netif_stop_queue(net_dev);
-       i1480u_rx_release(i1480u);
-error_rx_setup:
-       return result;
-}
-
-
-/**
- * Called on 'ifconfig down'
- */
-int i1480u_stop(struct net_device *net_dev)
-{
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       struct wlp *wlp = &i1480u->wlp;
-
-       BUG_ON(wlp->rc == NULL);
-       wlp_wss_remove(&wlp->wss);
-       netif_carrier_off(net_dev);
-#ifdef i1480u_FLOW_CONTROL
-       usb_kill_urb(i1480u->notif_urb);
-#endif
-       netif_stop_queue(net_dev);
-       uwb_radio_stop(&wlp->pal);
-       i1480u_rx_release(i1480u);
-       i1480u_tx_release(i1480u);
-       return 0;
-}
-
-/**
- *
- * Change the interface config--we probably don't have to do anything.
- */
-int i1480u_set_config(struct net_device *net_dev, struct ifmap *map)
-{
-       int result;
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       BUG_ON(i1480u->wlp.rc == NULL);
-       result = 0;
-       return result;
-}
-
-/**
- * Change the MTU of the interface
- */
-int i1480u_change_mtu(struct net_device *net_dev, int mtu)
-{
-       static union {
-               struct wlp_tx_hdr tx;
-               struct wlp_rx_hdr rx;
-       } i1480u_all_hdrs;
-
-       if (mtu < ETH_HLEN)     /* We encap eth frames */
-               return -ERANGE;
-       if (mtu > 4000 - sizeof(i1480u_all_hdrs))
-               return -ERANGE;
-       net_dev->mtu = mtu;
-       return 0;
-}
-
-/**
- * Stop the network queue
- *
- * Enable WLP substack to stop network queue. We also set the flow control
- * threshold at this time to prevent the flow control from restarting the
- * queue.
- *
- * we are loosing the current threshold value here ... FIXME?
- */
-void i1480u_stop_queue(struct wlp *wlp)
-{
-       struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
-       struct net_device *net_dev = i1480u->net_dev;
-       i1480u->tx_inflight.threshold = 0;
-       netif_stop_queue(net_dev);
-}
-
-/**
- * Start the network queue
- *
- * Enable WLP substack to start network queue. Also re-enable the flow
- * control to manage the queue again.
- *
- * We re-enable the flow control by storing the default threshold in the
- * flow control threshold. This means that if the user modified the
- * threshold before the queue was stopped and restarted that information
- * will be lost. FIXME?
- */
-void i1480u_start_queue(struct wlp *wlp)
-{
-       struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
-       struct net_device *net_dev = i1480u->net_dev;
-       i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD;
-       netif_start_queue(net_dev);
-}
diff --git a/drivers/uwb/i1480/i1480u-wlp/rx.c b/drivers/uwb/i1480/i1480u-wlp/rx.c
deleted file mode 100644 (file)
index d4e51e1..0000000
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Driver for the Linux Network stack.
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * i1480u's RX handling is simple. i1480u will send the received
- * network packets broken up in fragments; 1 to N fragments make a
- * packet, we assemble them together and deliver the packet with netif_rx().
- *
- * Beacuse each USB transfer is a *single* fragment (except when the
- * transfer contains a first fragment), each URB called thus
- * back contains one or two fragments. So we queue N URBs, each with its own
- * fragment buffer. When a URB is done, we process it (adding to the
- * current skb from the fragment buffer until complete). Once
- * processed, we requeue the URB. There is always a bunch of URBs
- * ready to take data, so the intergap should be minimal.
- *
- * An URB's transfer buffer is the data field of a socket buffer. This
- * reduces copying as data can be passed directly to network layer. If a
- * complete packet or 1st fragment is received the URB's transfer buffer is
- * taken away from it and used to send data to the network layer. In this
- * case a new transfer buffer is allocated to the URB before being requeued.
- * If a "NEXT" or "LAST" fragment is received, the fragment contents is
- * appended to the RX packet under construction and the transfer buffer
- * is reused. To be able to use this buffer to assemble complete packets
- * we set each buffer's size to that of the MAX ethernet packet that can
- * be received. There is thus room for improvement in memory usage.
- *
- * When the max tx fragment size increases, we should be able to read
- * data into the skbs directly with very simple code.
- *
- * ROADMAP:
- *
- *   ENTRY POINTS:
- *
- *     i1480u_rx_setup(): setup RX context [from i1480u_open()]
- *
- *     i1480u_rx_release(): release RX context [from i1480u_stop()]
- *
- *     i1480u_rx_cb(): called when the RX USB URB receives a
- *                     packet. It removes the header and pushes it up
- *                     the Linux netdev stack with netif_rx().
- *
- *       i1480u_rx_buffer()
- *         i1480u_drop() and i1480u_fix()
- *         i1480u_skb_deliver
- *
- */
-
-#include <linux/gfp.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include "i1480u-wlp.h"
-
-/*
- * Setup the RX context
- *
- * Each URB is provided with a transfer_buffer that is the data field
- * of a new socket buffer.
- */
-int i1480u_rx_setup(struct i1480u *i1480u)
-{
-       int result, cnt;
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct usb_endpoint_descriptor *epd;
-       struct sk_buff *skb;
-
-       /* Alloc RX stuff */
-       i1480u->rx_skb = NULL;  /* not in process of receiving packet */
-       result = -ENOMEM;
-       epd = &i1480u->usb_iface->cur_altsetting->endpoint[1].desc;
-       for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
-               struct i1480u_rx_buf *rx_buf = &i1480u->rx_buf[cnt];
-               rx_buf->i1480u = i1480u;
-               skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE);
-               if (!skb) {
-                       dev_err(dev,
-                               "RX: cannot allocate RX buffer %d\n", cnt);
-                       result = -ENOMEM;
-                       goto error;
-               }
-               skb->dev = net_dev;
-               skb->ip_summed = CHECKSUM_NONE;
-               skb_reserve(skb, 2);
-               rx_buf->data = skb;
-               rx_buf->urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (unlikely(rx_buf->urb == NULL)) {
-                       dev_err(dev, "RX: cannot allocate URB %d\n", cnt);
-                       result = -ENOMEM;
-                       goto error;
-               }
-               usb_fill_bulk_urb(rx_buf->urb, i1480u->usb_dev,
-                         usb_rcvbulkpipe(i1480u->usb_dev, epd->bEndpointAddress),
-                         rx_buf->data->data, i1480u_MAX_RX_PKT_SIZE - 2,
-                         i1480u_rx_cb, rx_buf);
-               result = usb_submit_urb(rx_buf->urb, GFP_NOIO);
-               if (unlikely(result < 0)) {
-                       dev_err(dev, "RX: cannot submit URB %d: %d\n",
-                               cnt, result);
-                       goto error;
-               }
-       }
-       return 0;
-
-error:
-       i1480u_rx_release(i1480u);
-       return result;
-}
-
-
-/* Release resources associated to the rx context */
-void i1480u_rx_release(struct i1480u *i1480u)
-{
-       int cnt;
-       for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
-               if (i1480u->rx_buf[cnt].data)
-                       dev_kfree_skb(i1480u->rx_buf[cnt].data);
-               if (i1480u->rx_buf[cnt].urb) {
-                       usb_kill_urb(i1480u->rx_buf[cnt].urb);
-                       usb_free_urb(i1480u->rx_buf[cnt].urb);
-               }
-       }
-       if (i1480u->rx_skb != NULL)
-               dev_kfree_skb(i1480u->rx_skb);
-}
-
-static
-void i1480u_rx_unlink_urbs(struct i1480u *i1480u)
-{
-       int cnt;
-       for (cnt = 0; cnt < i1480u_RX_BUFS; cnt++) {
-               if (i1480u->rx_buf[cnt].urb)
-                       usb_unlink_urb(i1480u->rx_buf[cnt].urb);
-       }
-}
-
-/* Fix an out-of-sequence packet */
-#define i1480u_fix(i1480u, msg...)                     \
-do {                                                   \
-       if (printk_ratelimit())                         \
-               dev_err(&i1480u->usb_iface->dev, msg);  \
-       dev_kfree_skb_irq(i1480u->rx_skb);              \
-       i1480u->rx_skb = NULL;                          \
-       i1480u->rx_untd_pkt_size = 0;                   \
-} while (0)
-
-
-/* Drop an out-of-sequence packet */
-#define i1480u_drop(i1480u, msg...)                    \
-do {                                                   \
-       if (printk_ratelimit())                         \
-               dev_err(&i1480u->usb_iface->dev, msg);  \
-       i1480u->net_dev->stats.rx_dropped++;                    \
-} while (0)
-
-
-
-
-/* Finalizes setting up the SKB and delivers it
- *
- * We first pass the incoming frame to WLP substack for verification. It
- * may also be a WLP association frame in which case WLP will take over the
- * processing. If WLP does not take it over it will still verify it, if the
- * frame is invalid the skb will be freed by WLP and we will not continue
- * parsing.
- * */
-static
-void i1480u_skb_deliver(struct i1480u *i1480u)
-{
-       int should_parse;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct device *dev = &i1480u->usb_iface->dev;
-
-       should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb,
-                                        &i1480u->rx_srcaddr);
-       if (!should_parse)
-               goto out;
-       i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev);
-       net_dev->stats.rx_packets++;
-       net_dev->stats.rx_bytes += i1480u->rx_untd_pkt_size;
-
-       netif_rx(i1480u->rx_skb);               /* deliver */
-out:
-       i1480u->rx_skb = NULL;
-       i1480u->rx_untd_pkt_size = 0;
-}
-
-
-/*
- * Process a buffer of data received from the USB RX endpoint
- *
- * First fragment arrives with next or last fragment. All other fragments
- * arrive alone.
- *
- * /me hates long functions.
- */
-static
-void i1480u_rx_buffer(struct i1480u_rx_buf *rx_buf)
-{
-       unsigned pkt_completed = 0;     /* !0 when we got all pkt fragments */
-       size_t untd_hdr_size, untd_frg_size;
-       size_t i1480u_hdr_size;
-       struct wlp_rx_hdr *i1480u_hdr = NULL;
-
-       struct i1480u *i1480u = rx_buf->i1480u;
-       struct sk_buff *skb = rx_buf->data;
-       int size_left = rx_buf->urb->actual_length;
-       void *ptr = rx_buf->urb->transfer_buffer; /* also rx_buf->data->data */
-       struct untd_hdr *untd_hdr;
-
-       struct net_device *net_dev = i1480u->net_dev;
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct sk_buff *new_skb;
-
-#if 0
-       dev_fnstart(dev,
-                   "(i1480u %p ptr %p size_left %zu)\n", i1480u, ptr, size_left);
-       dev_err(dev, "RX packet, %zu bytes\n", size_left);
-       dump_bytes(dev, ptr, size_left);
-#endif
-       i1480u_hdr_size = sizeof(struct wlp_rx_hdr);
-
-       while (size_left > 0) {
-               if (pkt_completed) {
-                       i1480u_drop(i1480u, "RX: fragment follows completed"
-                                        "packet in same buffer. Dropping\n");
-                       break;
-               }
-               untd_hdr = ptr;
-               if (size_left < sizeof(*untd_hdr)) {    /*  Check the UNTD header */
-                       i1480u_drop(i1480u, "RX: short UNTD header! Dropping\n");
-                       goto out;
-               }
-               if (unlikely(untd_hdr_rx_tx(untd_hdr) == 0)) {  /* Paranoia: TX set? */
-                       i1480u_drop(i1480u, "RX: TX bit set! Dropping\n");
-                       goto out;
-               }
-               switch (untd_hdr_type(untd_hdr)) {      /* Check the UNTD header type */
-               case i1480u_PKT_FRAG_1ST: {
-                       struct untd_hdr_1st *untd_hdr_1st = (void *) untd_hdr;
-                       dev_dbg(dev, "1st fragment\n");
-                       untd_hdr_size = sizeof(struct untd_hdr_1st);
-                       if (i1480u->rx_skb != NULL)
-                               i1480u_fix(i1480u, "RX: 1st fragment out of "
-                                       "sequence! Fixing\n");
-                       if (size_left < untd_hdr_size + i1480u_hdr_size) {
-                               i1480u_drop(i1480u, "RX: short 1st fragment! "
-                                       "Dropping\n");
-                               goto out;
-                       }
-                       i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len)
-                                                - i1480u_hdr_size;
-                       untd_frg_size = le16_to_cpu(untd_hdr_1st->fragment_len);
-                       if (size_left < untd_hdr_size + untd_frg_size) {
-                               i1480u_drop(i1480u,
-                                           "RX: short payload! Dropping\n");
-                               goto out;
-                       }
-                       i1480u->rx_skb = skb;
-                       i1480u_hdr = (void *) untd_hdr_1st + untd_hdr_size;
-                       i1480u->rx_srcaddr = i1480u_hdr->srcaddr;
-                       skb_put(i1480u->rx_skb, untd_hdr_size + untd_frg_size);
-                       skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size);
-                       stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7);
-                       stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18);
-                       rx_buf->data = NULL; /* need to create new buffer */
-                       break;
-               }
-               case i1480u_PKT_FRAG_NXT: {
-                       dev_dbg(dev, "nxt fragment\n");
-                       untd_hdr_size = sizeof(struct untd_hdr_rst);
-                       if (i1480u->rx_skb == NULL) {
-                               i1480u_drop(i1480u, "RX: next fragment out of "
-                                           "sequence! Dropping\n");
-                               goto out;
-                       }
-                       if (size_left < untd_hdr_size) {
-                               i1480u_drop(i1480u, "RX: short NXT fragment! "
-                                           "Dropping\n");
-                               goto out;
-                       }
-                       untd_frg_size = le16_to_cpu(untd_hdr->len);
-                       if (size_left < untd_hdr_size + untd_frg_size) {
-                               i1480u_drop(i1480u,
-                                           "RX: short payload! Dropping\n");
-                               goto out;
-                       }
-                       memmove(skb_put(i1480u->rx_skb, untd_frg_size),
-                                       ptr + untd_hdr_size, untd_frg_size);
-                       break;
-               }
-               case i1480u_PKT_FRAG_LST: {
-                       dev_dbg(dev, "Lst fragment\n");
-                       untd_hdr_size = sizeof(struct untd_hdr_rst);
-                       if (i1480u->rx_skb == NULL) {
-                               i1480u_drop(i1480u, "RX: last fragment out of "
-                                           "sequence! Dropping\n");
-                               goto out;
-                       }
-                       if (size_left < untd_hdr_size) {
-                               i1480u_drop(i1480u, "RX: short LST fragment! "
-                                           "Dropping\n");
-                               goto out;
-                       }
-                       untd_frg_size = le16_to_cpu(untd_hdr->len);
-                       if (size_left < untd_frg_size + untd_hdr_size) {
-                               i1480u_drop(i1480u,
-                                           "RX: short payload! Dropping\n");
-                               goto out;
-                       }
-                       memmove(skb_put(i1480u->rx_skb, untd_frg_size),
-                                       ptr + untd_hdr_size, untd_frg_size);
-                       pkt_completed = 1;
-                       break;
-               }
-               case i1480u_PKT_FRAG_CMP: {
-                       dev_dbg(dev, "cmp fragment\n");
-                       untd_hdr_size = sizeof(struct untd_hdr_cmp);
-                       if (i1480u->rx_skb != NULL)
-                               i1480u_fix(i1480u, "RX: fix out-of-sequence CMP"
-                                          " fragment!\n");
-                       if (size_left < untd_hdr_size + i1480u_hdr_size) {
-                               i1480u_drop(i1480u, "RX: short CMP fragment! "
-                                           "Dropping\n");
-                               goto out;
-                       }
-                       i1480u->rx_untd_pkt_size = le16_to_cpu(untd_hdr->len);
-                       untd_frg_size = i1480u->rx_untd_pkt_size;
-                       if (size_left < i1480u->rx_untd_pkt_size + untd_hdr_size) {
-                               i1480u_drop(i1480u,
-                                           "RX: short payload! Dropping\n");
-                               goto out;
-                       }
-                       i1480u->rx_skb = skb;
-                       i1480u_hdr = (void *) untd_hdr + untd_hdr_size;
-                       i1480u->rx_srcaddr = i1480u_hdr->srcaddr;
-                       stats_add_sample(&i1480u->lqe_stats, (s8) i1480u_hdr->LQI - 7);
-                       stats_add_sample(&i1480u->rssi_stats, i1480u_hdr->RSSI + 18);
-                       skb_put(i1480u->rx_skb, untd_hdr_size + i1480u->rx_untd_pkt_size);
-                       skb_pull(i1480u->rx_skb, untd_hdr_size + i1480u_hdr_size);
-                       rx_buf->data = NULL;    /* for hand off skb to network stack */
-                       pkt_completed = 1;
-                       i1480u->rx_untd_pkt_size -= i1480u_hdr_size; /* accurate stat */
-                       break;
-               }
-               default:
-                       i1480u_drop(i1480u, "RX: unknown packet type %u! "
-                                   "Dropping\n", untd_hdr_type(untd_hdr));
-                       goto out;
-               }
-               size_left -= untd_hdr_size + untd_frg_size;
-               if (size_left > 0)
-                       ptr += untd_hdr_size + untd_frg_size;
-       }
-       if (pkt_completed)
-               i1480u_skb_deliver(i1480u);
-out:
-       /* recreate needed RX buffers*/
-       if (rx_buf->data == NULL) {
-               /* buffer is being used to receive packet, create new */
-               new_skb = dev_alloc_skb(i1480u_MAX_RX_PKT_SIZE);
-               if (!new_skb) {
-                       if (printk_ratelimit())
-                               dev_err(dev,
-                               "RX: cannot allocate RX buffer\n");
-               } else {
-                       new_skb->dev = net_dev;
-                       new_skb->ip_summed = CHECKSUM_NONE;
-                       skb_reserve(new_skb, 2);
-                       rx_buf->data = new_skb;
-               }
-       }
-       return;
-}
-
-
-/*
- * Called when an RX URB has finished receiving or has found some kind
- * of error condition.
- *
- * LIMITATIONS:
- *
- *  - We read USB-transfers, each transfer contains a SINGLE fragment
- *    (can contain a complete packet, or a 1st, next, or last fragment
- *    of a packet).
- *    Looks like a transfer can contain more than one fragment (07/18/06)
- *
- *  - Each transfer buffer is the size of the maximum packet size (minus
- *    headroom), i1480u_MAX_PKT_SIZE - 2
- *
- *  - We always read the full USB-transfer, no partials.
- *
- *  - Each transfer is read directly into a skb. This skb will be used to
- *    send data to the upper layers if it is the first fragment or a complete
- *    packet. In the other cases the data will be copied from the skb to
- *    another skb that is being prepared for the upper layers from a prev
- *    first fragment.
- *
- * It is simply too much of a pain. Gosh, there should be a unified
- * SG infrastructure for *everything* [so that I could declare a SG
- * buffer, pass it to USB for receiving, append some space to it if
- * I wish, receive more until I have the whole chunk, adapt
- * pointers on each fragment to remove hardware headers and then
- * attach that to an skbuff and netif_rx()].
- */
-void i1480u_rx_cb(struct urb *urb)
-{
-       int result;
-       int do_parse_buffer = 1;
-       struct i1480u_rx_buf *rx_buf = urb->context;
-       struct i1480u *i1480u = rx_buf->i1480u;
-       struct device *dev = &i1480u->usb_iface->dev;
-       unsigned long flags;
-       u8 rx_buf_idx = rx_buf - i1480u->rx_buf;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ECONNRESET:       /* Not an error, but a controlled situation; */
-       case -ENOENT:           /* (we killed the URB)...so, no broadcast */
-       case -ESHUTDOWN:        /* going away! */
-               dev_err(dev, "RX URB[%u]: goind down %d\n",
-                       rx_buf_idx, urb->status);
-               goto error;
-       default:
-               dev_err(dev, "RX URB[%u]: unknown status %d\n",
-                       rx_buf_idx, urb->status);
-               if (edc_inc(&i1480u->rx_errors, EDC_MAX_ERRORS,
-                                       EDC_ERROR_TIMEFRAME)) {
-                       dev_err(dev, "RX: max acceptable errors exceeded,"
-                                       " resetting device.\n");
-                       i1480u_rx_unlink_urbs(i1480u);
-                       wlp_reset_all(&i1480u->wlp);
-                       goto error;
-               }
-               do_parse_buffer = 0;
-               break;
-       }
-       spin_lock_irqsave(&i1480u->lock, flags);
-       /* chew the data fragments, extract network packets */
-       if (do_parse_buffer) {
-               i1480u_rx_buffer(rx_buf);
-               if (rx_buf->data) {
-                       rx_buf->urb->transfer_buffer = rx_buf->data->data;
-                       result = usb_submit_urb(rx_buf->urb, GFP_ATOMIC);
-                       if (result < 0) {
-                               dev_err(dev, "RX URB[%u]: cannot submit %d\n",
-                                       rx_buf_idx, result);
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&i1480u->lock, flags);
-error:
-       return;
-}
-
diff --git a/drivers/uwb/i1480/i1480u-wlp/sysfs.c b/drivers/uwb/i1480/i1480u-wlp/sysfs.c
deleted file mode 100644 (file)
index 4ffaf54..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Sysfs interfaces
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- */
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/device.h>
-
-#include "i1480u-wlp.h"
-
-
-/**
- *
- * @dev: Class device from the net_device; assumed refcnted.
- *
- * Yes, I don't lock--we assume it is refcounted and I am getting a
- * single byte value that is kind of atomic to read.
- */
-ssize_t uwb_phy_rate_show(const struct wlp_options *options, char *buf)
-{
-       return sprintf(buf, "%u\n",
-                      wlp_tx_hdr_phy_rate(&options->def_tx_hdr));
-}
-EXPORT_SYMBOL_GPL(uwb_phy_rate_show);
-
-
-ssize_t uwb_phy_rate_store(struct wlp_options *options,
-                          const char *buf, size_t size)
-{
-       ssize_t result;
-       unsigned rate;
-
-       result = sscanf(buf, "%u\n", &rate);
-       if (result != 1) {
-               result = -EINVAL;
-               goto out;
-       }
-       result = -EINVAL;
-       if (rate >= UWB_PHY_RATE_INVALID)
-               goto out;
-       wlp_tx_hdr_set_phy_rate(&options->def_tx_hdr, rate);
-       result = 0;
-out:
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(uwb_phy_rate_store);
-
-
-ssize_t uwb_rts_cts_show(const struct wlp_options *options, char *buf)
-{
-       return sprintf(buf, "%u\n",
-                      wlp_tx_hdr_rts_cts(&options->def_tx_hdr));
-}
-EXPORT_SYMBOL_GPL(uwb_rts_cts_show);
-
-
-ssize_t uwb_rts_cts_store(struct wlp_options *options,
-                         const char *buf, size_t size)
-{
-       ssize_t result;
-       unsigned value;
-
-       result = sscanf(buf, "%u\n", &value);
-       if (result != 1) {
-               result = -EINVAL;
-               goto out;
-       }
-       result = -EINVAL;
-       wlp_tx_hdr_set_rts_cts(&options->def_tx_hdr, !!value);
-       result = 0;
-out:
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(uwb_rts_cts_store);
-
-
-ssize_t uwb_ack_policy_show(const struct wlp_options *options, char *buf)
-{
-       return sprintf(buf, "%u\n",
-                      wlp_tx_hdr_ack_policy(&options->def_tx_hdr));
-}
-EXPORT_SYMBOL_GPL(uwb_ack_policy_show);
-
-
-ssize_t uwb_ack_policy_store(struct wlp_options *options,
-                            const char *buf, size_t size)
-{
-       ssize_t result;
-       unsigned value;
-
-       result = sscanf(buf, "%u\n", &value);
-       if (result != 1 || value > UWB_ACK_B_REQ) {
-               result = -EINVAL;
-               goto out;
-       }
-       wlp_tx_hdr_set_ack_policy(&options->def_tx_hdr, value);
-       result = 0;
-out:
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(uwb_ack_policy_store);
-
-
-/**
- * Show the PCA base priority.
- *
- * We can access without locking, as the value is (for now) orthogonal
- * to other values.
- */
-ssize_t uwb_pca_base_priority_show(const struct wlp_options *options,
-                                  char *buf)
-{
-       return sprintf(buf, "%u\n",
-                      options->pca_base_priority);
-}
-EXPORT_SYMBOL_GPL(uwb_pca_base_priority_show);
-
-
-/**
- * Set the PCA base priority.
- *
- * We can access without locking, as the value is (for now) orthogonal
- * to other values.
- */
-ssize_t uwb_pca_base_priority_store(struct wlp_options *options,
-                                   const char *buf, size_t size)
-{
-       ssize_t result = -EINVAL;
-       u8 pca_base_priority;
-
-       result = sscanf(buf, "%hhu\n", &pca_base_priority);
-       if (result != 1) {
-               result = -EINVAL;
-               goto out;
-       }
-       result = -EINVAL;
-       if (pca_base_priority >= 8)
-               goto out;
-       options->pca_base_priority = pca_base_priority;
-       /* Update TX header if we are currently using PCA. */
-       if (result >= 0 && (wlp_tx_hdr_delivery_id_type(&options->def_tx_hdr) & WLP_DRP) == 0)
-               wlp_tx_hdr_set_delivery_id_type(&options->def_tx_hdr, options->pca_base_priority);
-       result = 0;
-out:
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(uwb_pca_base_priority_store);
-
-/**
- * Show current inflight values
- *
- * Will print the current MAX and THRESHOLD values for the basic flow
- * control. In addition it will report how many times the TX queue needed
- * to be restarted since the last time this query was made.
- */
-static ssize_t wlp_tx_inflight_show(struct i1480u_tx_inflight *inflight,
-                                   char *buf)
-{
-       ssize_t result;
-       unsigned long sec_elapsed = (jiffies - inflight->restart_ts)/HZ;
-       unsigned long restart_count = atomic_read(&inflight->restart_count);
-
-       result = scnprintf(buf, PAGE_SIZE, "%lu %lu %d %lu %lu %lu\n"
-                          "#read: threshold max inflight_count restarts "
-                          "seconds restarts/sec\n"
-                          "#write: threshold max\n",
-                          inflight->threshold, inflight->max,
-                          atomic_read(&inflight->count),
-                          restart_count, sec_elapsed,
-                          sec_elapsed == 0 ? 0 : restart_count/sec_elapsed);
-       inflight->restart_ts = jiffies;
-       atomic_set(&inflight->restart_count, 0);
-       return result;
-}
-
-static
-ssize_t wlp_tx_inflight_store(struct i1480u_tx_inflight *inflight,
-                               const char *buf, size_t size)
-{
-       unsigned long in_threshold, in_max;
-       ssize_t result;
-       result = sscanf(buf, "%lu %lu", &in_threshold, &in_max);
-       if (result != 2)
-               return -EINVAL;
-       if (in_max <= in_threshold)
-               return -EINVAL;
-       inflight->max = in_max;
-       inflight->threshold = in_threshold;
-       return size;
-}
-/*
- * Glue (or function adaptors) for accesing info on sysfs
- *
- * [we need this indirection because the PCI driver does almost the
- * same]
- *
- * Linux 2.6.21 changed how 'struct netdevice' does attributes (from
- * having a 'struct class_dev' to having a 'struct device'). That is
- * quite of a pain.
- *
- * So we try to abstract that here. i1480u_SHOW() and i1480u_STORE()
- * create adaptors for extracting the 'struct i1480u' from a 'struct
- * dev' and calling a function for doing a sysfs operation (as we have
- * them factorized already). i1480u_ATTR creates the attribute file
- * (CLASS_DEVICE_ATTR or DEVICE_ATTR) and i1480u_ATTR_NAME produces a
- * class_device_attr_NAME or device_attr_NAME (for group registration).
- */
-
-#define i1480u_SHOW(name, fn, param)                           \
-static ssize_t i1480u_show_##name(struct device *dev,          \
-                                 struct device_attribute *attr,\
-                                 char *buf)                    \
-{                                                              \
-       struct i1480u *i1480u = netdev_priv(to_net_dev(dev));   \
-       return fn(&i1480u->param, buf);                         \
-}
-
-#define i1480u_STORE(name, fn, param)                          \
-static ssize_t i1480u_store_##name(struct device *dev,         \
-                                  struct device_attribute *attr,\
-                                  const char *buf, size_t size)\
-{                                                              \
-       struct i1480u *i1480u = netdev_priv(to_net_dev(dev));   \
-       return fn(&i1480u->param, buf, size);                   \
-}
-
-#define i1480u_ATTR(name, perm) static DEVICE_ATTR(name, perm,  \
-                                            i1480u_show_##name,\
-                                            i1480u_store_##name)
-
-#define i1480u_ATTR_SHOW(name) static DEVICE_ATTR(name,                \
-                                       S_IRUGO,                \
-                                       i1480u_show_##name, NULL)
-
-#define i1480u_ATTR_NAME(a) (dev_attr_##a)
-
-
-/*
- * Sysfs adaptors
- */
-i1480u_SHOW(uwb_phy_rate, uwb_phy_rate_show, options);
-i1480u_STORE(uwb_phy_rate, uwb_phy_rate_store, options);
-i1480u_ATTR(uwb_phy_rate, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(uwb_rts_cts, uwb_rts_cts_show, options);
-i1480u_STORE(uwb_rts_cts, uwb_rts_cts_store, options);
-i1480u_ATTR(uwb_rts_cts, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(uwb_ack_policy, uwb_ack_policy_show, options);
-i1480u_STORE(uwb_ack_policy, uwb_ack_policy_store, options);
-i1480u_ATTR(uwb_ack_policy, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(uwb_pca_base_priority, uwb_pca_base_priority_show, options);
-i1480u_STORE(uwb_pca_base_priority, uwb_pca_base_priority_store, options);
-i1480u_ATTR(uwb_pca_base_priority, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_eda, wlp_eda_show, wlp);
-i1480u_STORE(wlp_eda, wlp_eda_store, wlp);
-i1480u_ATTR(wlp_eda, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_uuid, wlp_uuid_show, wlp);
-i1480u_STORE(wlp_uuid, wlp_uuid_store, wlp);
-i1480u_ATTR(wlp_uuid, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_name, wlp_dev_name_show, wlp);
-i1480u_STORE(wlp_dev_name, wlp_dev_name_store, wlp);
-i1480u_ATTR(wlp_dev_name, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_manufacturer, wlp_dev_manufacturer_show, wlp);
-i1480u_STORE(wlp_dev_manufacturer, wlp_dev_manufacturer_store, wlp);
-i1480u_ATTR(wlp_dev_manufacturer, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_model_name, wlp_dev_model_name_show, wlp);
-i1480u_STORE(wlp_dev_model_name, wlp_dev_model_name_store, wlp);
-i1480u_ATTR(wlp_dev_model_name, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_model_nr, wlp_dev_model_nr_show, wlp);
-i1480u_STORE(wlp_dev_model_nr, wlp_dev_model_nr_store, wlp);
-i1480u_ATTR(wlp_dev_model_nr, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_serial, wlp_dev_serial_show, wlp);
-i1480u_STORE(wlp_dev_serial, wlp_dev_serial_store, wlp);
-i1480u_ATTR(wlp_dev_serial, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_prim_category, wlp_dev_prim_category_show, wlp);
-i1480u_STORE(wlp_dev_prim_category, wlp_dev_prim_category_store, wlp);
-i1480u_ATTR(wlp_dev_prim_category, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_prim_OUI, wlp_dev_prim_OUI_show, wlp);
-i1480u_STORE(wlp_dev_prim_OUI, wlp_dev_prim_OUI_store, wlp);
-i1480u_ATTR(wlp_dev_prim_OUI, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_show, wlp);
-i1480u_STORE(wlp_dev_prim_OUI_sub, wlp_dev_prim_OUI_sub_store, wlp);
-i1480u_ATTR(wlp_dev_prim_OUI_sub, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_dev_prim_subcat, wlp_dev_prim_subcat_show, wlp);
-i1480u_STORE(wlp_dev_prim_subcat, wlp_dev_prim_subcat_store, wlp);
-i1480u_ATTR(wlp_dev_prim_subcat, S_IRUGO | S_IWUSR);
-
-i1480u_SHOW(wlp_neighborhood, wlp_neighborhood_show, wlp);
-i1480u_ATTR_SHOW(wlp_neighborhood);
-
-i1480u_SHOW(wss_activate, wlp_wss_activate_show, wlp.wss);
-i1480u_STORE(wss_activate, wlp_wss_activate_store, wlp.wss);
-i1480u_ATTR(wss_activate, S_IRUGO | S_IWUSR);
-
-/*
- * Show the (min, max, avg) Line Quality Estimate (LQE, in dB) as over
- * the last 256 received WLP frames (ECMA-368 13.3).
- *
- * [the -7dB that have to be substracted from the LQI to make the LQE
- * are already taken into account].
- */
-i1480u_SHOW(wlp_lqe, stats_show, lqe_stats);
-i1480u_STORE(wlp_lqe, stats_store, lqe_stats);
-i1480u_ATTR(wlp_lqe, S_IRUGO | S_IWUSR);
-
-/*
- * Show the Receive Signal Strength Indicator averaged over all the
- * received WLP frames (ECMA-368 13.3). Still is not clear what
- * this value is, but is kind of a percentage of the signal strength
- * at the antenna.
- */
-i1480u_SHOW(wlp_rssi, stats_show, rssi_stats);
-i1480u_STORE(wlp_rssi, stats_store, rssi_stats);
-i1480u_ATTR(wlp_rssi, S_IRUGO | S_IWUSR);
-
-/**
- * We maintain a basic flow control counter. "count" how many TX URBs are
- * outstanding. Only allow "max"
- * TX URBs to be outstanding. If this value is reached the queue will be
- * stopped. The queue will be restarted when there are
- * "threshold" URBs outstanding.
- */
-i1480u_SHOW(wlp_tx_inflight, wlp_tx_inflight_show, tx_inflight);
-i1480u_STORE(wlp_tx_inflight, wlp_tx_inflight_store, tx_inflight);
-i1480u_ATTR(wlp_tx_inflight, S_IRUGO | S_IWUSR);
-
-static struct attribute *i1480u_attrs[] = {
-       &i1480u_ATTR_NAME(uwb_phy_rate).attr,
-       &i1480u_ATTR_NAME(uwb_rts_cts).attr,
-       &i1480u_ATTR_NAME(uwb_ack_policy).attr,
-       &i1480u_ATTR_NAME(uwb_pca_base_priority).attr,
-       &i1480u_ATTR_NAME(wlp_lqe).attr,
-       &i1480u_ATTR_NAME(wlp_rssi).attr,
-       &i1480u_ATTR_NAME(wlp_eda).attr,
-       &i1480u_ATTR_NAME(wlp_uuid).attr,
-       &i1480u_ATTR_NAME(wlp_dev_name).attr,
-       &i1480u_ATTR_NAME(wlp_dev_manufacturer).attr,
-       &i1480u_ATTR_NAME(wlp_dev_model_name).attr,
-       &i1480u_ATTR_NAME(wlp_dev_model_nr).attr,
-       &i1480u_ATTR_NAME(wlp_dev_serial).attr,
-       &i1480u_ATTR_NAME(wlp_dev_prim_category).attr,
-       &i1480u_ATTR_NAME(wlp_dev_prim_OUI).attr,
-       &i1480u_ATTR_NAME(wlp_dev_prim_OUI_sub).attr,
-       &i1480u_ATTR_NAME(wlp_dev_prim_subcat).attr,
-       &i1480u_ATTR_NAME(wlp_neighborhood).attr,
-       &i1480u_ATTR_NAME(wss_activate).attr,
-       &i1480u_ATTR_NAME(wlp_tx_inflight).attr,
-       NULL,
-};
-
-static struct attribute_group i1480u_attr_group = {
-       .name = NULL,   /* we want them in the same directory */
-       .attrs = i1480u_attrs,
-};
-
-int i1480u_sysfs_setup(struct i1480u *i1480u)
-{
-       int result;
-       struct device *dev = &i1480u->usb_iface->dev;
-       result = sysfs_create_group(&i1480u->net_dev->dev.kobj,
-                                   &i1480u_attr_group);
-       if (result < 0)
-               dev_err(dev, "cannot initialize sysfs attributes: %d\n",
-                       result);
-       return result;
-}
-
-
-void i1480u_sysfs_release(struct i1480u *i1480u)
-{
-       sysfs_remove_group(&i1480u->net_dev->dev.kobj,
-                          &i1480u_attr_group);
-}
diff --git a/drivers/uwb/i1480/i1480u-wlp/tx.c b/drivers/uwb/i1480/i1480u-wlp/tx.c
deleted file mode 100644 (file)
index 3c117a3..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Deal with TX (massaging data to transmit, handling it)
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Transmission engine. Get an skb, create from that a WLP transmit
- * context, add a WLP TX header (which we keep prefilled in the
- * device's instance), fill out the target-specific fields and
- * fire it.
- *
- * ROADMAP:
- *
- *   Entry points:
- *
- *     i1480u_tx_release(): called by i1480u_disconnect() to release
- *                          pending tx contexts.
- *
- *     i1480u_tx_cb(): callback for TX contexts (USB URBs)
- *       i1480u_tx_destroy():
- *
- *     i1480u_tx_timeout(): called for timeout handling from the
- *                          network stack.
- *
- *     i1480u_hard_start_xmit(): called for transmitting an skb from
- *                               the network stack. Will interact with WLP
- *                               substack to verify and prepare frame.
- *       i1480u_xmit_frame(): actual transmission on hardware
- *
- *         i1480u_tx_create()      Creates TX context
- *            i1480u_tx_create_1()    For packets in 1 fragment
- *            i1480u_tx_create_n()    For packets in >1 fragments
- *
- * TODO:
- *
- * - FIXME: rewrite using usb_sg_*(), add asynch support to
- *          usb_sg_*(). It might not make too much sense as most of
- *          the times the MTU will be smaller than one page...
- */
-
-#include <linux/slab.h>
-#include "i1480u-wlp.h"
-
-enum {
-       /* This is only for Next and Last TX packets */
-       i1480u_MAX_PL_SIZE = i1480u_MAX_FRG_SIZE
-               - sizeof(struct untd_hdr_rst),
-};
-
-/* Free resources allocated to a i1480u tx context. */
-static
-void i1480u_tx_free(struct i1480u_tx *wtx)
-{
-       kfree(wtx->buf);
-       if (wtx->skb)
-               dev_kfree_skb_irq(wtx->skb);
-       usb_free_urb(wtx->urb);
-       kfree(wtx);
-}
-
-static
-void i1480u_tx_destroy(struct i1480u *i1480u, struct i1480u_tx *wtx)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);        /* not active any more */
-       list_del(&wtx->list_node);
-       i1480u_tx_free(wtx);
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-}
-
-static
-void i1480u_tx_unlink_urbs(struct i1480u *i1480u)
-{
-       unsigned long flags;
-       struct i1480u_tx *wtx, *next;
-
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
-               usb_unlink_urb(wtx->urb);
-       }
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-}
-
-
-/*
- * Callback for a completed tx USB URB.
- *
- * TODO:
- *
- * - FIXME: recover errors more gracefully
- * - FIXME: handle NAKs (I dont think they come here) for flow ctl
- */
-static
-void i1480u_tx_cb(struct urb *urb)
-{
-       struct i1480u_tx *wtx = urb->context;
-       struct i1480u *i1480u = wtx->i1480u;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct device *dev = &i1480u->usb_iface->dev;
-       unsigned long flags;
-
-       switch (urb->status) {
-       case 0:
-               spin_lock_irqsave(&i1480u->lock, flags);
-               net_dev->stats.tx_packets++;
-               net_dev->stats.tx_bytes += urb->actual_length;
-               spin_unlock_irqrestore(&i1480u->lock, flags);
-               break;
-       case -ECONNRESET:       /* Not an error, but a controlled situation; */
-       case -ENOENT:           /* (we killed the URB)...so, no broadcast */
-               dev_dbg(dev, "notif endp: reset/noent %d\n", urb->status);
-               netif_stop_queue(net_dev);
-               break;
-       case -ESHUTDOWN:        /* going away! */
-               dev_dbg(dev, "notif endp: down %d\n", urb->status);
-               netif_stop_queue(net_dev);
-               break;
-       default:
-               dev_err(dev, "TX: unknown URB status %d\n", urb->status);
-               if (edc_inc(&i1480u->tx_errors, EDC_MAX_ERRORS,
-                                       EDC_ERROR_TIMEFRAME)) {
-                       dev_err(dev, "TX: max acceptable errors exceeded."
-                                       "Reset device.\n");
-                       netif_stop_queue(net_dev);
-                       i1480u_tx_unlink_urbs(i1480u);
-                       wlp_reset_all(&i1480u->wlp);
-               }
-               break;
-       }
-       i1480u_tx_destroy(i1480u, wtx);
-       if (atomic_dec_return(&i1480u->tx_inflight.count)
-           <= i1480u->tx_inflight.threshold
-           && netif_queue_stopped(net_dev)
-           && i1480u->tx_inflight.threshold != 0) {
-               netif_start_queue(net_dev);
-               atomic_inc(&i1480u->tx_inflight.restart_count);
-       }
-       return;
-}
-
-
-/*
- * Given a buffer that doesn't fit in a single fragment, create an
- * scatter/gather structure for delivery to the USB pipe.
- *
- * Implements functionality of i1480u_tx_create().
- *
- * @wtx:       tx descriptor
- * @skb:       skb to send
- * @gfp_mask:  gfp allocation mask
- * @returns:    Pointer to @wtx if ok, NULL on error.
- *
- * Sorry, TOO LONG a function, but breaking it up is kind of hard
- *
- * This will break the buffer in chunks smaller than
- * i1480u_MAX_FRG_SIZE (including the header) and add proper headers
- * to each:
- *
- *   1st header           \
- *   i1480 tx header      |  fragment 1
- *   fragment data        /
- *   nxt header           \  fragment 2
- *   fragment data        /
- *   ..
- *   ..
- *   last header          \  fragment 3
- *   last fragment data   /
- *
- * This does not fill the i1480 TX header, it is left up to the
- * caller to do that; you can get it from @wtx->wlp_tx_hdr.
- *
- * This function consumes the skb unless there is an error.
- */
-static
-int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
-                      gfp_t gfp_mask)
-{
-       int result;
-       void *pl;
-       size_t pl_size;
-
-       void *pl_itr, *buf_itr;
-       size_t pl_size_left, frgs, pl_size_1st, frg_pl_size = 0;
-       struct untd_hdr_1st *untd_hdr_1st;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-       struct untd_hdr_rst *untd_hdr_rst;
-
-       wtx->skb = NULL;
-       pl = skb->data;
-       pl_itr = pl;
-       pl_size = skb->len;
-       pl_size_left = pl_size; /* payload size */
-       /* First fragment; fits as much as i1480u_MAX_FRG_SIZE minus
-        * the headers */
-       pl_size_1st = i1480u_MAX_FRG_SIZE
-               - sizeof(struct untd_hdr_1st) - sizeof(struct wlp_tx_hdr);
-       BUG_ON(pl_size_1st > pl_size);
-       pl_size_left -= pl_size_1st;
-       /* The rest have an smaller header (no i1480 TX header). We
-        * need to break up the payload in blocks smaller than
-        * i1480u_MAX_PL_SIZE (payload excluding header). */
-       frgs = (pl_size_left + i1480u_MAX_PL_SIZE - 1) / i1480u_MAX_PL_SIZE;
-       /* Allocate space for the new buffer. In this new buffer we'll
-        * place the headers followed by the data fragment, headers,
-        * data fragments, etc..
-        */
-       result = -ENOMEM;
-       wtx->buf_size = sizeof(*untd_hdr_1st)
-               + sizeof(*wlp_tx_hdr)
-               + frgs * sizeof(*untd_hdr_rst)
-               + pl_size;
-       wtx->buf = kmalloc(wtx->buf_size, gfp_mask);
-       if (wtx->buf == NULL)
-               goto error_buf_alloc;
-
-       buf_itr = wtx->buf;             /* We got the space, let's fill it up */
-       /* Fill 1st fragment */
-       untd_hdr_1st = buf_itr;
-       buf_itr += sizeof(*untd_hdr_1st);
-       untd_hdr_set_type(&untd_hdr_1st->hdr, i1480u_PKT_FRAG_1ST);
-       untd_hdr_set_rx_tx(&untd_hdr_1st->hdr, 0);
-       untd_hdr_1st->hdr.len = cpu_to_le16(pl_size + sizeof(*wlp_tx_hdr));
-       untd_hdr_1st->fragment_len =
-               cpu_to_le16(pl_size_1st + sizeof(*wlp_tx_hdr));
-       memset(untd_hdr_1st->padding, 0, sizeof(untd_hdr_1st->padding));
-       /* Set up i1480 header info */
-       wlp_tx_hdr = wtx->wlp_tx_hdr = buf_itr;
-       buf_itr += sizeof(*wlp_tx_hdr);
-       /* Copy the first fragment */
-       memcpy(buf_itr, pl_itr, pl_size_1st);
-       pl_itr += pl_size_1st;
-       buf_itr += pl_size_1st;
-
-       /* Now do each remaining fragment */
-       result = -EINVAL;
-       while (pl_size_left > 0) {
-               if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf
-                   > wtx->buf_size) {
-                       printk(KERN_ERR "BUG: no space for header\n");
-                       goto error_bug;
-               }
-               untd_hdr_rst = buf_itr;
-               buf_itr += sizeof(*untd_hdr_rst);
-               if (pl_size_left > i1480u_MAX_PL_SIZE) {
-                       frg_pl_size = i1480u_MAX_PL_SIZE;
-                       untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_NXT);
-               } else {
-                       frg_pl_size = pl_size_left;
-                       untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST);
-               }
-               untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0);
-               untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size);
-               untd_hdr_rst->padding = 0;
-               if (buf_itr + frg_pl_size - wtx->buf
-                   > wtx->buf_size) {
-                       printk(KERN_ERR "BUG: no space for payload\n");
-                       goto error_bug;
-               }
-               memcpy(buf_itr, pl_itr, frg_pl_size);
-               buf_itr += frg_pl_size;
-               pl_itr += frg_pl_size;
-               pl_size_left -= frg_pl_size;
-       }
-       dev_kfree_skb_irq(skb);
-       return 0;
-
-error_bug:
-       printk(KERN_ERR
-              "BUG: skb %u bytes\n"
-              "BUG: frg_pl_size %zd i1480u_MAX_FRG_SIZE %u\n"
-              "BUG: buf_itr %zu buf_size %zu pl_size_left %zu\n",
-              skb->len,
-              frg_pl_size, i1480u_MAX_FRG_SIZE,
-              buf_itr - wtx->buf, wtx->buf_size, pl_size_left);
-
-       kfree(wtx->buf);
-error_buf_alloc:
-       return result;
-}
-
-
-/*
- * Given a buffer that fits in a single fragment, fill out a @wtx
- * struct for transmitting it down the USB pipe.
- *
- * Uses the fact that we have space reserved in front of the skbuff
- * for hardware headers :]
- *
- * This does not fill the i1480 TX header, it is left up to the
- * caller to do that; you can get it from @wtx->wlp_tx_hdr.
- *
- * @pl:                pointer to payload data
- * @pl_size:    size of the payuload
- *
- * This function does not consume the @skb.
- */
-static
-int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb,
-                      gfp_t gfp_mask)
-{
-       struct untd_hdr_cmp *untd_hdr_cmp;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-
-       wtx->buf = NULL;
-       wtx->skb = skb;
-       BUG_ON(skb_headroom(skb) < sizeof(*wlp_tx_hdr));
-       wlp_tx_hdr = (void *) __skb_push(skb, sizeof(*wlp_tx_hdr));
-       wtx->wlp_tx_hdr = wlp_tx_hdr;
-       BUG_ON(skb_headroom(skb) < sizeof(*untd_hdr_cmp));
-       untd_hdr_cmp = (void *) __skb_push(skb, sizeof(*untd_hdr_cmp));
-
-       untd_hdr_set_type(&untd_hdr_cmp->hdr, i1480u_PKT_FRAG_CMP);
-       untd_hdr_set_rx_tx(&untd_hdr_cmp->hdr, 0);
-       untd_hdr_cmp->hdr.len = cpu_to_le16(skb->len - sizeof(*untd_hdr_cmp));
-       untd_hdr_cmp->padding = 0;
-       return 0;
-}
-
-
-/*
- * Given a skb to transmit, massage it to become palatable for the TX pipe
- *
- * This will break the buffer in chunks smaller than
- * i1480u_MAX_FRG_SIZE and add proper headers to each.
- *
- *   1st header           \
- *   i1480 tx header      |  fragment 1
- *   fragment data        /
- *   nxt header           \  fragment 2
- *   fragment data        /
- *   ..
- *   ..
- *   last header          \  fragment 3
- *   last fragment data   /
- *
- * Each fragment will be always smaller or equal to i1480u_MAX_FRG_SIZE.
- *
- * If the first fragment is smaller than i1480u_MAX_FRG_SIZE, then the
- * following is composed:
- *
- *   complete header      \
- *   i1480 tx header      | single fragment
- *   packet data          /
- *
- * We were going to use s/g support, but because the interface is
- * synch and at the end there is plenty of overhead to do it, it
- * didn't seem that worth for data that is going to be smaller than
- * one page.
- */
-static
-struct i1480u_tx *i1480u_tx_create(struct i1480u *i1480u,
-                                  struct sk_buff *skb, gfp_t gfp_mask)
-{
-       int result;
-       struct usb_endpoint_descriptor *epd;
-       int usb_pipe;
-       unsigned long flags;
-
-       struct i1480u_tx *wtx;
-       const size_t pl_max_size =
-               i1480u_MAX_FRG_SIZE - sizeof(struct untd_hdr_cmp)
-               - sizeof(struct wlp_tx_hdr);
-
-       wtx = kmalloc(sizeof(*wtx), gfp_mask);
-       if (wtx == NULL)
-               goto error_wtx_alloc;
-       wtx->urb = usb_alloc_urb(0, gfp_mask);
-       if (wtx->urb == NULL)
-               goto error_urb_alloc;
-       epd = &i1480u->usb_iface->cur_altsetting->endpoint[2].desc;
-       usb_pipe = usb_sndbulkpipe(i1480u->usb_dev, epd->bEndpointAddress);
-       /* Fits in a single complete packet or need to split? */
-       if (skb->len > pl_max_size) {
-               result = i1480u_tx_create_n(wtx, skb, gfp_mask);
-               if (result < 0)
-                       goto error_create;
-               usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
-                                 wtx->buf, wtx->buf_size, i1480u_tx_cb, wtx);
-       } else {
-               result = i1480u_tx_create_1(wtx, skb, gfp_mask);
-               if (result < 0)
-                       goto error_create;
-               usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
-                                 skb->data, skb->len, i1480u_tx_cb, wtx);
-       }
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_add(&wtx->list_node, &i1480u->tx_list);
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-       return wtx;
-
-error_create:
-       kfree(wtx->urb);
-error_urb_alloc:
-       kfree(wtx);
-error_wtx_alloc:
-       return NULL;
-}
-
-/*
- * Actual fragmentation and transmission of frame
- *
- * @wlp:  WLP substack data structure
- * @skb:  To be transmitted
- * @dst:  Device address of destination
- * @returns: 0 on success, <0 on failure
- *
- * This function can also be called directly (not just from
- * hard_start_xmit), so we also check here if the interface is up before
- * taking sending anything.
- */
-int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
-                     struct uwb_dev_addr *dst)
-{
-       int result = -ENXIO;
-       struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct i1480u_tx *wtx;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-       static unsigned char dev_bcast[2] = { 0xff, 0xff };
-
-       BUG_ON(i1480u->wlp.rc == NULL);
-       if ((net_dev->flags & IFF_UP) == 0)
-               goto out;
-       result = -EBUSY;
-       if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) {
-               netif_stop_queue(net_dev);
-               goto error_max_inflight;
-       }
-       result = -ENOMEM;
-       wtx = i1480u_tx_create(i1480u, skb, GFP_ATOMIC);
-       if (unlikely(wtx == NULL)) {
-               if (printk_ratelimit())
-                       dev_err(dev, "TX: no memory for WLP TX URB,"
-                               "dropping packet (in flight %d)\n",
-                               atomic_read(&i1480u->tx_inflight.count));
-               netif_stop_queue(net_dev);
-               goto error_wtx_alloc;
-       }
-       wtx->i1480u = i1480u;
-       /* Fill out the i1480 header; @i1480u->def_tx_hdr read without
-        * locking. We do so because they are kind of orthogonal to
-        * each other (and thus not changed in an atomic batch).
-        * The ETH header is right after the WLP TX header. */
-       wlp_tx_hdr = wtx->wlp_tx_hdr;
-       *wlp_tx_hdr = i1480u->options.def_tx_hdr;
-       wlp_tx_hdr->dstaddr = *dst;
-       if (!memcmp(&wlp_tx_hdr->dstaddr, dev_bcast, sizeof(dev_bcast))
-           && (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)) {
-               /*Broadcast message directed to DRP host. Send as best effort
-                * on PCA. */
-               wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority);
-       }
-
-       result = usb_submit_urb(wtx->urb, GFP_ATOMIC);          /* Go baby */
-       if (result < 0) {
-               dev_err(dev, "TX: cannot submit URB: %d\n", result);
-               /* We leave the freeing of skb to calling function */
-               wtx->skb = NULL;
-               goto error_tx_urb_submit;
-       }
-       atomic_inc(&i1480u->tx_inflight.count);
-       net_dev->trans_start = jiffies;
-       return result;
-
-error_tx_urb_submit:
-       i1480u_tx_destroy(i1480u, wtx);
-error_wtx_alloc:
-error_max_inflight:
-out:
-       return result;
-}
-
-
-/*
- * Transmit an skb  Called when an skbuf has to be transmitted
- *
- * The skb is first passed to WLP substack to ensure this is a valid
- * frame. If valid the device address of destination will be filled and
- * the WLP header prepended to the skb. If this step fails we fake sending
- * the frame, if we return an error the network stack will just keep trying.
- *
- * Broadcast frames inside a WSS needs to be treated special as multicast is
- * not supported. A broadcast frame is sent as unicast to each member of the
- * WSS - this is done by the WLP substack when it finds a broadcast frame.
- * So, we test if the WLP substack took over the skb and only transmit it
- * if it has not (been taken over).
- *
- * @net_dev->xmit_lock is held
- */
-netdev_tx_t i1480u_hard_start_xmit(struct sk_buff *skb,
-                                        struct net_device *net_dev)
-{
-       int result;
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct uwb_dev_addr dst;
-
-       if ((net_dev->flags & IFF_UP) == 0)
-               goto error;
-       result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst);
-       if (result < 0) {
-               dev_err(dev, "WLP verification of TX frame failed (%d). "
-                       "Dropping packet.\n", result);
-               goto error;
-       } else if (result == 1) {
-               /* trans_start time will be set when WLP actually transmits
-                * the frame */
-               goto out;
-       }
-       result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst);
-       if (result < 0) {
-               dev_err(dev, "Frame TX failed (%d).\n", result);
-               goto error;
-       }
-       return NETDEV_TX_OK;
-error:
-       dev_kfree_skb_any(skb);
-       net_dev->stats.tx_dropped++;
-out:
-       return NETDEV_TX_OK;
-}
-
-
-/*
- * Called when a pkt transmission doesn't complete in a reasonable period
- * Device reset may sleep - do it outside of interrupt context (delayed)
- */
-void i1480u_tx_timeout(struct net_device *net_dev)
-{
-       struct i1480u *i1480u = netdev_priv(net_dev);
-
-       wlp_reset_all(&i1480u->wlp);
-}
-
-
-void i1480u_tx_release(struct i1480u *i1480u)
-{
-       unsigned long flags;
-       struct i1480u_tx *wtx, *next;
-       int count = 0, empty;
-
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
-               count++;
-               usb_unlink_urb(wtx->urb);
-       }
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-       count = count*10; /* i1480ut 200ms per unlinked urb (intervals of 20ms) */
-       /*
-        * We don't like this sollution too much (dirty as it is), but
-        * it is cheaper than putting a refcount on each i1480u_tx and
-        * i1480uting for all of them to go away...
-        *
-        * Called when no more packets can be added to tx_list
-        * so can i1480ut for it to be empty.
-        */
-       while (1) {
-               spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-               empty = list_empty(&i1480u->tx_list);
-               spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-               if (empty)
-                       break;
-               count--;
-               BUG_ON(count == 0);
-               msleep(20);
-       }
-}
diff --git a/drivers/uwb/wlp/Makefile b/drivers/uwb/wlp/Makefile
deleted file mode 100644 (file)
index c72c11d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-$(CONFIG_UWB_WLP) := wlp.o
-
-wlp-objs :=    \
-       driver.o        \
-       eda.o           \
-       messages.o      \
-       sysfs.o         \
-       txrx.o          \
-       wlp-lc.o        \
-       wss-lc.o
diff --git a/drivers/uwb/wlp/driver.c b/drivers/uwb/wlp/driver.c
deleted file mode 100644 (file)
index cb8d699..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Life cycle of WLP substack
- *
- * FIXME: Docs
- */
-
-#include <linux/module.h>
-
-static int __init wlp_subsys_init(void)
-{
-       return 0;
-}
-module_init(wlp_subsys_init);
-
-static void __exit wlp_subsys_exit(void)
-{
-       return;
-}
-module_exit(wlp_subsys_exit);
-
-MODULE_AUTHOR("Reinette Chatre <reinette.chatre@intel.com>");
-MODULE_DESCRIPTION("WiMedia Logical Link Control Protocol (WLP)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/uwb/wlp/eda.c b/drivers/uwb/wlp/eda.c
deleted file mode 100644 (file)
index 086fc0c..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Ethernet to device address cache
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * We need to be able to map ethernet addresses to device addresses
- * and back because there is not explicit relationship between the eth
- * addresses used in the ETH frames and the device addresses (no, it
- * would not have been simpler to force as ETH address the MBOA MAC
- * address...no, not at all :).
- *
- * A device has one MBOA MAC address and one device address. It is possible
- * for a device to have more than one virtual MAC address (although a
- * virtual address can be the same as the MBOA MAC address). The device
- * address is guaranteed to be unique among the devices in the extended
- * beacon group (see ECMA 17.1.1). We thus use the device address as index
- * to this cache. We do allow searching based on virtual address as this
- * is how Ethernet frames will be addressed.
- *
- * We need to support virtual EUI-48. Although, right now the virtual
- * EUI-48 will always be the same as the MAC SAP address. The EDA cache
- * entry thus contains a MAC SAP address as well as the virtual address
- * (used to map the network stack address to a neighbor). When we move
- * to support more than one virtual MAC on a host then this organization
- * will have to change. Perhaps a neighbor has a list of WSSs, each with a
- * tag and virtual EUI-48.
- *
- * On data transmission
- * it is used to determine if the neighbor is connected and what WSS it
- * belongs to. With this we know what tag to add to the WLP frame. Storing
- * the WSS in the EDA cache may be overkill because we only support one
- * WSS. Hopefully we will support more than one WSS at some point.
- * On data reception it is used to determine the WSS based on
- * the tag and address of the transmitting neighbor.
- */
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/wlp.h>
-#include "wlp-internal.h"
-
-
-/* FIXME: cache is not purged, only on device close */
-
-/* FIXME: does not scale, change to dynamic array */
-
-/*
- * Initialize the EDA cache
- *
- * @returns 0 if ok, < 0 errno code on error
- *
- * Call when the interface is being brought up
- *
- * NOTE: Keep it as a separate function as the implementation will
- *       change and be more complex.
- */
-void wlp_eda_init(struct wlp_eda *eda)
-{
-       INIT_LIST_HEAD(&eda->cache);
-       spin_lock_init(&eda->lock);
-}
-
-/*
- * Release the EDA cache
- *
- * @returns 0 if ok, < 0 errno code on error
- *
- * Called when the interface is brought down
- */
-void wlp_eda_release(struct wlp_eda *eda)
-{
-       unsigned long flags;
-       struct wlp_eda_node *itr, *next;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
-               list_del(&itr->list_node);
-               kfree(itr);
-       }
-       spin_unlock_irqrestore(&eda->lock, flags);
-}
-
-/*
- * Add an address mapping
- *
- * @returns 0 if ok, < 0 errno code on error
- *
- * An address mapping is initially created when the neighbor device is seen
- * for the first time (it is "onair"). At this time the neighbor is not
- * connected or associated with a WSS so we only populate the Ethernet and
- * Device address fields.
- *
- */
-int wlp_eda_create_node(struct wlp_eda *eda,
-                       const unsigned char eth_addr[ETH_ALEN],
-                       const struct uwb_dev_addr *dev_addr)
-{
-       int result = 0;
-       struct wlp_eda_node *itr;
-       unsigned long flags;
-
-       BUG_ON(dev_addr == NULL || eth_addr == NULL);
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(itr, &eda->cache, list_node) {
-               if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
-                       printk(KERN_ERR "EDA cache already contains entry "
-                              "for neighbor %02x:%02x\n",
-                              dev_addr->data[1], dev_addr->data[0]);
-                       result = -EEXIST;
-                       goto out_unlock;
-               }
-       }
-       itr = kzalloc(sizeof(*itr), GFP_ATOMIC);
-       if (itr != NULL) {
-               memcpy(itr->eth_addr, eth_addr, sizeof(itr->eth_addr));
-               itr->dev_addr = *dev_addr;
-               list_add(&itr->list_node, &eda->cache);
-       } else
-               result = -ENOMEM;
-out_unlock:
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-/*
- * Remove entry from EDA cache
- *
- * This is done when the device goes off air.
- */
-void wlp_eda_rm_node(struct wlp_eda *eda, const struct uwb_dev_addr *dev_addr)
-{
-       struct wlp_eda_node *itr, *next;
-       unsigned long flags;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry_safe(itr, next, &eda->cache, list_node) {
-               if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
-                       list_del(&itr->list_node);
-                       kfree(itr);
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&eda->lock, flags);
-}
-
-/*
- * Update an address mapping
- *
- * @returns 0 if ok, < 0 errno code on error
- */
-int wlp_eda_update_node(struct wlp_eda *eda,
-                       const struct uwb_dev_addr *dev_addr,
-                       struct wlp_wss *wss,
-                       const unsigned char virt_addr[ETH_ALEN],
-                       const u8 tag, const enum wlp_wss_connect state)
-{
-       int result = -ENOENT;
-       struct wlp_eda_node *itr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(itr, &eda->cache, list_node) {
-               if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
-                       /* Found it, update it */
-                       itr->wss = wss;
-                       memcpy(itr->virt_addr, virt_addr,
-                              sizeof(itr->virt_addr));
-                       itr->tag = tag;
-                       itr->state = state;
-                       result = 0;
-                       goto out_unlock;
-               }
-       }
-       /* Not found */
-out_unlock:
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-/*
- * Update only state field of an address mapping
- *
- * @returns 0 if ok, < 0 errno code on error
- */
-int wlp_eda_update_node_state(struct wlp_eda *eda,
-                             const struct uwb_dev_addr *dev_addr,
-                             const enum wlp_wss_connect state)
-{
-       int result = -ENOENT;
-       struct wlp_eda_node *itr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(itr, &eda->cache, list_node) {
-               if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
-                       /* Found it, update it */
-                       itr->state = state;
-                       result = 0;
-                       goto out_unlock;
-               }
-       }
-       /* Not found */
-out_unlock:
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-/*
- * Return contents of EDA cache entry
- *
- * @dev_addr: index to EDA cache
- * @eda_entry: pointer to where contents of EDA cache will be copied
- */
-int wlp_copy_eda_node(struct wlp_eda *eda, struct uwb_dev_addr *dev_addr,
-                     struct wlp_eda_node *eda_entry)
-{
-       int result = -ENOENT;
-       struct wlp_eda_node *itr;
-       unsigned long flags;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(itr, &eda->cache, list_node) {
-               if (!memcmp(&itr->dev_addr, dev_addr, sizeof(itr->dev_addr))) {
-                       *eda_entry = *itr;
-                       result = 0;
-                       goto out_unlock;
-               }
-       }
-       /* Not found */
-out_unlock:
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-/*
- * Execute function for every element in the cache
- *
- * @function: function to execute on element of cache (must be atomic)
- * @priv:     private data of function
- * @returns:  result of first function that failed, or last function
- *            executed if no function failed.
- *
- * Stop executing when function returns error for any element in cache.
- *
- * IMPORTANT: We are using a spinlock here: the function executed on each
- * element has to be atomic.
- */
-int wlp_eda_for_each(struct wlp_eda *eda, wlp_eda_for_each_f function,
-                    void *priv)
-{
-       int result = 0;
-       struct wlp *wlp = container_of(eda, struct wlp, eda);
-       struct wlp_eda_node *entry;
-       unsigned long flags;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(entry, &eda->cache, list_node) {
-               result = (*function)(wlp, entry, priv);
-               if (result < 0)
-                       break;
-       }
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-/*
- * Execute function for single element in the cache (return dev addr)
- *
- * @virt_addr: index into EDA cache used to determine which element to
- *             execute the function on
- * @dev_addr: device address of element in cache will be returned using
- *            @dev_addr
- * @function: function to execute on element of cache (must be atomic)
- * @priv:     private data of function
- * @returns:  result of function
- *
- * IMPORTANT: We are using a spinlock here: the function executed on the
- * element has to be atomic.
- */
-int wlp_eda_for_virtual(struct wlp_eda *eda,
-                       const unsigned char virt_addr[ETH_ALEN],
-                       struct uwb_dev_addr *dev_addr,
-                       wlp_eda_for_each_f function,
-                       void *priv)
-{
-       int result = 0;
-       struct wlp *wlp = container_of(eda, struct wlp, eda);
-       struct wlp_eda_node *itr;
-       unsigned long flags;
-       int found = 0;
-
-       spin_lock_irqsave(&eda->lock, flags);
-       list_for_each_entry(itr, &eda->cache, list_node) {
-               if (!memcmp(itr->virt_addr, virt_addr,
-                          sizeof(itr->virt_addr))) {
-                       result = (*function)(wlp, itr, priv);
-                       *dev_addr = itr->dev_addr;
-                       found = 1;
-                       break;
-               }
-       }
-       if (!found)
-               result = -ENODEV;
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-
-static const char *__wlp_wss_connect_state[] = { "WLP_WSS_UNCONNECTED",
-                                         "WLP_WSS_CONNECTED",
-                                         "WLP_WSS_CONNECT_FAILED",
-};
-
-static const char *wlp_wss_connect_state_str(unsigned id)
-{
-       if (id >= ARRAY_SIZE(__wlp_wss_connect_state))
-               return "unknown WSS connection state";
-       return __wlp_wss_connect_state[id];
-}
-
-/*
- * View EDA cache from user space
- *
- * A debugging feature to give user visibility into the EDA cache. Also
- * used to display members of WSS to user (called from wlp_wss_members_show())
- */
-ssize_t wlp_eda_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-       struct wlp_eda_node *entry;
-       unsigned long flags;
-       struct wlp_eda *eda = &wlp->eda;
-       spin_lock_irqsave(&eda->lock, flags);
-       result = scnprintf(buf, PAGE_SIZE, "#eth_addr dev_addr wss_ptr "
-                          "tag state virt_addr\n");
-       list_for_each_entry(entry, &eda->cache, list_node) {
-               result += scnprintf(buf + result, PAGE_SIZE - result,
-                                   "%pM %02x:%02x %p 0x%02x %s %pM\n",
-                                   entry->eth_addr,
-                                   entry->dev_addr.data[1],
-                                   entry->dev_addr.data[0], entry->wss,
-                                   entry->tag,
-                                   wlp_wss_connect_state_str(entry->state),
-                                   entry->virt_addr);
-               if (result >= PAGE_SIZE)
-                       break;
-       }
-       spin_unlock_irqrestore(&eda->lock, flags);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_eda_show);
-
-/*
- * Add new EDA cache entry based on user input in sysfs
- *
- * Should only be used for debugging.
- *
- * The WSS is assumed to be the only WSS supported. This needs to be
- * redesigned when we support more than one WSS.
- */
-ssize_t wlp_eda_store(struct wlp *wlp, const char *buf, size_t size)
-{
-       ssize_t result;
-       struct wlp_eda *eda = &wlp->eda;
-       u8 eth_addr[6];
-       struct uwb_dev_addr dev_addr;
-       u8 tag;
-       unsigned state;
-
-       result = sscanf(buf, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx "
-                       "%02hhx:%02hhx %02hhx %u\n",
-                       &eth_addr[0], &eth_addr[1],
-                       &eth_addr[2], &eth_addr[3],
-                       &eth_addr[4], &eth_addr[5],
-                       &dev_addr.data[1], &dev_addr.data[0], &tag, &state);
-       switch (result) {
-       case 6: /* no dev addr specified -- remove entry NOT IMPLEMENTED */
-               /*result = wlp_eda_rm(eda, eth_addr, &dev_addr);*/
-               result = -ENOSYS;
-               break;
-       case 10:
-               state = state >= 1 ? 1 : 0;
-               result = wlp_eda_create_node(eda, eth_addr, &dev_addr);
-               if (result < 0 && result != -EEXIST)
-                       goto error;
-               /* Set virtual addr to be same as MAC */
-               result = wlp_eda_update_node(eda, &dev_addr, &wlp->wss,
-                                            eth_addr, tag, state);
-               if (result < 0)
-                       goto error;
-               break;
-       default: /* bad format */
-               result = -EINVAL;
-       }
-error:
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_eda_store);
diff --git a/drivers/uwb/wlp/messages.c b/drivers/uwb/wlp/messages.c
deleted file mode 100644 (file)
index 3a8e033..0000000
+++ /dev/null
@@ -1,1798 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- * Message construction and parsing
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- */
-
-#include <linux/wlp.h>
-#include <linux/slab.h>
-
-#include "wlp-internal.h"
-
-static
-const char *__wlp_assoc_frame[] = {
-       [WLP_ASSOC_D1] = "WLP_ASSOC_D1",
-       [WLP_ASSOC_D2] = "WLP_ASSOC_D2",
-       [WLP_ASSOC_M1] = "WLP_ASSOC_M1",
-       [WLP_ASSOC_M2] = "WLP_ASSOC_M2",
-       [WLP_ASSOC_M3] = "WLP_ASSOC_M3",
-       [WLP_ASSOC_M4] = "WLP_ASSOC_M4",
-       [WLP_ASSOC_M5] = "WLP_ASSOC_M5",
-       [WLP_ASSOC_M6] = "WLP_ASSOC_M6",
-       [WLP_ASSOC_M7] = "WLP_ASSOC_M7",
-       [WLP_ASSOC_M8] = "WLP_ASSOC_M8",
-       [WLP_ASSOC_F0] = "WLP_ASSOC_F0",
-       [WLP_ASSOC_E1] = "WLP_ASSOC_E1",
-       [WLP_ASSOC_E2] = "WLP_ASSOC_E2",
-       [WLP_ASSOC_C1] = "WLP_ASSOC_C1",
-       [WLP_ASSOC_C2] = "WLP_ASSOC_C2",
-       [WLP_ASSOC_C3] = "WLP_ASSOC_C3",
-       [WLP_ASSOC_C4] = "WLP_ASSOC_C4",
-};
-
-static const char *wlp_assoc_frame_str(unsigned id)
-{
-       if (id >= ARRAY_SIZE(__wlp_assoc_frame))
-               return "unknown association frame";
-       return __wlp_assoc_frame[id];
-}
-
-static const char *__wlp_assc_error[] = {
-       "none",
-       "Authenticator Failure",
-       "Rogue activity suspected",
-       "Device busy",
-       "Setup Locked",
-       "Registrar not ready",
-       "Invalid WSS selection",
-       "Message timeout",
-       "Enrollment session timeout",
-       "Device password invalid",
-       "Unsupported version",
-       "Internal error",
-       "Undefined error",
-       "Numeric comparison failure",
-       "Waiting for user input",
-};
-
-static const char *wlp_assc_error_str(unsigned id)
-{
-       if (id >= ARRAY_SIZE(__wlp_assc_error))
-               return "unknown WLP association error";
-       return __wlp_assc_error[id];
-}
-
-static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
-                                   size_t len)
-{
-       hdr->type = cpu_to_le16(type);
-       hdr->length = cpu_to_le16(len);
-}
-
-/*
- * Populate fields of a constant sized attribute
- *
- * @returns: total size of attribute including size of new value
- *
- * We have two instances of this function (wlp_pset and wlp_set): one takes
- * the value as a parameter, the other takes a pointer to the value as
- * parameter. They thus only differ in how the value is assigned to the
- * attribute.
- *
- * We use sizeof(*attr) - sizeof(struct wlp_attr_hdr) instead of
- * sizeof(type) to be able to use this same code for the structures that
- * contain 8bit enum values and be able to deal with pointer types.
- */
-#define wlp_set(type, type_code, name)                                 \
-static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
-{                                                                      \
-       wlp_set_attr_hdr(&attr->hdr, type_code,                         \
-                        sizeof(*attr) - sizeof(struct wlp_attr_hdr));  \
-       attr->name = value;                                             \
-       return sizeof(*attr);                                           \
-}
-
-#define wlp_pset(type, type_code, name)                                        \
-static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
-{                                                                      \
-       wlp_set_attr_hdr(&attr->hdr, type_code,                         \
-                        sizeof(*attr) - sizeof(struct wlp_attr_hdr));  \
-       attr->name = *value;                                            \
-       return sizeof(*attr);                                           \
-}
-
-/**
- * Populate fields of a variable attribute
- *
- * @returns: total size of attribute including size of new value
- *
- * Provided with a pointer to the memory area reserved for the
- * attribute structure, the field is populated with the value. The
- * reserved memory has to contain enough space for the value.
- */
-#define wlp_vset(type, type_code, name)                                        \
-static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \
-                               size_t len)                             \
-{                                                                      \
-       wlp_set_attr_hdr(&attr->hdr, type_code, len);                   \
-       memcpy(attr->name, value, len);                                 \
-       return sizeof(*attr) + len;                                     \
-}
-
-wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name)
-wlp_vset(char *, WLP_ATTR_MANUF, manufacturer)
-wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type)
-wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name)
-wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr)
-wlp_vset(char *, WLP_ATTR_SERIAL, serial)
-wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name)
-wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e)
-wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r)
-wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid)
-wlp_pset(struct wlp_dev_type *, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
-/*wlp_pset(struct wlp_dev_type *, WLP_ATTR_SEC_DEV_TYPE, sec_dev_type)*/
-wlp_set(u8, WLP_ATTR_WLP_VER, version)
-wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
-wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
-wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
-wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
-wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast)
-wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce)
-wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce)
-wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag)
-wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt)
-
-/**
- * Fill in the WSS information attributes
- *
- * We currently only support one WSS, and this is assumed in this function
- * that can populate only one WSS information attribute.
- */
-static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
-                              struct wlp_wss *wss)
-{
-       size_t datalen;
-       void *ptr = attr->wss_info;
-       size_t used = sizeof(*attr);
-
-       datalen = sizeof(struct wlp_wss_info) + strlen(wss->name);
-       wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen);
-       used = wlp_set_wssid(ptr, &wss->wssid);
-       used += wlp_set_wss_name(ptr + used, wss->name, strlen(wss->name));
-       used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll);
-       used += wlp_set_wss_sec_status(ptr + used, wss->secure_status);
-       used += wlp_set_wss_bcast(ptr + used, &wss->bcast);
-       return sizeof(*attr) + used;
-}
-
-/**
- * Verify attribute header
- *
- * @hdr:     Pointer to attribute header that will be verified.
- * @type:    Expected attribute type.
- * @len:     Expected length of attribute value (excluding header).
- *
- * Most attribute values have a known length even when they do have a
- * length field. This knowledge can be used via this function to verify
- * that the length field matches the expected value.
- */
-static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
-                      enum wlp_attr_type type, unsigned len)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-
-       if (le16_to_cpu(hdr->type) != type) {
-               dev_err(dev, "WLP: unexpected header type. Expected "
-                       "%u, got %u.\n", type, le16_to_cpu(hdr->type));
-               return -EINVAL;
-       }
-       if (le16_to_cpu(hdr->length) != len) {
-               dev_err(dev, "WLP: unexpected length in header. Expected "
-                       "%u, got %u.\n", len, le16_to_cpu(hdr->length));
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/**
- * Check if header of WSS information attribute valid
- *
- * @returns: length of WSS attributes (value of length attribute field) if
- *             valid WSS information attribute found
- *           -ENODATA if no WSS information attribute found
- *           -EIO other error occured
- *
- * The WSS information attribute is optional. The function will be provided
- * with a pointer to data that could _potentially_ be a WSS information
- * attribute. If a valid WSS information attribute is found it will return
- * 0, if no WSS information attribute is found it will return -ENODATA, and
- * another error will be returned if it is a WSS information attribute, but
- * some parsing failure occured.
- */
-static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
-                                      struct wlp_attr_hdr *hdr, size_t buflen)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       size_t len;
-       int result = 0;
-
-       if (buflen < sizeof(*hdr)) {
-               dev_err(dev, "WLP: Not enough space in buffer to parse"
-                       " WSS information attribute header.\n");
-               result = -EIO;
-               goto out;
-       }
-       if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
-               /* WSS information is optional */
-               result = -ENODATA;
-               goto out;
-       }
-       len = le16_to_cpu(hdr->length);
-       if (buflen < sizeof(*hdr) + len) {
-               dev_err(dev, "WLP: Not enough space in buffer to parse "
-                       "variable data. Got %d, expected %d.\n",
-                       (int)buflen, (int)(sizeof(*hdr) + len));
-               result = -EIO;
-               goto out;
-       }
-       result = len;
-out:
-       return result;
-}
-
-
-static ssize_t wlp_get_attribute(struct wlp *wlp, u16 type_code,
-       struct wlp_attr_hdr *attr_hdr, void *value, ssize_t value_len,
-       ssize_t buflen)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       ssize_t attr_len = sizeof(*attr_hdr) + value_len;
-       if (buflen < 0)
-               return -EINVAL;
-       if (buflen < attr_len) {
-               dev_err(dev, "WLP: Not enough space in buffer to parse"
-                       " attribute field. Need %d, received %zu\n",
-                       (int)attr_len, buflen);
-               return -EIO;
-       }
-       if (wlp_check_attr_hdr(wlp, attr_hdr, type_code, value_len) < 0) {
-               dev_err(dev, "WLP: Header verification failed. \n");
-               return -EINVAL;
-       }
-       memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len);
-       return attr_len;
-}
-
-static ssize_t wlp_vget_attribute(struct wlp *wlp, u16 type_code,
-       struct wlp_attr_hdr *attr_hdr, void *value, ssize_t max_value_len,
-       ssize_t buflen)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       size_t len;
-       if (buflen < 0)
-               return -EINVAL;
-       if (buflen < sizeof(*attr_hdr)) {
-               dev_err(dev, "WLP: Not enough space in buffer to parse"
-                       " header.\n");
-               return -EIO;
-       }
-       if (le16_to_cpu(attr_hdr->type) != type_code) {
-               dev_err(dev, "WLP: Unexpected attribute type. Got %u, "
-                       "expected %u.\n", le16_to_cpu(attr_hdr->type),
-                       type_code);
-               return -EINVAL;
-       }
-       len = le16_to_cpu(attr_hdr->length);
-       if (len > max_value_len) {
-               dev_err(dev, "WLP: Attribute larger than maximum "
-                       "allowed. Received %zu, max is %d.\n", len,
-                       (int)max_value_len);
-               return -EFBIG;
-       }
-       if (buflen < sizeof(*attr_hdr) + len) {
-               dev_err(dev, "WLP: Not enough space in buffer to parse "
-                       "variable data.\n");
-               return -EIO;
-       }
-       memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len);
-       return sizeof(*attr_hdr) + len;
-}
-
-/**
- * Get value of attribute from fixed size attribute field.
- *
- * @attr:    Pointer to attribute field.
- * @value:   Pointer to variable in which attribute value will be placed.
- * @buflen:  Size of buffer in which attribute field (including header)
- *           can be found.
- * @returns: Amount of given buffer consumed by parsing for this attribute.
- *
- * The size and type of the value is known by the type of the attribute.
- */
-#define wlp_get(type, type_code, name)                                 \
-ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr,  \
-                     type *value, ssize_t buflen)                      \
-{                                                                      \
-       return wlp_get_attribute(wlp, (type_code), &attr->hdr,          \
-                                value, sizeof(*value), buflen);        \
-}
-
-#define wlp_get_sparse(type, type_code, name) \
-       static wlp_get(type, type_code, name)
-
-/**
- * Get value of attribute from variable sized attribute field.
- *
- * @max:     The maximum size of this attribute. This value is dictated by
- *           the maximum value from the WLP specification.
- *
- * @attr:    Pointer to attribute field.
- * @value:   Pointer to variable that will contain the value. The memory
- *           must already have been allocated for this value.
- * @buflen:  Size of buffer in which attribute field (including header)
- *           can be found.
- * @returns: Amount of given bufferconsumed by parsing for this attribute.
- */
-#define wlp_vget(type_val, type_code, name, max)                       \
-static ssize_t wlp_get_##name(struct wlp *wlp,                         \
-                             struct wlp_attr_##name *attr,             \
-                             type_val *value, ssize_t buflen)          \
-{                                                                      \
-       return wlp_vget_attribute(wlp, (type_code), &attr->hdr,         \
-                             value, (max), buflen);                    \
-}
-
-wlp_get(u8, WLP_ATTR_WLP_VER, version)
-wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
-wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
-wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
-wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
-wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
-wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
-wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
-wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
-wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
-wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
-wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
-wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
-wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
-
-/* The buffers for the device info attributes can be found in the
- * wlp_device_info struct. These buffers contain one byte more than the
- * max allowed by the spec - this is done to be able to add the
- * terminating \0 for user display. This terminating byte is not required
- * in the actual attribute field (because it has a length field) so the
- * maximum allowed for this value is one less than its size in the
- * structure.
- */
-wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
-        FIELD_SIZEOF(struct wlp_wss, name) - 1)
-wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
-        FIELD_SIZEOF(struct wlp_device_info, name) - 1)
-wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
-        FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
-wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
-        FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
-wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
-        FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
-wlp_vget(char, WLP_ATTR_SERIAL, serial,
-        FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
-
-/**
- * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
- *
- * @attr: pointer to WSS name attribute in WSS information attribute field
- * @info: structure that will be populated with data from WSS information
- *        field (WSS name, Accept enroll, secure status, broadcast address)
- * @buflen: size of buffer
- *
- * Although the WSSID attribute forms part of the WSS info attribute it is
- * retrieved separately and stored in a different location.
- */
-static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp,
-                                     struct wlp_attr_hdr *attr,
-                                     struct wlp_wss_tmp_info *info,
-                                     ssize_t buflen)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       void *ptr = attr;
-       size_t used = 0;
-       ssize_t result = -EINVAL;
-
-       result = wlp_get_wss_name(wlp, ptr, info->name, buflen);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS name from "
-                       "WSS info in D2 message.\n");
-               goto error_parse;
-       }
-       used += result;
-
-       result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll,
-                                    buflen - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain accepting "
-                       "enrollment from WSS info in D2 message.\n");
-               goto error_parse;
-       }
-       if (info->accept_enroll != 0 && info->accept_enroll != 1) {
-               dev_err(dev, "WLP: invalid value for accepting "
-                       "enrollment in D2 message.\n");
-               result = -EINVAL;
-               goto error_parse;
-       }
-       used += result;
-
-       result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status,
-                                       buflen - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain secure "
-                       "status from WSS info in D2 message.\n");
-               goto error_parse;
-       }
-       if (info->sec_status != 0 && info->sec_status != 1) {
-               dev_err(dev, "WLP: invalid value for secure "
-                       "status in D2 message.\n");
-               result = -EINVAL;
-               goto error_parse;
-       }
-       used += result;
-
-       result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast,
-                                  buflen - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain broadcast "
-                       "address from WSS info in D2 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = used;
-error_parse:
-       return result;
-}
-
-/**
- * Create a new WSSID entry for the neighbor, allocate temporary storage
- *
- * Each neighbor can have many WSS active. We maintain a list of WSSIDs
- * advertised by neighbor. During discovery we also cache information about
- * these WSS in temporary storage.
- *
- * The temporary storage will be removed after it has been used (eg.
- * displayed to user), the wssid element will be removed from the list when
- * the neighbor is rediscovered or when it disappears.
- */
-static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
-                                             struct wlp_neighbor_e *neighbor)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_wssid_e *wssid_e;
-
-       wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL);
-       if (wssid_e == NULL) {
-               dev_err(dev, "WLP: unable to allocate memory "
-                       "for WSS information.\n");
-               goto error_alloc;
-       }
-       wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL);
-       if (wssid_e->info == NULL) {
-               dev_err(dev, "WLP: unable to allocate memory "
-                       "for temporary WSS information.\n");
-               kfree(wssid_e);
-               wssid_e = NULL;
-               goto error_alloc;
-       }
-       list_add(&wssid_e->node, &neighbor->wssid);
-error_alloc:
-       return wssid_e;
-}
-
-/**
- * Parse WSS information attribute
- *
- * @attr: pointer to WSS information attribute header
- * @buflen: size of buffer in which WSS information attribute appears
- * @wssid: will place wssid from WSS info attribute in this location
- * @wss_info: will place other information from WSS information attribute
- * in this location
- *
- * memory for @wssid and @wss_info must be allocated when calling this
- */
-static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr,
-                               size_t buflen, struct wlp_uuid *wssid,
-                               struct wlp_wss_tmp_info *wss_info)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       ssize_t result;
-       size_t len;
-       size_t used = 0;
-       void *ptr;
-
-       result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr,
-                                            buflen);
-       if (result < 0)
-               goto out;
-       len = result;
-       used = sizeof(*attr);
-       ptr = attr;
-
-       result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n");
-               goto out;
-       }
-       used += result;
-       result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info,
-                                       buflen - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS information "
-                       "from WSS information attributes. \n");
-               goto out;
-       }
-       used += result;
-       if (len + sizeof(*attr) != used) {
-               dev_err(dev, "WLP: Amount of data parsed does not "
-                       "match length field. Parsed %zu, length "
-                       "field %zu. \n", used, len);
-               result = -EINVAL;
-               goto out;
-       }
-       result = used;
-out:
-       return result;
-}
-
-/**
- * Retrieve WSS info from association frame
- *
- * @attr:     pointer to WSS information attribute
- * @neighbor: ptr to neighbor being discovered, NULL if enrollment in
- *            progress
- * @wss:      ptr to WSS being enrolled in, NULL if discovery in progress
- * @buflen:   size of buffer in which WSS information appears
- *
- * The WSS information attribute appears in the D2 association message.
- * This message is used in two ways: to discover all neighbors or to enroll
- * into a WSS activated by a neighbor. During discovery we only want to
- * store the WSS info in a cache, to be deleted right after it has been
- * used (eg. displayed to the user). During enrollment we store the WSS
- * information for the lifetime of enrollment.
- *
- * During discovery we are interested in all WSS information, during
- * enrollment we are only interested in the WSS being enrolled in. Even so,
- * when in enrollment we keep parsing the message after finding the WSS of
- * interest, this simplifies the calling routine in that it can be sure
- * that all WSS information attributes have been parsed out of the message.
- *
- * Association frame is process with nbmutex held. The list access is safe.
- */
-static ssize_t wlp_get_all_wss_info(struct wlp *wlp,
-                                   struct wlp_attr_wss_info *attr,
-                                   struct wlp_neighbor_e *neighbor,
-                                   struct wlp_wss *wss, ssize_t buflen)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       size_t used = 0;
-       ssize_t result = -EINVAL;
-       struct wlp_attr_wss_info *cur;
-       struct wlp_uuid wssid;
-       struct wlp_wss_tmp_info wss_info;
-       unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */
-       struct wlp_wssid_e *wssid_e;
-       char buf[WLP_WSS_UUID_STRSIZE];
-
-       if (buflen < 0)
-               goto out;
-
-       if (neighbor != NULL && wss == NULL)
-               enroll = 0; /* discovery */
-       else if (wss != NULL && neighbor == NULL)
-               enroll = 1; /* enrollment */
-       else
-               goto out;
-
-       cur = attr;
-       while (buflen - used > 0) {
-               memset(&wss_info, 0, sizeof(wss_info));
-               cur = (void *)cur + used;
-               result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid,
-                                         &wss_info);
-               if (result == -ENODATA) {
-                       result = used;
-                       goto out;
-               } else if (result < 0) {
-                       dev_err(dev, "WLP: Unable to parse WSS information "
-                               "from WSS information attribute. \n");
-                       result = -EINVAL;
-                       goto error_parse;
-               }
-               if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) {
-                       if (wss_info.accept_enroll != 1) {
-                               dev_err(dev, "WLP: Requested WSS does "
-                                       "not accept enrollment.\n");
-                               result = -EINVAL;
-                               goto out;
-                       }
-                       memcpy(wss->name, wss_info.name, sizeof(wss->name));
-                       wss->bcast = wss_info.bcast;
-                       wss->secure_status = wss_info.sec_status;
-                       wss->accept_enroll = wss_info.accept_enroll;
-                       wss->state = WLP_WSS_STATE_PART_ENROLLED;
-                       wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
-                       dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf);
-               } else {
-                       wssid_e = wlp_create_wssid_e(wlp, neighbor);
-                       if (wssid_e == NULL) {
-                               dev_err(dev, "WLP: Cannot create new WSSID "
-                                       "entry for neighbor %02x:%02x.\n",
-                                       neighbor->uwb_dev->dev_addr.data[1],
-                                       neighbor->uwb_dev->dev_addr.data[0]);
-                               result = -ENOMEM;
-                               goto out;
-                       }
-                       wssid_e->wssid = wssid;
-                       *wssid_e->info = wss_info;
-               }
-               used += result;
-       }
-       result = used;
-error_parse:
-       if (result < 0 && !enroll) /* this was a discovery */
-               wlp_remove_neighbor_tmp_info(neighbor);
-out:
-       return result;
-
-}
-
-/**
- * Parse WSS information attributes into cache for discovery
- *
- * @attr: the first WSS information attribute in message
- * @neighbor: the neighbor whose cache will be populated
- * @buflen: size of the input buffer
- */
-static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp,
-                                        struct wlp_attr_wss_info *attr,
-                                        struct wlp_neighbor_e *neighbor,
-                                        ssize_t buflen)
-{
-       return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
-}
-
-/**
- * Parse WSS information attributes into WSS struct for enrollment
- *
- * @attr: the first WSS information attribute in message
- * @wss: the WSS that will be enrolled
- * @buflen: size of the input buffer
- */
-static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp,
-                                         struct wlp_attr_wss_info *attr,
-                                         struct wlp_wss *wss, ssize_t buflen)
-{
-       return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
-}
-
-/**
- * Construct a D1 association frame
- *
- * We use the radio control functions to determine the values of the device
- * properties. These are of variable length and the total space needed is
- * tallied first before we start constructing the message. The radio
- * control functions return strings that are terminated with \0. This
- * character should not be included in the message (there is a length field
- * accompanying it in the attribute).
- */
-static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
-                             struct sk_buff **skb)
-{
-
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-       struct wlp_device_info *info;
-       size_t used = 0;
-       struct wlp_frame_assoc *_d1;
-       struct sk_buff *_skb;
-       void *d1_itr;
-
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to setup device "
-                               "information for D1 message.\n");
-                       goto error;
-               }
-       }
-       info = wlp->dev_info;
-       _skb = dev_alloc_skb(sizeof(*_d1)
-                     + sizeof(struct wlp_attr_uuid_e)
-                     + sizeof(struct wlp_attr_wss_sel_mthd)
-                     + sizeof(struct wlp_attr_dev_name)
-                     + strlen(info->name)
-                     + sizeof(struct wlp_attr_manufacturer)
-                     + strlen(info->manufacturer)
-                     + sizeof(struct wlp_attr_model_name)
-                     + strlen(info->model_name)
-                     + sizeof(struct wlp_attr_model_nr)
-                     + strlen(info->model_nr)
-                     + sizeof(struct wlp_attr_serial)
-                     + strlen(info->serial)
-                     + sizeof(struct wlp_attr_prim_dev_type)
-                     + sizeof(struct wlp_attr_wlp_assc_err));
-       if (_skb == NULL) {
-               dev_err(dev, "WLP: Cannot allocate memory for association "
-                       "message.\n");
-               result = -ENOMEM;
-               goto error;
-       }
-       _d1 = (void *) _skb->data;
-       _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-       _d1->hdr.type = WLP_FRAME_ASSOCIATION;
-       _d1->type = WLP_ASSOC_D1;
-
-       wlp_set_version(&_d1->version, WLP_VERSION);
-       wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1);
-       d1_itr = _d1->attr;
-       used = wlp_set_uuid_e(d1_itr, &wlp->uuid);
-       used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT);
-       used += wlp_set_dev_name(d1_itr + used, info->name,
-                                strlen(info->name));
-       used += wlp_set_manufacturer(d1_itr + used, info->manufacturer,
-                                    strlen(info->manufacturer));
-       used += wlp_set_model_name(d1_itr + used, info->model_name,
-                                  strlen(info->model_name));
-       used += wlp_set_model_nr(d1_itr + used, info->model_nr,
-                                strlen(info->model_nr));
-       used += wlp_set_serial(d1_itr + used, info->serial,
-                              strlen(info->serial));
-       used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type);
-       used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE);
-       skb_put(_skb, sizeof(*_d1) + used);
-       *skb = _skb;
-error:
-       return result;
-}
-
-/**
- * Construct a D2 association frame
- *
- * We use the radio control functions to determine the values of the device
- * properties. These are of variable length and the total space needed is
- * tallied first before we start constructing the message. The radio
- * control functions return strings that are terminated with \0. This
- * character should not be included in the message (there is a length field
- * accompanying it in the attribute).
- */
-static
-int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
-                      struct sk_buff **skb, struct wlp_uuid *uuid_e)
-{
-
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-       struct wlp_device_info *info;
-       size_t used = 0;
-       struct wlp_frame_assoc *_d2;
-       struct sk_buff *_skb;
-       void *d2_itr;
-       size_t mem_needed;
-
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to setup device "
-                               "information for D2 message.\n");
-                       goto error;
-               }
-       }
-       info = wlp->dev_info;
-       mem_needed = sizeof(*_d2)
-                     + sizeof(struct wlp_attr_uuid_e)
-                     + sizeof(struct wlp_attr_uuid_r)
-                     + sizeof(struct wlp_attr_dev_name)
-                     + strlen(info->name)
-                     + sizeof(struct wlp_attr_manufacturer)
-                     + strlen(info->manufacturer)
-                     + sizeof(struct wlp_attr_model_name)
-                     + strlen(info->model_name)
-                     + sizeof(struct wlp_attr_model_nr)
-                     + strlen(info->model_nr)
-                     + sizeof(struct wlp_attr_serial)
-                     + strlen(info->serial)
-                     + sizeof(struct wlp_attr_prim_dev_type)
-                     + sizeof(struct wlp_attr_wlp_assc_err);
-       if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
-               mem_needed += sizeof(struct wlp_attr_wss_info)
-                             + sizeof(struct wlp_wss_info)
-                             + strlen(wlp->wss.name);
-       _skb = dev_alloc_skb(mem_needed);
-       if (_skb == NULL) {
-               dev_err(dev, "WLP: Cannot allocate memory for association "
-                       "message.\n");
-               result = -ENOMEM;
-               goto error;
-       }
-       _d2 = (void *) _skb->data;
-       _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-       _d2->hdr.type = WLP_FRAME_ASSOCIATION;
-       _d2->type = WLP_ASSOC_D2;
-
-       wlp_set_version(&_d2->version, WLP_VERSION);
-       wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2);
-       d2_itr = _d2->attr;
-       used = wlp_set_uuid_e(d2_itr, uuid_e);
-       used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid);
-       if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
-               used += wlp_set_wss_info(d2_itr + used, &wlp->wss);
-       used += wlp_set_dev_name(d2_itr + used, info->name,
-                                strlen(info->name));
-       used += wlp_set_manufacturer(d2_itr + used, info->manufacturer,
-                                    strlen(info->manufacturer));
-       used += wlp_set_model_name(d2_itr + used, info->model_name,
-                                  strlen(info->model_name));
-       used += wlp_set_model_nr(d2_itr + used, info->model_nr,
-                                strlen(info->model_nr));
-       used += wlp_set_serial(d2_itr + used, info->serial,
-                              strlen(info->serial));
-       used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type);
-       used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE);
-       skb_put(_skb, sizeof(*_d2) + used);
-       *skb = _skb;
-error:
-       return result;
-}
-
-/**
- * Allocate memory for and populate fields of F0 association frame
- *
- * Currently (while focusing on unsecure enrollment) we ignore the
- * nonce's that could be placed in the message. Only the error field is
- * populated by the value provided by the caller.
- */
-static
-int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
-                      enum wlp_assc_error error)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = -ENOMEM;
-       struct {
-               struct wlp_frame_assoc f0_hdr;
-               struct wlp_attr_enonce enonce;
-               struct wlp_attr_rnonce rnonce;
-               struct wlp_attr_wlp_assc_err assc_err;
-       } *f0;
-       struct sk_buff *_skb;
-       struct wlp_nonce tmp;
-
-       _skb = dev_alloc_skb(sizeof(*f0));
-       if (_skb == NULL) {
-               dev_err(dev, "WLP: Unable to allocate memory for F0 "
-                       "association frame. \n");
-               goto error_alloc;
-       }
-       f0 = (void *) _skb->data;
-       f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-       f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
-       f0->f0_hdr.type = WLP_ASSOC_F0;
-       wlp_set_version(&f0->f0_hdr.version, WLP_VERSION);
-       wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0);
-       memset(&tmp, 0, sizeof(tmp));
-       wlp_set_enonce(&f0->enonce, &tmp);
-       wlp_set_rnonce(&f0->rnonce, &tmp);
-       wlp_set_wlp_assc_err(&f0->assc_err, error);
-       skb_put(_skb, sizeof(*f0));
-       *skb = _skb;
-       result = 0;
-error_alloc:
-       return result;
-}
-
-/**
- * Parse F0 frame
- *
- * We just retrieve the values and print it as an error to the user.
- * Calling function already knows an error occured (F0 indicates error), so
- * we just parse the content as debug for higher layers.
- */
-int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *f0 = (void *) skb->data;
-       void *ptr = skb->data;
-       size_t len = skb->len;
-       size_t used;
-       ssize_t result;
-       struct wlp_nonce enonce, rnonce;
-       enum wlp_assc_error assc_err;
-       char enonce_buf[WLP_WSS_NONCE_STRSIZE];
-       char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
-
-       used = sizeof(*f0);
-       result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Enrollee nonce "
-                       "attribute from F0 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Registrar nonce "
-                       "attribute from F0 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WLP Association error "
-                       "attribute from F0 message.\n");
-               goto error_parse;
-       }
-       wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce);
-       wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce);
-       dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee "
-               "nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n",
-               enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err));
-       result = 0;
-error_parse:
-       return result;
-}
-
-/**
- * Retrieve variable device information from association message
- *
- * The device information parsed is not required in any message. This
- * routine will thus not fail if an attribute is not present.
- * The attributes are expected in a certain order, even if all are not
- * present. The "attribute type" value is used to ensure the attributes
- * are parsed in the correct order.
- *
- * If an error is encountered during parsing the function will return an
- * error code, when this happens the given device_info structure may be
- * partially filled.
- */
-static
-int wlp_get_variable_info(struct wlp *wlp, void *data,
-                         struct wlp_device_info *dev_info, ssize_t len)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       size_t used = 0;
-       struct wlp_attr_hdr *hdr;
-       ssize_t result = 0;
-       unsigned last = 0;
-
-       while (len - used > 0) {
-               if (len - used < sizeof(*hdr)) {
-                       dev_err(dev, "WLP: Partial data in frame, cannot "
-                               "parse. \n");
-                       goto error_parse;
-               }
-               hdr = data + used;
-               switch (le16_to_cpu(hdr->type)) {
-               case WLP_ATTR_MANUF:
-                       if (last >= WLP_ATTR_MANUF) {
-                               dev_err(dev, "WLP: Incorrect order of "
-                                       "attribute values in D1 msg.\n");
-                               goto error_parse;
-                       }
-                       result = wlp_get_manufacturer(wlp, data + used,
-                                                     dev_info->manufacturer,
-                                                     len - used);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to obtain "
-                                       "Manufacturer attribute from D1 "
-                                       "message.\n");
-                               goto error_parse;
-                       }
-                       last = WLP_ATTR_MANUF;
-                       used += result;
-                       break;
-               case WLP_ATTR_MODEL_NAME:
-                       if (last >= WLP_ATTR_MODEL_NAME) {
-                               dev_err(dev, "WLP: Incorrect order of "
-                                       "attribute values in D1 msg.\n");
-                               goto error_parse;
-                       }
-                       result = wlp_get_model_name(wlp, data + used,
-                                                   dev_info->model_name,
-                                                   len - used);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to obtain Model "
-                                       "name attribute from D1 message.\n");
-                               goto error_parse;
-                       }
-                       last = WLP_ATTR_MODEL_NAME;
-                       used += result;
-                       break;
-               case WLP_ATTR_MODEL_NR:
-                       if (last >= WLP_ATTR_MODEL_NR) {
-                               dev_err(dev, "WLP: Incorrect order of "
-                                       "attribute values in D1 msg.\n");
-                               goto error_parse;
-                       }
-                       result = wlp_get_model_nr(wlp, data + used,
-                                                 dev_info->model_nr,
-                                                 len - used);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to obtain Model "
-                                       "number attribute from D1 message.\n");
-                               goto error_parse;
-                       }
-                       last = WLP_ATTR_MODEL_NR;
-                       used += result;
-                       break;
-               case WLP_ATTR_SERIAL:
-                       if (last >= WLP_ATTR_SERIAL) {
-                               dev_err(dev, "WLP: Incorrect order of "
-                                       "attribute values in D1 msg.\n");
-                               goto error_parse;
-                       }
-                       result = wlp_get_serial(wlp, data + used,
-                                               dev_info->serial, len - used);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to obtain Serial "
-                                       "number attribute from D1 message.\n");
-                               goto error_parse;
-                       }
-                       last = WLP_ATTR_SERIAL;
-                       used += result;
-                       break;
-               case WLP_ATTR_PRI_DEV_TYPE:
-                       if (last >= WLP_ATTR_PRI_DEV_TYPE) {
-                               dev_err(dev, "WLP: Incorrect order of "
-                                       "attribute values in D1 msg.\n");
-                               goto error_parse;
-                       }
-                       result = wlp_get_prim_dev_type(wlp, data + used,
-                                                      &dev_info->prim_dev_type,
-                                                      len - used);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to obtain Primary "
-                                       "device type attribute from D1 "
-                                       "message.\n");
-                               goto error_parse;
-                       }
-                       dev_info->prim_dev_type.category =
-                               le16_to_cpu(dev_info->prim_dev_type.category);
-                       dev_info->prim_dev_type.subID =
-                               le16_to_cpu(dev_info->prim_dev_type.subID);
-                       last = WLP_ATTR_PRI_DEV_TYPE;
-                       used += result;
-                       break;
-               default:
-                       /* This is not variable device information. */
-                       goto out;
-                       break;
-               }
-       }
-out:
-       return used;
-error_parse:
-       return -EINVAL;
-}
-
-/**
- * Parse incoming D1 frame, populate attribute values
- *
- * Caller provides pointers to memory already allocated for attributes
- * expected in the D1 frame. These variables will be populated.
- */
-static
-int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
-                      struct wlp_uuid *uuid_e,
-                      enum wlp_wss_sel_mthd *sel_mthd,
-                      struct wlp_device_info *dev_info,
-                      enum wlp_assc_error *assc_err)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *d1 = (void *) skb->data;
-       void *ptr = skb->data;
-       size_t len = skb->len;
-       size_t used;
-       ssize_t result;
-
-       used = sizeof(*d1);
-       result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 "
-                       "message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS selection method "
-                       "from D1 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
-                                    len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Name from D1 "
-                       "message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Information from "
-                       "D1 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WLP Association Error "
-                       "Information from D1 message.\n");
-               goto error_parse;
-       }
-       result = 0;
-error_parse:
-       return result;
-}
-/**
- * Handle incoming D1 frame
- *
- * The frame has already been verified to contain an Association header with
- * the correct version number. Parse the incoming frame, construct and send
- * a D2 frame in response.
- *
- * It is not clear what to do with most fields in the incoming D1 frame. We
- * retrieve and discard the information here for now.
- */
-void wlp_handle_d1_frame(struct work_struct *ws)
-{
-       struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
-                                                 struct wlp_assoc_frame_ctx,
-                                                 ws);
-       struct wlp *wlp = frame_ctx->wlp;
-       struct wlp_wss *wss = &wlp->wss;
-       struct sk_buff *skb = frame_ctx->skb;
-       struct uwb_dev_addr *src = &frame_ctx->src;
-       int result;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_uuid uuid_e;
-       enum wlp_wss_sel_mthd sel_mthd = 0;
-       struct wlp_device_info dev_info;
-       enum wlp_assc_error assc_err;
-       struct sk_buff *resp = NULL;
-
-       /* Parse D1 frame */
-       mutex_lock(&wss->mutex);
-       mutex_lock(&wlp->mutex); /* to access wlp->uuid */
-       memset(&dev_info, 0, sizeof(dev_info));
-       result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
-                                   &assc_err);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
-               kfree_skb(skb);
-               goto out;
-       }
-
-       kfree_skb(skb);
-       if (!wlp_uuid_is_set(&wlp->uuid)) {
-               dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
-                       "proceed. Respong to D1 message with error F0.\n");
-               result = wlp_build_assoc_f0(wlp, &resp,
-                                           WLP_ASSOC_ERROR_NOT_READY);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to construct F0 message.\n");
-                       goto out;
-               }
-       } else {
-               /* Construct D2 frame */
-               result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to construct D2 message.\n");
-                       goto out;
-               }
-       }
-       /* Send D2 frame */
-       BUG_ON(wlp->xmit_frame == NULL);
-       result = wlp->xmit_frame(wlp, resp, src);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to transmit D2 association "
-                       "message: %d\n", result);
-               if (result == -ENXIO)
-                       dev_err(dev, "WLP: Is network interface up? \n");
-               /* We could try again ... */
-               dev_kfree_skb_any(resp); /* we need to free if tx fails */
-       }
-out:
-       kfree(frame_ctx);
-       mutex_unlock(&wlp->mutex);
-       mutex_unlock(&wss->mutex);
-}
-
-/**
- * Parse incoming D2 frame, create and populate temporary cache
- *
- * @skb: socket buffer in which D2 frame can be found
- * @neighbor: the neighbor that sent the D2 frame
- *
- * Will allocate memory for temporary storage of information learned during
- * discovery.
- */
-int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
-                               struct wlp_neighbor_e *neighbor)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *d2 = (void *) skb->data;
-       void *ptr = skb->data;
-       size_t len = skb->len;
-       size_t used;
-       ssize_t result;
-       struct wlp_uuid uuid_e;
-       struct wlp_device_info *nb_info;
-       enum wlp_assc_error assc_err;
-
-       used = sizeof(*d2);
-       result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
-               dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
-                       "local UUID sent in D1. \n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor,
-                                          len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS information "
-                       "from D2 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
-       if (neighbor->info == NULL) {
-               dev_err(dev, "WLP: cannot allocate memory to store device "
-                       "info.\n");
-               result = -ENOMEM;
-               goto error_parse;
-       }
-       nb_info = neighbor->info;
-       result = wlp_get_dev_name(wlp, ptr + used, nb_info->name,
-                                 len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Name from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Information from "
-                       "D2 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WLP Association Error "
-                       "Information from D2 message.\n");
-               goto error_parse;
-       }
-       if (assc_err != WLP_ASSOC_ERROR_NONE) {
-               dev_err(dev, "WLP: neighbor device returned association "
-                       "error %d\n", assc_err);
-               result = -EINVAL;
-               goto error_parse;
-       }
-       result = 0;
-error_parse:
-       if (result < 0)
-               wlp_remove_neighbor_tmp_info(neighbor);
-       return result;
-}
-
-/**
- * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
- *
- * @wss: our WSS that will be enrolled
- * @skb: socket buffer in which D2 frame can be found
- * @neighbor: the neighbor that sent the D2 frame
- * @wssid: the wssid of the WSS in which we want to enroll
- *
- * Forms part of enrollment sequence. We are trying to enroll in WSS with
- * @wssid by using @neighbor as registrar. A D1 message was sent to
- * @neighbor and now we need to parse the D2 response. The neighbor's
- * response is searched for the requested WSS and if found (and it accepts
- * enrollment), we store the information.
- */
-int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb,
-                                struct wlp_neighbor_e *neighbor,
-                                struct wlp_uuid *wssid)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       void *ptr = skb->data;
-       size_t len = skb->len;
-       size_t used;
-       ssize_t result;
-       struct wlp_uuid uuid_e;
-       struct wlp_uuid uuid_r;
-       struct wlp_device_info nb_info;
-       enum wlp_assc_error assc_err;
-       char uuid_bufA[WLP_WSS_UUID_STRSIZE];
-       char uuid_bufB[WLP_WSS_UUID_STRSIZE];
-
-       used = sizeof(struct wlp_frame_assoc);
-       result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
-               dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
-                       "local UUID sent in D1. \n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) {
-               wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA),
-                                  &neighbor->uuid);
-               wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r);
-               dev_err(dev, "WLP: UUID of neighbor does not match UUID "
-                       "learned during discovery. Originally discovered: %s, "
-                       "now from D2 message: %s\n", uuid_bufA, uuid_bufB);
-               result = -EINVAL;
-               goto error_parse;
-       }
-       used += result;
-       wss->wssid = *wssid;
-       result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS information "
-                       "from D2 message.\n");
-               goto error_parse;
-       }
-       if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
-               dev_err(dev, "WLP: D2 message did not contain information "
-                       "for successful enrollment. \n");
-               result = -EINVAL;
-               goto error_parse;
-       }
-       used += result;
-       /* Place device information on stack to continue parsing of message */
-       result = wlp_get_dev_name(wlp, ptr + used, nb_info.name,
-                                 len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Name from D2 "
-                       "message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain Device Information from "
-                       "D2 message.\n");
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WLP Association Error "
-                       "Information from D2 message.\n");
-               goto error_parse;
-       }
-       if (assc_err != WLP_ASSOC_ERROR_NONE) {
-               dev_err(dev, "WLP: neighbor device returned association "
-                       "error %d\n", assc_err);
-               if (wss->state == WLP_WSS_STATE_PART_ENROLLED) {
-                       dev_err(dev, "WLP: Enrolled in WSS (should not "
-                               "happen according to spec). Undoing. \n");
-                       wlp_wss_reset(wss);
-               }
-               result = -EINVAL;
-               goto error_parse;
-       }
-       result = 0;
-error_parse:
-       return result;
-}
-
-/**
- * Parse C3/C4 frame into provided variables
- *
- * @wssid: will point to copy of wssid retrieved from C3/C4 frame
- * @tag:   will point to copy of tag retrieved from C3/C4 frame
- * @virt_addr: will point to copy of virtual address retrieved from C3/C4
- * frame.
- *
- * Calling function has to allocate memory for these values.
- *
- * skb contains a valid C3/C4 frame, return the individual fields of this
- * frame in the provided variables.
- */
-int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb,
-                      struct wlp_uuid *wssid, u8 *tag,
-                      struct uwb_mac_addr *virt_addr)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result;
-       void *ptr = skb->data;
-       size_t len = skb->len;
-       size_t used;
-       struct wlp_frame_assoc *assoc = ptr;
-
-       used = sizeof(*assoc);
-       result = wlp_get_wssid(wlp, ptr + used, wssid, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSSID attribute from "
-                       "%s message.\n", wlp_assoc_frame_str(assoc->type));
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS tag attribute from "
-                       "%s message.\n", wlp_assoc_frame_str(assoc->type));
-               goto error_parse;
-       }
-       used += result;
-       result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSS virtual address "
-                       "attribute from %s message.\n",
-                       wlp_assoc_frame_str(assoc->type));
-               goto error_parse;
-       }
-error_parse:
-       return result;
-}
-
-/**
- * Allocate memory for and populate fields of C1 or C2 association frame
- *
- * The C1 and C2 association frames appear identical - except for the type.
- */
-static
-int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
-                        struct sk_buff **skb, enum wlp_assoc_type type)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result  = -ENOMEM;
-       struct {
-               struct wlp_frame_assoc c_hdr;
-               struct wlp_attr_wssid wssid;
-       } *c;
-       struct sk_buff *_skb;
-
-       _skb = dev_alloc_skb(sizeof(*c));
-       if (_skb == NULL) {
-               dev_err(dev, "WLP: Unable to allocate memory for C1/C2 "
-                       "association frame. \n");
-               goto error_alloc;
-       }
-       c = (void *) _skb->data;
-       c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-       c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
-       c->c_hdr.type = type;
-       wlp_set_version(&c->c_hdr.version, WLP_VERSION);
-       wlp_set_msg_type(&c->c_hdr.msg_type, type);
-       wlp_set_wssid(&c->wssid, &wss->wssid);
-       skb_put(_skb, sizeof(*c));
-       *skb = _skb;
-       result = 0;
-error_alloc:
-       return result;
-}
-
-
-static
-int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
-                      struct sk_buff **skb)
-{
-       return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
-}
-
-static
-int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
-                      struct sk_buff **skb)
-{
-       return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
-}
-
-
-/**
- * Allocate memory for and populate fields of C3 or C4 association frame
- *
- * The C3 and C4 association frames appear identical - except for the type.
- */
-static
-int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
-                        struct sk_buff **skb, enum wlp_assoc_type type)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result  = -ENOMEM;
-       struct {
-               struct wlp_frame_assoc c_hdr;
-               struct wlp_attr_wssid wssid;
-               struct wlp_attr_wss_tag wss_tag;
-               struct wlp_attr_wss_virt wss_virt;
-       } *c;
-       struct sk_buff *_skb;
-
-       _skb = dev_alloc_skb(sizeof(*c));
-       if (_skb == NULL) {
-               dev_err(dev, "WLP: Unable to allocate memory for C3/C4 "
-                       "association frame. \n");
-               goto error_alloc;
-       }
-       c = (void *) _skb->data;
-       c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-       c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
-       c->c_hdr.type = type;
-       wlp_set_version(&c->c_hdr.version, WLP_VERSION);
-       wlp_set_msg_type(&c->c_hdr.msg_type, type);
-       wlp_set_wssid(&c->wssid, &wss->wssid);
-       wlp_set_wss_tag(&c->wss_tag, wss->tag);
-       wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr);
-       skb_put(_skb, sizeof(*c));
-       *skb = _skb;
-       result = 0;
-error_alloc:
-       return result;
-}
-
-static
-int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
-                      struct sk_buff **skb)
-{
-       return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
-}
-
-static
-int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
-                      struct sk_buff **skb)
-{
-       return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
-}
-
-
-#define wlp_send_assoc(type, id)                                       \
-static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \
-                                struct uwb_dev_addr *dev_addr)         \
-{                                                                      \
-       struct device *dev = &wlp->rc->uwb_dev.dev;                     \
-       int result;                                                     \
-       struct sk_buff *skb = NULL;                                     \
-                                                                       \
-       /* Build the frame */                                           \
-       result = wlp_build_assoc_##type(wlp, wss, &skb);                \
-       if (result < 0) {                                               \
-               dev_err(dev, "WLP: Unable to construct %s association " \
-                       "frame: %d\n", wlp_assoc_frame_str(id), result);\
-               goto error_build_assoc;                                 \
-       }                                                               \
-       /* Send the frame */                                            \
-       BUG_ON(wlp->xmit_frame == NULL);                                \
-       result = wlp->xmit_frame(wlp, skb, dev_addr);                   \
-       if (result < 0) {                                               \
-               dev_err(dev, "WLP: Unable to transmit %s association "  \
-                       "message: %d\n", wlp_assoc_frame_str(id),       \
-                       result);                                        \
-               if (result == -ENXIO)                                   \
-                       dev_err(dev, "WLP: Is network interface "       \
-                               "up? \n");                              \
-               goto error_xmit;                                        \
-       }                                                               \
-       return 0;                                                       \
-error_xmit:                                                            \
-       /* We could try again ... */                                    \
-       dev_kfree_skb_any(skb);/*we need to free if tx fails*/          \
-error_build_assoc:                                                     \
-       return result;                                                  \
-}
-
-wlp_send_assoc(d1, WLP_ASSOC_D1)
-wlp_send_assoc(c1, WLP_ASSOC_C1)
-wlp_send_assoc(c3, WLP_ASSOC_C3)
-
-int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
-                        struct uwb_dev_addr *dev_addr,
-                        enum wlp_assoc_type type)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       switch (type) {
-       case WLP_ASSOC_D1:
-               result = wlp_send_assoc_d1(wlp, wss, dev_addr);
-               break;
-       case WLP_ASSOC_C1:
-               result = wlp_send_assoc_c1(wlp, wss, dev_addr);
-               break;
-       case WLP_ASSOC_C3:
-               result = wlp_send_assoc_c3(wlp, wss, dev_addr);
-               break;
-       default:
-               dev_err(dev, "WLP: Received request to send unknown "
-                       "association message.\n");
-               result = -EINVAL;
-               break;
-       }
-       return result;
-}
-
-/**
- * Handle incoming C1 frame
- *
- * The frame has already been verified to contain an Association header with
- * the correct version number. Parse the incoming frame, construct and send
- * a C2 frame in response.
- */
-void wlp_handle_c1_frame(struct work_struct *ws)
-{
-       struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
-                                                 struct wlp_assoc_frame_ctx,
-                                                 ws);
-       struct wlp *wlp = frame_ctx->wlp;
-       struct wlp_wss *wss = &wlp->wss;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data;
-       unsigned int len = frame_ctx->skb->len;
-       struct uwb_dev_addr *src = &frame_ctx->src;
-       int result;
-       struct wlp_uuid wssid;
-       struct sk_buff *resp = NULL;
-
-       /* Parse C1 frame */
-       mutex_lock(&wss->mutex);
-       result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid,
-                              len - sizeof(*c1));
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n");
-               goto out;
-       }
-       if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
-           && wss->state == WLP_WSS_STATE_ACTIVE) {
-               /* Construct C2 frame */
-               result = wlp_build_assoc_c2(wlp, wss, &resp);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to construct C2 message.\n");
-                       goto out;
-               }
-       } else {
-               /* Construct F0 frame */
-               result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to construct F0 message.\n");
-                       goto out;
-               }
-       }
-       /* Send C2 frame */
-       BUG_ON(wlp->xmit_frame == NULL);
-       result = wlp->xmit_frame(wlp, resp, src);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to transmit response association "
-                       "message: %d\n", result);
-               if (result == -ENXIO)
-                       dev_err(dev, "WLP: Is network interface up? \n");
-               /* We could try again ... */
-               dev_kfree_skb_any(resp); /* we need to free if tx fails */
-       }
-out:
-       kfree_skb(frame_ctx->skb);
-       kfree(frame_ctx);
-       mutex_unlock(&wss->mutex);
-}
-
-/**
- * Handle incoming C3 frame
- *
- * The frame has already been verified to contain an Association header with
- * the correct version number. Parse the incoming frame, construct and send
- * a C4 frame in response. If the C3 frame identifies a WSS that is locally
- * active then we connect to this neighbor (add it to our EDA cache).
- */
-void wlp_handle_c3_frame(struct work_struct *ws)
-{
-       struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
-                                                 struct wlp_assoc_frame_ctx,
-                                                 ws);
-       struct wlp *wlp = frame_ctx->wlp;
-       struct wlp_wss *wss = &wlp->wss;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct sk_buff *skb = frame_ctx->skb;
-       struct uwb_dev_addr *src = &frame_ctx->src;
-       int result;
-       struct sk_buff *resp = NULL;
-       struct wlp_uuid wssid;
-       u8 tag;
-       struct uwb_mac_addr virt_addr;
-
-       /* Parse C3 frame */
-       mutex_lock(&wss->mutex);
-       result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain values from C3 frame.\n");
-               goto out;
-       }
-       if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
-           && wss->state >= WLP_WSS_STATE_ACTIVE) {
-               result = wlp_eda_update_node(&wlp->eda, src, wss,
-                                            (void *) virt_addr.data, tag,
-                                            WLP_WSS_CONNECTED);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to update EDA cache "
-                               "with new connected neighbor information.\n");
-                       result = wlp_build_assoc_f0(wlp, &resp,
-                                                   WLP_ASSOC_ERROR_INT);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to construct F0 "
-                                       "message.\n");
-                               goto out;
-                       }
-               } else {
-                       wss->state = WLP_WSS_STATE_CONNECTED;
-                       /* Construct C4 frame */
-                       result = wlp_build_assoc_c4(wlp, wss, &resp);
-                       if (result < 0) {
-                               dev_err(dev, "WLP: Unable to construct C4 "
-                                       "message.\n");
-                               goto out;
-                       }
-               }
-       } else {
-               /* Construct F0 frame */
-               result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to construct F0 message.\n");
-                       goto out;
-               }
-       }
-       /* Send C4 frame */
-       BUG_ON(wlp->xmit_frame == NULL);
-       result = wlp->xmit_frame(wlp, resp, src);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to transmit response association "
-                       "message: %d\n", result);
-               if (result == -ENXIO)
-                       dev_err(dev, "WLP: Is network interface up? \n");
-               /* We could try again ... */
-               dev_kfree_skb_any(resp); /* we need to free if tx fails */
-       }
-out:
-       kfree_skb(frame_ctx->skb);
-       kfree(frame_ctx);
-       mutex_unlock(&wss->mutex);
-}
-
-
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c
deleted file mode 100644 (file)
index 6627c94..0000000
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- * sysfs functions
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: Docs
- *
- */
-#include <linux/wlp.h>
-
-#include "wlp-internal.h"
-
-static
-size_t wlp_wss_wssid_e_print(char *buf, size_t bufsize,
-                            struct wlp_wssid_e *wssid_e)
-{
-       size_t used = 0;
-       used += scnprintf(buf, bufsize, " WSS: ");
-       used += wlp_wss_uuid_print(buf + used, bufsize - used,
-                                  &wssid_e->wssid);
-
-       if (wssid_e->info != NULL) {
-               used += scnprintf(buf + used, bufsize - used, " ");
-               used += uwb_mac_addr_print(buf + used, bufsize - used,
-                                          &wssid_e->info->bcast);
-               used += scnprintf(buf + used, bufsize - used, " %u %u %s\n",
-                                 wssid_e->info->accept_enroll,
-                                 wssid_e->info->sec_status,
-                                 wssid_e->info->name);
-       }
-       return used;
-}
-
-/**
- * Print out information learned from neighbor discovery
- *
- * Some fields being printed may not be included in the device discovery
- * information (it is not mandatory). We are thus careful how the
- * information is printed to ensure it is clear to the user what field is
- * being referenced.
- * The information being printed is for one time use - temporary storage is
- * cleaned after it is printed.
- *
- * Ideally sysfs output should be on one line. The information printed here
- * contain a few strings so it will be hard to parse if they are all
- * printed on the same line - without agreeing on a standard field
- * separator.
- */
-static
-ssize_t wlp_wss_neighborhood_print_remove(struct wlp *wlp, char *buf,
-                                  size_t bufsize)
-{
-       size_t used = 0;
-       struct wlp_neighbor_e *neighb;
-       struct wlp_wssid_e *wssid_e;
-
-       mutex_lock(&wlp->nbmutex);
-       used = scnprintf(buf, bufsize, "#Neighbor information\n"
-                        "#uuid dev_addr\n"
-                        "# Device Name:\n# Model Name:\n# Manufacturer:\n"
-                        "# Model Nr:\n# Serial:\n"
-                        "# Pri Dev type: CategoryID OUI OUISubdiv "
-                        "SubcategoryID\n"
-                        "# WSS: WSSID WSS_name accept_enroll sec_status "
-                        "bcast\n"
-                        "# WSS: WSSID WSS_name accept_enroll sec_status "
-                        "bcast\n\n");
-       list_for_each_entry(neighb, &wlp->neighbors, node) {
-               if (bufsize - used <= 0)
-                       goto out;
-               used += wlp_wss_uuid_print(buf + used, bufsize - used,
-                                          &neighb->uuid);
-               buf[used++] = ' ';
-               used += uwb_dev_addr_print(buf + used, bufsize - used,
-                                          &neighb->uwb_dev->dev_addr);
-               if (neighb->info != NULL)
-                       used += scnprintf(buf + used, bufsize - used,
-                                         "\n Device Name: %s\n"
-                                         " Model Name: %s\n"
-                                         " Manufacturer:%s \n"
-                                         " Model Nr: %s\n"
-                                         " Serial: %s\n"
-                                         " Pri Dev type: "
-                                         "%u %02x:%02x:%02x %u %u\n",
-                                         neighb->info->name,
-                                         neighb->info->model_name,
-                                         neighb->info->manufacturer,
-                                         neighb->info->model_nr,
-                                         neighb->info->serial,
-                                         neighb->info->prim_dev_type.category,
-                                         neighb->info->prim_dev_type.OUI[0],
-                                         neighb->info->prim_dev_type.OUI[1],
-                                         neighb->info->prim_dev_type.OUI[2],
-                                         neighb->info->prim_dev_type.OUIsubdiv,
-                                         neighb->info->prim_dev_type.subID);
-               list_for_each_entry(wssid_e, &neighb->wssid, node) {
-                       used += wlp_wss_wssid_e_print(buf + used,
-                                                     bufsize - used,
-                                                     wssid_e);
-               }
-               buf[used++] = '\n';
-               wlp_remove_neighbor_tmp_info(neighb);
-       }
-
-
-out:
-       mutex_unlock(&wlp->nbmutex);
-       return used;
-}
-
-
-/**
- * Show properties of all WSS in neighborhood.
- *
- * Will trigger a complete discovery of WSS activated by this device and
- * its neighbors.
- */
-ssize_t wlp_neighborhood_show(struct wlp *wlp, char *buf)
-{
-       wlp_discover(wlp);
-       return wlp_wss_neighborhood_print_remove(wlp, buf, PAGE_SIZE);
-}
-EXPORT_SYMBOL_GPL(wlp_neighborhood_show);
-
-static
-ssize_t __wlp_wss_properties_show(struct wlp_wss *wss, char *buf,
-                                 size_t bufsize)
-{
-       ssize_t result;
-
-       result = wlp_wss_uuid_print(buf, bufsize, &wss->wssid);
-       result += scnprintf(buf + result, bufsize - result, " ");
-       result += uwb_mac_addr_print(buf + result, bufsize - result,
-                                    &wss->bcast);
-       result += scnprintf(buf + result, bufsize - result,
-                           " 0x%02x %u ", wss->hash, wss->secure_status);
-       result += wlp_wss_key_print(buf + result, bufsize - result,
-                                   wss->master_key);
-       result += scnprintf(buf + result, bufsize - result, " 0x%02x ",
-                           wss->tag);
-       result += uwb_mac_addr_print(buf + result, bufsize - result,
-                                    &wss->virtual_addr);
-       result += scnprintf(buf + result, bufsize - result, " %s", wss->name);
-       result += scnprintf(buf + result, bufsize - result,
-                           "\n\n#WSSID\n#WSS broadcast address\n"
-                           "#WSS hash\n#WSS secure status\n"
-                           "#WSS master key\n#WSS local tag\n"
-                           "#WSS local virtual EUI-48\n#WSS name\n");
-       return result;
-}
-
-/**
- * Show which WSS is activated.
- */
-ssize_t wlp_wss_activate_show(struct wlp_wss *wss, char *buf)
-{
-       int result = 0;
-
-       if (mutex_lock_interruptible(&wss->mutex))
-               goto out;
-       if (wss->state >= WLP_WSS_STATE_ACTIVE)
-               result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
-       else
-               result = scnprintf(buf, PAGE_SIZE, "No local WSS active.\n");
-       result += scnprintf(buf + result, PAGE_SIZE - result,
-                       "\n\n"
-                       "# echo WSSID SECURE_STATUS ACCEPT_ENROLLMENT "
-                       "NAME #create new WSS\n"
-                       "# echo WSSID [DEV ADDR] #enroll in and activate "
-                       "existing WSS, can request registrar\n"
-                       "#\n"
-                       "# WSSID is a 16 byte hex array. Eg. 12 A3 3B ... \n"
-                       "# SECURE_STATUS 0 - unsecure, 1 - secure (default)\n"
-                       "# ACCEPT_ENROLLMENT 0 - no, 1 - yes (default)\n"
-                       "# NAME is the text string identifying the WSS\n"
-                       "# DEV ADDR is the device address of neighbor "
-                       "that should be registrar. Eg. 32:AB\n");
-
-       mutex_unlock(&wss->mutex);
-out:
-       return result;
-
-}
-EXPORT_SYMBOL_GPL(wlp_wss_activate_show);
-
-/**
- * Create/activate a new WSS or enroll/activate in neighboring WSS
- *
- * The user can provide the WSSID of a WSS in which it wants to enroll.
- * Only the WSSID is necessary if the WSS have been discovered before. If
- * the WSS has not been discovered before, or the user wants to use a
- * particular neighbor as its registrar, then the user can also provide a
- * device address or the neighbor that will be used as registrar.
- *
- * A new WSS is created when the user provides a WSSID, secure status, and
- * WSS name.
- */
-ssize_t wlp_wss_activate_store(struct wlp_wss *wss,
-                              const char *buf, size_t size)
-{
-       ssize_t result = -EINVAL;
-       struct wlp_uuid wssid;
-       struct uwb_dev_addr dev;
-       struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };
-       char name[65];
-       unsigned sec_status, accept;
-       memset(name, 0, sizeof(name));
-       result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx:%02hhx",
-                       &wssid.data[0] , &wssid.data[1],
-                       &wssid.data[2] , &wssid.data[3],
-                       &wssid.data[4] , &wssid.data[5],
-                       &wssid.data[6] , &wssid.data[7],
-                       &wssid.data[8] , &wssid.data[9],
-                       &wssid.data[10], &wssid.data[11],
-                       &wssid.data[12], &wssid.data[13],
-                       &wssid.data[14], &wssid.data[15],
-                       &dev.data[1], &dev.data[0]);
-       if (result == 16 || result == 17) {
-               result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
-                               "%02hhx %02hhx %02hhx %02hhx "
-                               "%02hhx %02hhx %02hhx %02hhx "
-                               "%02hhx %02hhx %02hhx %02hhx "
-                               "%u %u %64c",
-                               &wssid.data[0] , &wssid.data[1],
-                               &wssid.data[2] , &wssid.data[3],
-                               &wssid.data[4] , &wssid.data[5],
-                               &wssid.data[6] , &wssid.data[7],
-                               &wssid.data[8] , &wssid.data[9],
-                               &wssid.data[10], &wssid.data[11],
-                               &wssid.data[12], &wssid.data[13],
-                               &wssid.data[14], &wssid.data[15],
-                               &sec_status, &accept, name);
-               if (result == 16)
-                       result = wlp_wss_enroll_activate(wss, &wssid, &bcast);
-               else if (result == 19) {
-                       sec_status = sec_status == 0 ? 0 : 1;
-                       accept = accept == 0 ? 0 : 1;
-                       /* We read name using %c, so the newline needs to be
-                        * removed */
-                       if (strlen(name) != sizeof(name) - 1)
-                               name[strlen(name) - 1] = '\0';
-                       result = wlp_wss_create_activate(wss, &wssid, name,
-                                                        sec_status, accept);
-               } else
-                       result = -EINVAL;
-       } else if (result == 18)
-               result = wlp_wss_enroll_activate(wss, &wssid, &dev);
-       else
-               result = -EINVAL;
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_wss_activate_store);
-
-/**
- * Show the UUID of this host
- */
-ssize_t wlp_uuid_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-
-       mutex_lock(&wlp->mutex);
-       result = wlp_wss_uuid_print(buf, PAGE_SIZE, &wlp->uuid);
-       buf[result++] = '\n';
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_uuid_show);
-
-/**
- * Store a new UUID for this host
- *
- * According to the spec this should be encoded as an octet string in the
- * order the octets are shown in string representation in RFC 4122 (WLP
- * 0.99 [Table 6])
- *
- * We do not check value provided by user.
- */
-ssize_t wlp_uuid_store(struct wlp *wlp, const char *buf, size_t size)
-{
-       ssize_t result;
-       struct wlp_uuid uuid;
-
-       mutex_lock(&wlp->mutex);
-       result = sscanf(buf, "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx "
-                       "%02hhx %02hhx %02hhx %02hhx ",
-                       &uuid.data[0] , &uuid.data[1],
-                       &uuid.data[2] , &uuid.data[3],
-                       &uuid.data[4] , &uuid.data[5],
-                       &uuid.data[6] , &uuid.data[7],
-                       &uuid.data[8] , &uuid.data[9],
-                       &uuid.data[10], &uuid.data[11],
-                       &uuid.data[12], &uuid.data[13],
-                       &uuid.data[14], &uuid.data[15]);
-       if (result != 16) {
-               result = -EINVAL;
-               goto error;
-       }
-       wlp->uuid = uuid;
-error:
-       mutex_unlock(&wlp->mutex);
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_uuid_store);
-
-/**
- * Show contents of members of device information structure
- */
-#define wlp_dev_info_show(type)                                                \
-ssize_t wlp_dev_##type##_show(struct wlp *wlp, char *buf)              \
-{                                                                      \
-       ssize_t result = 0;                                             \
-       mutex_lock(&wlp->mutex);                                        \
-       if (wlp->dev_info == NULL) {                                    \
-               result = __wlp_setup_device_info(wlp);                  \
-               if (result < 0)                                         \
-                       goto out;                                       \
-       }                                                               \
-       result = scnprintf(buf, PAGE_SIZE, "%s\n", wlp->dev_info->type);\
-out:                                                                   \
-       mutex_unlock(&wlp->mutex);                                      \
-       return result;                                                  \
-}                                                                      \
-EXPORT_SYMBOL_GPL(wlp_dev_##type##_show);
-
-wlp_dev_info_show(name)
-wlp_dev_info_show(model_name)
-wlp_dev_info_show(model_nr)
-wlp_dev_info_show(manufacturer)
-wlp_dev_info_show(serial)
-
-/**
- * Store contents of members of device information structure
- */
-#define wlp_dev_info_store(type, len)                                  \
-ssize_t wlp_dev_##type##_store(struct wlp *wlp, const char *buf, size_t size)\
-{                                                                      \
-       ssize_t result;                                                 \
-       char format[10];                                                \
-       mutex_lock(&wlp->mutex);                                        \
-       if (wlp->dev_info == NULL) {                                    \
-               result = __wlp_alloc_device_info(wlp);                  \
-               if (result < 0)                                         \
-                       goto out;                                       \
-       }                                                               \
-       memset(wlp->dev_info->type, 0, sizeof(wlp->dev_info->type));    \
-       sprintf(format, "%%%uc", len);                                  \
-       result = sscanf(buf, format, wlp->dev_info->type);              \
-out:                                                                   \
-       mutex_unlock(&wlp->mutex);                                      \
-       return result < 0 ? result : size;                              \
-}                                                                      \
-EXPORT_SYMBOL_GPL(wlp_dev_##type##_store);
-
-wlp_dev_info_store(name, 32)
-wlp_dev_info_store(manufacturer, 64)
-wlp_dev_info_store(model_name, 32)
-wlp_dev_info_store(model_nr, 32)
-wlp_dev_info_store(serial, 32)
-
-static
-const char *__wlp_dev_category[] = {
-       [WLP_DEV_CAT_COMPUTER] = "Computer",
-       [WLP_DEV_CAT_INPUT] = "Input device",
-       [WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER] = "Printer, scanner, FAX, or "
-                                             "Copier",
-       [WLP_DEV_CAT_CAMERA] = "Camera",
-       [WLP_DEV_CAT_STORAGE] = "Storage Network",
-       [WLP_DEV_CAT_INFRASTRUCTURE] = "Infrastructure",
-       [WLP_DEV_CAT_DISPLAY] = "Display",
-       [WLP_DEV_CAT_MULTIM] = "Multimedia device",
-       [WLP_DEV_CAT_GAMING] = "Gaming device",
-       [WLP_DEV_CAT_TELEPHONE] = "Telephone",
-       [WLP_DEV_CAT_OTHER] = "Other",
-};
-
-static
-const char *wlp_dev_category_str(unsigned cat)
-{
-       if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
-           || cat == WLP_DEV_CAT_OTHER)
-               return __wlp_dev_category[cat];
-       return "unknown category";
-}
-
-ssize_t wlp_dev_prim_category_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = scnprintf(buf, PAGE_SIZE, "%s\n",
-                 wlp_dev_category_str(wlp->dev_info->prim_dev_type.category));
-out:
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_category_show);
-
-ssize_t wlp_dev_prim_category_store(struct wlp *wlp, const char *buf,
-                                   size_t size)
-{
-       ssize_t result;
-       u16 cat;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_alloc_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = sscanf(buf, "%hu", &cat);
-       if ((cat >= WLP_DEV_CAT_COMPUTER && cat <= WLP_DEV_CAT_TELEPHONE)
-           || cat == WLP_DEV_CAT_OTHER)
-               wlp->dev_info->prim_dev_type.category = cat;
-       else
-               result = -EINVAL;
-out:
-       mutex_unlock(&wlp->mutex);
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_category_store);
-
-ssize_t wlp_dev_prim_OUI_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = scnprintf(buf, PAGE_SIZE, "%02x:%02x:%02x\n",
-                          wlp->dev_info->prim_dev_type.OUI[0],
-                          wlp->dev_info->prim_dev_type.OUI[1],
-                          wlp->dev_info->prim_dev_type.OUI[2]);
-out:
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_show);
-
-ssize_t wlp_dev_prim_OUI_store(struct wlp *wlp, const char *buf, size_t size)
-{
-       ssize_t result;
-       u8 OUI[3];
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_alloc_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = sscanf(buf, "%hhx:%hhx:%hhx",
-                       &OUI[0], &OUI[1], &OUI[2]);
-       if (result != 3) {
-               result = -EINVAL;
-               goto out;
-       } else
-               memcpy(wlp->dev_info->prim_dev_type.OUI, OUI, sizeof(OUI));
-out:
-       mutex_unlock(&wlp->mutex);
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_store);
-
-
-ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = scnprintf(buf, PAGE_SIZE, "%u\n",
-                          wlp->dev_info->prim_dev_type.OUIsubdiv);
-out:
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_show);
-
-ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *wlp, const char *buf,
-                                  size_t size)
-{
-       ssize_t result;
-       unsigned sub;
-       u8 max_sub = ~0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_alloc_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = sscanf(buf, "%u", &sub);
-       if (sub <= max_sub)
-               wlp->dev_info->prim_dev_type.OUIsubdiv = sub;
-       else
-               result = -EINVAL;
-out:
-       mutex_unlock(&wlp->mutex);
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_OUI_sub_store);
-
-ssize_t wlp_dev_prim_subcat_show(struct wlp *wlp, char *buf)
-{
-       ssize_t result = 0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_setup_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = scnprintf(buf, PAGE_SIZE, "%u\n",
-                          wlp->dev_info->prim_dev_type.subID);
-out:
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_show);
-
-ssize_t wlp_dev_prim_subcat_store(struct wlp *wlp, const char *buf,
-                                 size_t size)
-{
-       ssize_t result;
-       unsigned sub;
-       __le16 max_sub = ~0;
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info == NULL) {
-               result = __wlp_alloc_device_info(wlp);
-               if (result < 0)
-                       goto out;
-       }
-       result = sscanf(buf, "%u", &sub);
-       if (sub <= max_sub)
-               wlp->dev_info->prim_dev_type.subID = sub;
-       else
-               result = -EINVAL;
-out:
-       mutex_unlock(&wlp->mutex);
-       return result < 0 ? result : size;
-}
-EXPORT_SYMBOL_GPL(wlp_dev_prim_subcat_store);
-
-/**
- * Subsystem implementation for interaction with individual WSS via sysfs
- *
- * Followed instructions for subsystem in Documentation/filesystems/sysfs.txt
- */
-
-#define kobj_to_wlp_wss(obj) container_of(obj, struct wlp_wss, kobj)
-#define attr_to_wlp_wss_attr(_attr) \
-       container_of(_attr, struct wlp_wss_attribute, attr)
-
-/**
- * Sysfs subsystem: forward read calls
- *
- * Sysfs operation for forwarding read call to the show method of the
- * attribute owner
- */
-static
-ssize_t wlp_wss_attr_show(struct kobject *kobj, struct attribute *attr,
-                         char *buf)
-{
-       struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
-       struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
-       ssize_t ret = -EIO;
-
-       if (wss_attr->show)
-               ret = wss_attr->show(wss, buf);
-       return ret;
-}
-/**
- * Sysfs subsystem: forward write calls
- *
- * Sysfs operation for forwarding write call to the store method of the
- * attribute owner
- */
-static
-ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr,
-                          const char *buf, size_t count)
-{
-       struct wlp_wss_attribute *wss_attr = attr_to_wlp_wss_attr(attr);
-       struct wlp_wss *wss = kobj_to_wlp_wss(kobj);
-       ssize_t ret = -EIO;
-
-       if (wss_attr->store)
-               ret = wss_attr->store(wss, buf, count);
-       return ret;
-}
-
-static const struct sysfs_ops wss_sysfs_ops = {
-       .show   = wlp_wss_attr_show,
-       .store  = wlp_wss_attr_store,
-};
-
-struct kobj_type wss_ktype = {
-       .release        = wlp_wss_release,
-       .sysfs_ops      = &wss_sysfs_ops,
-};
-
-
-/**
- * Sysfs files for individual WSS
- */
-
-/**
- * Print static properties of this WSS
- *
- * The name of a WSS may not be null teminated. It's max size is 64 bytes
- * so we copy it to a larger array just to make sure we print sane data.
- */
-static ssize_t wlp_wss_properties_show(struct wlp_wss *wss, char *buf)
-{
-       int result = 0;
-
-       if (mutex_lock_interruptible(&wss->mutex))
-               goto out;
-       result = __wlp_wss_properties_show(wss, buf, PAGE_SIZE);
-       mutex_unlock(&wss->mutex);
-out:
-       return result;
-}
-WSS_ATTR(properties, S_IRUGO, wlp_wss_properties_show, NULL);
-
-/**
- * Print all connected members of this WSS
- * The EDA cache contains all members of WSS neighborhood.
- */
-static ssize_t wlp_wss_members_show(struct wlp_wss *wss, char *buf)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       return wlp_eda_show(wlp, buf);
-}
-WSS_ATTR(members, S_IRUGO, wlp_wss_members_show, NULL);
-
-static
-const char *__wlp_strstate[] = {
-       "none",
-       "partially enrolled",
-       "enrolled",
-       "active",
-       "connected",
-};
-
-static const char *wlp_wss_strstate(unsigned state)
-{
-       if (state >= ARRAY_SIZE(__wlp_strstate))
-               return "unknown state";
-       return __wlp_strstate[state];
-}
-
-/*
- * Print current state of this WSS
- */
-static ssize_t wlp_wss_state_show(struct wlp_wss *wss, char *buf)
-{
-       int result = 0;
-
-       if (mutex_lock_interruptible(&wss->mutex))
-               goto out;
-       result = scnprintf(buf, PAGE_SIZE, "%s\n",
-                          wlp_wss_strstate(wss->state));
-       mutex_unlock(&wss->mutex);
-out:
-       return result;
-}
-WSS_ATTR(state, S_IRUGO, wlp_wss_state_show, NULL);
-
-
-static
-struct attribute *wss_attrs[] = {
-       &wss_attr_properties.attr,
-       &wss_attr_members.attr,
-       &wss_attr_state.attr,
-       NULL,
-};
-
-struct attribute_group wss_attr_group = {
-       .name = NULL,   /* we want them in the same directory */
-       .attrs = wss_attrs,
-};
diff --git a/drivers/uwb/wlp/txrx.c b/drivers/uwb/wlp/txrx.c
deleted file mode 100644 (file)
index 05dde44..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- * Message exchange infrastructure
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: Docs
- *
- */
-
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/wlp.h>
-
-#include "wlp-internal.h"
-
-/*
- * Direct incoming association msg to correct parsing routine
- *
- * We only expect D1, E1, C1, C3 messages as new. All other incoming
- * association messages should form part of an established session that is
- * handled elsewhere.
- * The handling of these messages often require calling sleeping functions
- * - this cannot be done in interrupt context. We use the kernel's
- * workqueue to handle these messages.
- */
-static
-void wlp_direct_assoc_frame(struct wlp *wlp, struct sk_buff *skb,
-                          struct uwb_dev_addr *src)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *assoc = (void *) skb->data;
-       struct wlp_assoc_frame_ctx *frame_ctx;
-
-       frame_ctx = kmalloc(sizeof(*frame_ctx), GFP_ATOMIC);
-       if (frame_ctx == NULL) {
-               dev_err(dev, "WLP: Unable to allocate memory for association "
-                       "frame handling.\n");
-               kfree_skb(skb);
-               return;
-       }
-       frame_ctx->wlp = wlp;
-       frame_ctx->skb = skb;
-       frame_ctx->src = *src;
-       switch (assoc->type) {
-       case WLP_ASSOC_D1:
-               INIT_WORK(&frame_ctx->ws, wlp_handle_d1_frame);
-               schedule_work(&frame_ctx->ws);
-               break;
-       case WLP_ASSOC_E1:
-               kfree_skb(skb); /* Temporary until we handle it */
-               kfree(frame_ctx); /* Temporary until we handle it */
-               break;
-       case WLP_ASSOC_C1:
-               INIT_WORK(&frame_ctx->ws, wlp_handle_c1_frame);
-               schedule_work(&frame_ctx->ws);
-               break;
-       case WLP_ASSOC_C3:
-               INIT_WORK(&frame_ctx->ws, wlp_handle_c3_frame);
-               schedule_work(&frame_ctx->ws);
-               break;
-       default:
-               dev_err(dev, "Received unexpected association frame. "
-                       "Type = %d \n", assoc->type);
-               kfree_skb(skb);
-               kfree(frame_ctx);
-               break;
-       }
-}
-
-/*
- * Process incoming association frame
- *
- * Although it could be possible to deal with some incoming association
- * messages without creating a new session we are keeping things simple. We
- * do not accept new association messages if there is a session in progress
- * and the messages do not belong to that session.
- *
- * If an association message arrives that causes the creation of a session
- * (WLP_ASSOC_E1) while we are in the process of creating a session then we
- * rely on the neighbor mutex to protect the data. That is, the new session
- * will not be started until the previous is completed.
- */
-static
-void wlp_receive_assoc_frame(struct wlp *wlp, struct sk_buff *skb,
-                            struct uwb_dev_addr *src)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_frame_assoc *assoc = (void *) skb->data;
-       struct wlp_session *session = wlp->session;
-       u8 version;
-
-       if (wlp_get_version(wlp, &assoc->version, &version,
-                           sizeof(assoc->version)) < 0)
-               goto error;
-       if (version != WLP_VERSION) {
-               dev_err(dev, "Unsupported WLP version in association "
-                       "message.\n");
-               goto error;
-       }
-       if (session != NULL) {
-               /* Function that created this session is still holding the
-                * &wlp->mutex to protect this session. */
-               if (assoc->type == session->exp_message ||
-                   assoc->type == WLP_ASSOC_F0) {
-                       if (!memcmp(&session->neighbor_addr, src,
-                                  sizeof(*src))) {
-                               session->data = skb;
-                               (session->cb)(wlp);
-                       } else {
-                               dev_err(dev, "Received expected message from "
-                                       "unexpected source.  Expected message "
-                                       "%d or F0 from %02x:%02x, but received "
-                                       "it from %02x:%02x. Dropping.\n",
-                                       session->exp_message,
-                                       session->neighbor_addr.data[1],
-                                       session->neighbor_addr.data[0],
-                                       src->data[1], src->data[0]);
-                               goto error;
-                       }
-               } else {
-                       dev_err(dev, "Association already in progress. "
-                               "Dropping.\n");
-                       goto error;
-               }
-       } else {
-               wlp_direct_assoc_frame(wlp, skb, src);
-       }
-       return;
-error:
-       kfree_skb(skb);
-}
-
-/*
- * Verify incoming frame is from connected neighbor, prep to pass to WLP client
- *
- * Verification proceeds according to WLP 0.99 [7.3.1]. The source address
- * is used to determine which neighbor is sending the frame and the WSS tag
- * is used to know to which WSS the frame belongs (we only support one WSS
- * so this test is straight forward).
- * With the WSS found we need to ensure that we are connected before
- * allowing the exchange of data frames.
- */
-static
-int wlp_verify_prep_rx_frame(struct wlp *wlp, struct sk_buff *skb,
-                            struct uwb_dev_addr *src)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = -EINVAL;
-       struct wlp_eda_node eda_entry;
-       struct wlp_frame_std_abbrv_hdr *hdr = (void *) skb->data;
-
-       /*verify*/
-       result = wlp_copy_eda_node(&wlp->eda, src, &eda_entry);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Incoming frame is from unknown "
-                               "neighbor %02x:%02x.\n", src->data[1],
-                               src->data[0]);
-               goto out;
-       }
-       if (hdr->tag != eda_entry.tag) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Tag of incoming frame from "
-                               "%02x:%02x does not match expected tag. "
-                               "Received 0x%02x, expected 0x%02x. \n",
-                               src->data[1], src->data[0], hdr->tag,
-                               eda_entry.tag);
-               result = -EINVAL;
-               goto out;
-       }
-       if (eda_entry.state != WLP_WSS_CONNECTED) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Incoming frame from "
-                               "%02x:%02x does is not from connected WSS.\n",
-                               src->data[1], src->data[0]);
-               result = -EINVAL;
-               goto out;
-       }
-       /*prep*/
-       skb_pull(skb, sizeof(*hdr));
-out:
-       return result;
-}
-
-/*
- * Receive a WLP frame from device
- *
- * @returns: 1 if calling function should free the skb
- *           0 if it successfully handled skb and freed it
- *           0 if error occured, will free skb in this case
- */
-int wlp_receive_frame(struct device *dev, struct wlp *wlp, struct sk_buff *skb,
-                     struct uwb_dev_addr *src)
-{
-       unsigned len = skb->len;
-       void *ptr = skb->data;
-       struct wlp_frame_hdr *hdr;
-       int result = 0;
-
-       if (len < sizeof(*hdr)) {
-               dev_err(dev, "Not enough data to parse WLP header.\n");
-               result = -EINVAL;
-               goto out;
-       }
-       hdr = ptr;
-       if (le16_to_cpu(hdr->mux_hdr) != WLP_PROTOCOL_ID) {
-               dev_err(dev, "Not a WLP frame type.\n");
-               result = -EINVAL;
-               goto out;
-       }
-       switch (hdr->type) {
-       case WLP_FRAME_STANDARD:
-               if (len < sizeof(struct wlp_frame_std_abbrv_hdr)) {
-                       dev_err(dev, "Not enough data to parse Standard "
-                               "WLP header.\n");
-                       goto out;
-               }
-               result = wlp_verify_prep_rx_frame(wlp, skb, src);
-               if (result < 0) {
-                       if (printk_ratelimit())
-                               dev_err(dev, "WLP: Verification of frame "
-                                       "from neighbor %02x:%02x failed.\n",
-                                       src->data[1], src->data[0]);
-                       goto out;
-               }
-               result = 1;
-               break;
-       case WLP_FRAME_ABBREVIATED:
-               dev_err(dev, "Abbreviated frame received. FIXME?\n");
-               kfree_skb(skb);
-               break;
-       case WLP_FRAME_CONTROL:
-               dev_err(dev, "Control frame received. FIXME?\n");
-               kfree_skb(skb);
-               break;
-       case WLP_FRAME_ASSOCIATION:
-               if (len < sizeof(struct wlp_frame_assoc)) {
-                       dev_err(dev, "Not enough data to parse Association "
-                               "WLP header.\n");
-                       goto out;
-               }
-               wlp_receive_assoc_frame(wlp, skb, src);
-               break;
-       default:
-               dev_err(dev, "Invalid frame received.\n");
-               result = -EINVAL;
-               break;
-       }
-out:
-       if (result < 0) {
-               kfree_skb(skb);
-               result = 0;
-       }
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_receive_frame);
-
-
-/*
- * Verify frame from network stack, prepare for further transmission
- *
- * @skb:   the socket buffer that needs to be prepared for transmission (it
- *         is in need of a WLP header). If this is a broadcast frame we take
- *         over the entire transmission.
- *         If it is a unicast the WSS connection should already be established
- *         and transmission will be done by the calling function.
- * @dst:   On return this will contain the device address to which the
- *         frame is destined.
- * @returns: 0 on success no tx : WLP header successfully applied to skb buffer,
- *                                calling function can proceed with tx
- *           1 on success with tx : WLP will take over transmission of this
- *                                  frame
- *           <0 on error
- *
- * The network stack (WLP client) is attempting to transmit a frame. We can
- * only transmit data if a local WSS is at least active (connection will be
- * done here if this is a broadcast frame and neighbor also has the WSS
- * active).
- *
- * The frame can be either broadcast or unicast. Broadcast in a WSS is
- * supported via multicast, but we don't support multicast yet (until
- * devices start to support MAB IEs). If a broadcast frame needs to be
- * transmitted it is treated as a unicast frame to each neighbor. In this
- * case the WLP takes over transmission of the skb and returns 1
- * to the caller to indicate so. Also, in this case, if a neighbor has the
- * same WSS activated but is not connected then the WSS connection will be
- * done at this time. The neighbor's virtual address will be learned at
- * this time.
- *
- * The destination address in a unicast frame is the virtual address of the
- * neighbor. This address only becomes known when a WSS connection is
- * established. We thus rely on a broadcast frame to trigger the setup of
- * WSS connections to all neighbors before we are able to send unicast
- * frames to them. This seems reasonable as IP would usually use ARP first
- * before any unicast frames are sent.
- *
- * If we are already connected to the neighbor (neighbor's virtual address
- * is known) we just prepare the WLP header and the caller will continue to
- * send the frame.
- *
- * A failure in this function usually indicates something that cannot be
- * fixed automatically. So, if this function fails (@return < 0) the calling
- * function should not retry to send the frame as it will very likely keep
- * failing.
- *
- */
-int wlp_prepare_tx_frame(struct device *dev, struct wlp *wlp,
-                        struct sk_buff *skb, struct uwb_dev_addr *dst)
-{
-       int result = -EINVAL;
-       struct ethhdr *eth_hdr = (void *) skb->data;
-
-       if (is_multicast_ether_addr(eth_hdr->h_dest)) {
-               result = wlp_eda_for_each(&wlp->eda, wlp_wss_send_copy, skb);
-               if (result < 0) {
-                       if (printk_ratelimit())
-                               dev_err(dev, "Unable to handle broadcast "
-                                       "frame from WLP client.\n");
-                       goto out;
-               }
-               dev_kfree_skb_irq(skb);
-               result = 1;
-               /* Frame will be transmitted by WLP. */
-       } else {
-               result = wlp_eda_for_virtual(&wlp->eda, eth_hdr->h_dest, dst,
-                                            wlp_wss_prep_hdr, skb);
-               if (unlikely(result < 0)) {
-                       if (printk_ratelimit())
-                               dev_err(dev, "Unable to prepare "
-                                       "skb for transmission. \n");
-                       goto out;
-               }
-       }
-out:
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_prepare_tx_frame);
diff --git a/drivers/uwb/wlp/wlp-internal.h b/drivers/uwb/wlp/wlp-internal.h
deleted file mode 100644 (file)
index 3e8d5de..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- * Internal API
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#ifndef __WLP_INTERNAL_H__
-#define __WLP_INTERNAL_H__
-
-/**
- * State of WSS connection
- *
- * A device needs to connect to a neighbor in an activated WSS before data
- * can be transmitted. The spec also distinguishes between a new connection
- * attempt and a connection attempt after previous connection attempts. The
- * state WLP_WSS_CONNECT_FAILED is used for this scenario. See WLP 0.99
- * [7.2.6]
- */
-enum wlp_wss_connect {
-       WLP_WSS_UNCONNECTED = 0,
-       WLP_WSS_CONNECTED,
-       WLP_WSS_CONNECT_FAILED,
-};
-
-extern struct kobj_type wss_ktype;
-extern struct attribute_group wss_attr_group;
-
-/* This should be changed to a dynamic array where entries are sorted
- * by eth_addr and search is done in a binary form
- *
- * Although thinking twice about it: this technologie's maximum reach
- * is 10 meters...unless you want to pack too much stuff in around
- * your radio controller/WLP device, the list will probably not be
- * too big.
- *
- * In any case, there is probably some data structure in the kernel
- * than we could reused for that already.
- *
- * The below structure is really just good while we support one WSS per
- * host.
- */
-struct wlp_eda_node {
-       struct list_head list_node;
-       unsigned char eth_addr[ETH_ALEN];
-       struct uwb_dev_addr dev_addr;
-       struct wlp_wss *wss;
-       unsigned char virt_addr[ETH_ALEN];
-       u8 tag;
-       enum wlp_wss_connect state;
-};
-
-typedef int (*wlp_eda_for_each_f)(struct wlp *, struct wlp_eda_node *, void *);
-
-extern void wlp_eda_init(struct wlp_eda *);
-extern void wlp_eda_release(struct wlp_eda *);
-extern int wlp_eda_create_node(struct wlp_eda *,
-                              const unsigned char eth_addr[ETH_ALEN],
-                              const struct uwb_dev_addr *);
-extern void wlp_eda_rm_node(struct wlp_eda *, const struct uwb_dev_addr *);
-extern int wlp_eda_update_node(struct wlp_eda *,
-                              const struct uwb_dev_addr *,
-                              struct wlp_wss *,
-                              const unsigned char virt_addr[ETH_ALEN],
-                              const u8, const enum wlp_wss_connect);
-extern int wlp_eda_update_node_state(struct wlp_eda *,
-                                    const struct uwb_dev_addr *,
-                                    const enum wlp_wss_connect);
-
-extern int wlp_copy_eda_node(struct wlp_eda *, struct uwb_dev_addr *,
-                            struct wlp_eda_node *);
-extern int wlp_eda_for_each(struct wlp_eda *, wlp_eda_for_each_f , void *);
-extern int wlp_eda_for_virtual(struct wlp_eda *,
-                              const unsigned char eth_addr[ETH_ALEN],
-                              struct uwb_dev_addr *,
-                              wlp_eda_for_each_f , void *);
-
-
-extern void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *);
-
-extern size_t wlp_wss_key_print(char *, size_t, u8 *);
-
-/* Function called when no more references to WSS exists */
-extern void wlp_wss_release(struct kobject *);
-
-extern void wlp_wss_reset(struct wlp_wss *);
-extern int wlp_wss_create_activate(struct wlp_wss *, struct wlp_uuid *,
-                                  char *, unsigned, unsigned);
-extern int wlp_wss_enroll_activate(struct wlp_wss *, struct wlp_uuid *,
-                                  struct uwb_dev_addr *);
-extern ssize_t wlp_discover(struct wlp *);
-
-extern int wlp_enroll_neighbor(struct wlp *, struct wlp_neighbor_e *,
-                              struct wlp_wss *, struct wlp_uuid *);
-extern int wlp_wss_is_active(struct wlp *, struct wlp_wss *,
-                            struct uwb_dev_addr *);
-
-struct wlp_assoc_conn_ctx {
-       struct work_struct ws;
-       struct wlp *wlp;
-       struct sk_buff *skb;
-       struct wlp_eda_node eda_entry;
-};
-
-
-extern int wlp_wss_connect_prep(struct wlp *, struct wlp_eda_node *, void *);
-extern int wlp_wss_send_copy(struct wlp *, struct wlp_eda_node *, void *);
-
-
-/* Message handling */
-struct wlp_assoc_frame_ctx {
-       struct work_struct ws;
-       struct wlp *wlp;
-       struct sk_buff *skb;
-       struct uwb_dev_addr src;
-};
-
-extern int wlp_wss_prep_hdr(struct wlp *, struct wlp_eda_node *, void *);
-extern void wlp_handle_d1_frame(struct work_struct *);
-extern int wlp_parse_d2_frame_to_cache(struct wlp *, struct sk_buff *,
-                                      struct wlp_neighbor_e *);
-extern int wlp_parse_d2_frame_to_enroll(struct wlp_wss *, struct sk_buff *,
-                                       struct wlp_neighbor_e *,
-                                       struct wlp_uuid *);
-extern void wlp_handle_c1_frame(struct work_struct *);
-extern void wlp_handle_c3_frame(struct work_struct *);
-extern int wlp_parse_c3c4_frame(struct wlp *, struct sk_buff *,
-                               struct wlp_uuid *, u8 *,
-                               struct uwb_mac_addr *);
-extern int wlp_parse_f0(struct wlp *, struct sk_buff *);
-extern int wlp_send_assoc_frame(struct wlp *, struct wlp_wss *,
-                               struct uwb_dev_addr *, enum wlp_assoc_type);
-extern ssize_t wlp_get_version(struct wlp *, struct wlp_attr_version *,
-                              u8 *, ssize_t);
-extern ssize_t wlp_get_wssid(struct wlp *, struct wlp_attr_wssid *,
-                            struct wlp_uuid *, ssize_t);
-extern int __wlp_alloc_device_info(struct wlp *);
-extern int __wlp_setup_device_info(struct wlp *);
-
-extern struct wlp_wss_attribute wss_attribute_properties;
-extern struct wlp_wss_attribute wss_attribute_members;
-extern struct wlp_wss_attribute wss_attribute_state;
-
-static inline
-size_t wlp_wss_uuid_print(char *buf, size_t bufsize, struct wlp_uuid *uuid)
-{
-       size_t result;
-
-       result = scnprintf(buf, bufsize,
-                         "%02x:%02x:%02x:%02x:%02x:%02x:"
-                         "%02x:%02x:%02x:%02x:%02x:%02x:"
-                         "%02x:%02x:%02x:%02x",
-                         uuid->data[0], uuid->data[1],
-                         uuid->data[2], uuid->data[3],
-                         uuid->data[4], uuid->data[5],
-                         uuid->data[6], uuid->data[7],
-                         uuid->data[8], uuid->data[9],
-                         uuid->data[10], uuid->data[11],
-                         uuid->data[12], uuid->data[13],
-                         uuid->data[14], uuid->data[15]);
-       return result;
-}
-
-/**
- * FIXME: How should a nonce be displayed?
- */
-static inline
-size_t wlp_wss_nonce_print(char *buf, size_t bufsize, struct wlp_nonce *nonce)
-{
-       size_t result;
-
-       result = scnprintf(buf, bufsize,
-                         "%02x %02x %02x %02x %02x %02x "
-                         "%02x %02x %02x %02x %02x %02x "
-                         "%02x %02x %02x %02x",
-                         nonce->data[0], nonce->data[1],
-                         nonce->data[2], nonce->data[3],
-                         nonce->data[4], nonce->data[5],
-                         nonce->data[6], nonce->data[7],
-                         nonce->data[8], nonce->data[9],
-                         nonce->data[10], nonce->data[11],
-                         nonce->data[12], nonce->data[13],
-                         nonce->data[14], nonce->data[15]);
-       return result;
-}
-
-
-static inline
-void wlp_session_cb(struct wlp *wlp)
-{
-       struct completion *completion = wlp->session->cb_priv;
-       complete(completion);
-}
-
-static inline
-int wlp_uuid_is_set(struct wlp_uuid *uuid)
-{
-       struct wlp_uuid zero_uuid = { .data = { 0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00,
-                                               0x00, 0x00, 0x00, 0x00} };
-
-       if (!memcmp(uuid, &zero_uuid, sizeof(*uuid)))
-               return 0;
-       return 1;
-}
-
-#endif /* __WLP_INTERNAL_H__ */
diff --git a/drivers/uwb/wlp/wlp-lc.c b/drivers/uwb/wlp/wlp-lc.c
deleted file mode 100644 (file)
index 7f6a630..0000000
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- */
-#include <linux/wlp.h>
-#include <linux/slab.h>
-
-#include "wlp-internal.h"
-
-static
-void wlp_neighbor_init(struct wlp_neighbor_e *neighbor)
-{
-       INIT_LIST_HEAD(&neighbor->wssid);
-}
-
-/**
- * Create area for device information storage
- *
- * wlp->mutex must be held
- */
-int __wlp_alloc_device_info(struct wlp *wlp)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       BUG_ON(wlp->dev_info != NULL);
-       wlp->dev_info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
-       if (wlp->dev_info == NULL) {
-               dev_err(dev, "WLP: Unable to allocate memory for "
-                       "device information.\n");
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-
-/**
- * Fill in device information using function provided by driver
- *
- * wlp->mutex must be held
- */
-static
-void __wlp_fill_device_info(struct wlp *wlp)
-{
-       wlp->fill_device_info(wlp, wlp->dev_info);
-}
-
-/**
- * Setup device information
- *
- * Allocate area for device information and populate it.
- *
- * wlp->mutex must be held
- */
-int __wlp_setup_device_info(struct wlp *wlp)
-{
-       int result;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-
-       result = __wlp_alloc_device_info(wlp);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to allocate area for "
-                       "device information.\n");
-               return result;
-       }
-       __wlp_fill_device_info(wlp);
-       return 0;
-}
-
-/**
- * Remove information about neighbor stored temporarily
- *
- * Information learned during discovey should only be stored when the
- * device enrolls in the neighbor's WSS. We do need to store this
- * information temporarily in order to present it to the user.
- *
- * We are only interested in keeping neighbor WSS information if that
- * neighbor is accepting enrollment.
- *
- * should be called with wlp->nbmutex held
- */
-void wlp_remove_neighbor_tmp_info(struct wlp_neighbor_e *neighbor)
-{
-       struct wlp_wssid_e *wssid_e, *next;
-       u8 keep;
-       if (!list_empty(&neighbor->wssid)) {
-               list_for_each_entry_safe(wssid_e, next, &neighbor->wssid,
-                                        node) {
-                       if (wssid_e->info != NULL) {
-                               keep = wssid_e->info->accept_enroll;
-                               kfree(wssid_e->info);
-                               wssid_e->info = NULL;
-                               if (!keep) {
-                                       list_del(&wssid_e->node);
-                                       kfree(wssid_e);
-                               }
-                       }
-               }
-       }
-       if (neighbor->info != NULL) {
-               kfree(neighbor->info);
-               neighbor->info = NULL;
-       }
-}
-
-/*
- * Populate WLP neighborhood cache with neighbor information
- *
- * A new neighbor is found. If it is discoverable then we add it to the
- * neighborhood cache.
- *
- */
-static
-int wlp_add_neighbor(struct wlp *wlp, struct uwb_dev *dev)
-{
-       int result = 0;
-       int discoverable;
-       struct wlp_neighbor_e *neighbor;
-
-       /*
-        * FIXME:
-        * Use contents of WLP IE found in beacon cache to determine if
-        * neighbor is discoverable.
-        * The device does not support WLP IE yet so this still needs to be
-        * done. Until then we assume all devices are discoverable.
-        */
-       discoverable = 1; /* will be changed when FIXME disappears */
-       if (discoverable) {
-               /* Add neighbor to cache for discovery */
-               neighbor = kzalloc(sizeof(*neighbor), GFP_KERNEL);
-               if (neighbor == NULL) {
-                       dev_err(&dev->dev, "Unable to create memory for "
-                               "new neighbor. \n");
-                       result = -ENOMEM;
-                       goto error_no_mem;
-               }
-               wlp_neighbor_init(neighbor);
-               uwb_dev_get(dev);
-               neighbor->uwb_dev = dev;
-               list_add(&neighbor->node, &wlp->neighbors);
-       }
-error_no_mem:
-       return result;
-}
-
-/**
- * Remove one neighbor from cache
- */
-static
-void __wlp_neighbor_release(struct wlp_neighbor_e *neighbor)
-{
-       struct wlp_wssid_e *wssid_e, *next_wssid_e;
-
-       list_for_each_entry_safe(wssid_e, next_wssid_e,
-                                &neighbor->wssid, node) {
-               list_del(&wssid_e->node);
-               kfree(wssid_e);
-       }
-       uwb_dev_put(neighbor->uwb_dev);
-       list_del(&neighbor->node);
-       kfree(neighbor);
-}
-
-/**
- * Clear entire neighborhood cache.
- */
-static
-void __wlp_neighbors_release(struct wlp *wlp)
-{
-       struct wlp_neighbor_e *neighbor, *next;
-       if (list_empty(&wlp->neighbors))
-               return;
-       list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
-               __wlp_neighbor_release(neighbor);
-       }
-}
-
-static
-void wlp_neighbors_release(struct wlp *wlp)
-{
-       mutex_lock(&wlp->nbmutex);
-       __wlp_neighbors_release(wlp);
-       mutex_unlock(&wlp->nbmutex);
-}
-
-
-
-/**
- * Send D1 message to neighbor, receive D2 message
- *
- * @neighbor: neighbor to which D1 message will be sent
- * @wss:      if not NULL, it is an enrollment request for this WSS
- * @wssid:    if wss not NULL, this is the wssid of the WSS in which we
- *            want to enroll
- *
- * A D1/D2 exchange is done for one of two reasons: discovery or
- * enrollment. If done for discovery the D1 message is sent to the neighbor
- * and the contents of the D2 response is stored in a temporary cache.
- * If done for enrollment the @wss and @wssid are provided also. In this
- * case the D1 message is sent to the neighbor, the D2 response is parsed
- * for enrollment of the WSS with wssid.
- *
- * &wss->mutex is held
- */
-static
-int wlp_d1d2_exchange(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
-                     struct wlp_wss *wss, struct wlp_uuid *wssid)
-{
-       int result;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       DECLARE_COMPLETION_ONSTACK(completion);
-       struct wlp_session session;
-       struct sk_buff  *skb;
-       struct wlp_frame_assoc *resp;
-       struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
-
-       mutex_lock(&wlp->mutex);
-       if (!wlp_uuid_is_set(&wlp->uuid)) {
-               dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
-                       "proceed.\n");
-               result = -ENXIO;
-               goto out;
-       }
-       /* Send D1 association frame */
-       result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_D1);
-       if (result < 0) {
-               dev_err(dev, "Unable to send D1 frame to neighbor "
-                       "%02x:%02x (%d)\n", dev_addr->data[1],
-                       dev_addr->data[0], result);
-               goto out;
-       }
-       /* Create session, wait for response */
-       session.exp_message = WLP_ASSOC_D2;
-       session.cb = wlp_session_cb;
-       session.cb_priv = &completion;
-       session.neighbor_addr = *dev_addr;
-       BUG_ON(wlp->session != NULL);
-       wlp->session = &session;
-       /* Wait for D2/F0 frame */
-       result = wait_for_completion_interruptible_timeout(&completion,
-                                                  WLP_PER_MSG_TIMEOUT * HZ);
-       if (result == 0) {
-               result = -ETIMEDOUT;
-               dev_err(dev, "Timeout while sending D1 to neighbor "
-                            "%02x:%02x.\n", dev_addr->data[1],
-                            dev_addr->data[0]);
-               goto error_session;
-       }
-       if (result < 0) {
-               dev_err(dev, "Unable to discover/enroll neighbor %02x:%02x.\n",
-                       dev_addr->data[1], dev_addr->data[0]);
-               goto error_session;
-       }
-       /* Parse message in session->data: it will be either D2 or F0 */
-       skb = session.data;
-       resp = (void *) skb->data;
-
-       if (resp->type == WLP_ASSOC_F0) {
-               result = wlp_parse_f0(wlp, skb);
-               if (result < 0)
-                       dev_err(dev, "WLP: Unable to parse F0 from neighbor "
-                               "%02x:%02x.\n", dev_addr->data[1],
-                               dev_addr->data[0]);
-               result = -EINVAL;
-               goto error_resp_parse;
-       }
-       if (wss == NULL) {
-               /* Discovery */
-               result = wlp_parse_d2_frame_to_cache(wlp, skb, neighbor);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to parse D2 message from "
-                               "neighbor %02x:%02x for discovery.\n",
-                               dev_addr->data[1], dev_addr->data[0]);
-                       goto error_resp_parse;
-               }
-       } else {
-               /* Enrollment */
-               result = wlp_parse_d2_frame_to_enroll(wss, skb, neighbor,
-                                                     wssid);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to parse D2 message from "
-                               "neighbor %02x:%02x for enrollment.\n",
-                               dev_addr->data[1], dev_addr->data[0]);
-                       goto error_resp_parse;
-               }
-       }
-error_resp_parse:
-       kfree_skb(skb);
-error_session:
-       wlp->session = NULL;
-out:
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-
-/**
- * Enroll into WSS of provided WSSID by using neighbor as registrar
- *
- * &wss->mutex is held
- */
-int wlp_enroll_neighbor(struct wlp *wlp, struct wlp_neighbor_e *neighbor,
-                       struct wlp_wss *wss, struct wlp_uuid *wssid)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       char buf[WLP_WSS_UUID_STRSIZE];
-       struct uwb_dev_addr *dev_addr = &neighbor->uwb_dev->dev_addr;
-
-       wlp_wss_uuid_print(buf, sizeof(buf), wssid);
-
-       result =  wlp_d1d2_exchange(wlp, neighbor, wss, wssid);
-       if (result < 0) {
-               dev_err(dev, "WLP: D1/D2 message exchange for enrollment "
-                       "failed. result = %d \n", result);
-               goto out;
-       }
-       if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
-               dev_err(dev, "WLP: Unable to enroll into WSS %s using "
-                       "neighbor %02x:%02x. \n", buf,
-                       dev_addr->data[1], dev_addr->data[0]);
-               result = -EINVAL;
-               goto out;
-       }
-       if (wss->secure_status == WLP_WSS_SECURE) {
-               dev_err(dev, "FIXME: need to complete secure enrollment.\n");
-               result = -EINVAL;
-               goto error;
-       } else {
-               wss->state = WLP_WSS_STATE_ENROLLED;
-               dev_dbg(dev, "WLP: Success Enrollment into unsecure WSS "
-                       "%s using neighbor %02x:%02x. \n",
-                       buf, dev_addr->data[1], dev_addr->data[0]);
-       }
-out:
-       return result;
-error:
-       wlp_wss_reset(wss);
-       return result;
-}
-
-/**
- * Discover WSS information of neighbor's active WSS
- */
-static
-int wlp_discover_neighbor(struct wlp *wlp,
-                         struct wlp_neighbor_e *neighbor)
-{
-       return wlp_d1d2_exchange(wlp, neighbor, NULL, NULL);
-}
-
-
-/**
- * Each neighbor in the neighborhood cache is discoverable. Discover it.
- *
- * Discovery is done through sending of D1 association frame and parsing
- * the D2 association frame response. Only wssid from D2 will be included
- * in neighbor cache, rest is just displayed to user and forgotten.
- *
- * The discovery is not done in parallel. This is simple and enables us to
- * maintain only one association context.
- *
- * The discovery of one neighbor does not affect the other, but if the
- * discovery of a neighbor fails it is removed from the neighborhood cache.
- */
-static
-int wlp_discover_all_neighbors(struct wlp *wlp)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_neighbor_e *neighbor, *next;
-
-       list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
-               result = wlp_discover_neighbor(wlp, neighbor);
-               if (result < 0) {
-                       dev_err(dev, "WLP: Unable to discover neighbor "
-                               "%02x:%02x, removing from neighborhood. \n",
-                               neighbor->uwb_dev->dev_addr.data[1],
-                               neighbor->uwb_dev->dev_addr.data[0]);
-                       __wlp_neighbor_release(neighbor);
-               }
-       }
-       return result;
-}
-
-static int wlp_add_neighbor_helper(struct device *dev, void *priv)
-{
-       struct wlp *wlp = priv;
-       struct uwb_dev *uwb_dev = to_uwb_dev(dev);
-
-       return wlp_add_neighbor(wlp, uwb_dev);
-}
-
-/**
- * Discover WLP neighborhood
- *
- * Will send D1 association frame to all devices in beacon group that have
- * discoverable bit set in WLP IE. D2 frames will be received, information
- * displayed to user in @buf. Partial information (from D2 association
- * frame) will be cached to assist with future association
- * requests.
- *
- * The discovery of the WLP neighborhood is triggered by the user. This
- * should occur infrequently and we thus free current cache and re-allocate
- * memory if needed.
- *
- * If one neighbor fails during initial discovery (determining if it is a
- * neighbor or not), we fail all - note that interaction with neighbor has
- * not occured at this point so if a failure occurs we know something went wrong
- * locally. We thus undo everything.
- */
-ssize_t wlp_discover(struct wlp *wlp)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-
-       mutex_lock(&wlp->nbmutex);
-       /* Clear current neighborhood cache. */
-       __wlp_neighbors_release(wlp);
-       /* Determine which devices in neighborhood. Repopulate cache. */
-       result = uwb_dev_for_each(wlp->rc, wlp_add_neighbor_helper, wlp);
-       if (result < 0) {
-               /* May have partial neighbor information, release all. */
-               __wlp_neighbors_release(wlp);
-               goto error_dev_for_each;
-       }
-       /* Discover the properties of devices in neighborhood. */
-       result = wlp_discover_all_neighbors(wlp);
-       /* In case of failure we still print our partial results. */
-       if (result < 0) {
-               dev_err(dev, "Unable to fully discover neighborhood. \n");
-               result = 0;
-       }
-error_dev_for_each:
-       mutex_unlock(&wlp->nbmutex);
-       return result;
-}
-
-/**
- * Handle events from UWB stack
- *
- * We handle events conservatively. If a neighbor goes off the air we
- * remove it from the neighborhood. If an association process is in
- * progress this function will block waiting for the nbmutex to become
- * free. The association process will thus be allowed to complete before it
- * is removed.
- */
-static
-void wlp_uwb_notifs_cb(void *_wlp, struct uwb_dev *uwb_dev,
-                      enum uwb_notifs event)
-{
-       struct wlp *wlp = _wlp;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_neighbor_e *neighbor, *next;
-       int result;
-       switch (event) {
-       case UWB_NOTIF_ONAIR:
-               result = wlp_eda_create_node(&wlp->eda,
-                                            uwb_dev->mac_addr.data,
-                                            &uwb_dev->dev_addr);
-               if (result < 0)
-                       dev_err(dev, "WLP: Unable to add new neighbor "
-                               "%02x:%02x to EDA cache.\n",
-                               uwb_dev->dev_addr.data[1],
-                               uwb_dev->dev_addr.data[0]);
-               break;
-       case UWB_NOTIF_OFFAIR:
-               wlp_eda_rm_node(&wlp->eda, &uwb_dev->dev_addr);
-               mutex_lock(&wlp->nbmutex);
-               list_for_each_entry_safe(neighbor, next, &wlp->neighbors, node) {
-                       if (neighbor->uwb_dev == uwb_dev)
-                               __wlp_neighbor_release(neighbor);
-               }
-               mutex_unlock(&wlp->nbmutex);
-               break;
-       default:
-               dev_err(dev, "don't know how to handle event %d from uwb\n",
-                               event);
-       }
-}
-
-static void wlp_channel_changed(struct uwb_pal *pal, int channel)
-{
-       struct wlp *wlp = container_of(pal, struct wlp, pal);
-
-       if (channel < 0)
-               netif_carrier_off(wlp->ndev);
-       else
-               netif_carrier_on(wlp->ndev);
-}
-
-int wlp_setup(struct wlp *wlp, struct uwb_rc *rc, struct net_device *ndev)
-{
-       int result;
-
-       BUG_ON(wlp->fill_device_info == NULL);
-       BUG_ON(wlp->xmit_frame == NULL);
-       BUG_ON(wlp->stop_queue == NULL);
-       BUG_ON(wlp->start_queue == NULL);
-
-       wlp->rc = rc;
-       wlp->ndev = ndev;
-       wlp_eda_init(&wlp->eda);/* Set up address cache */
-       wlp->uwb_notifs_handler.cb = wlp_uwb_notifs_cb;
-       wlp->uwb_notifs_handler.data = wlp;
-       uwb_notifs_register(rc, &wlp->uwb_notifs_handler);
-
-       uwb_pal_init(&wlp->pal);
-       wlp->pal.rc = rc;
-       wlp->pal.channel_changed = wlp_channel_changed;
-       result = uwb_pal_register(&wlp->pal);
-       if (result < 0)
-               uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
-
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_setup);
-
-void wlp_remove(struct wlp *wlp)
-{
-       wlp_neighbors_release(wlp);
-       uwb_pal_unregister(&wlp->pal);
-       uwb_notifs_deregister(wlp->rc, &wlp->uwb_notifs_handler);
-       wlp_eda_release(&wlp->eda);
-       mutex_lock(&wlp->mutex);
-       if (wlp->dev_info != NULL)
-               kfree(wlp->dev_info);
-       mutex_unlock(&wlp->mutex);
-       wlp->rc = NULL;
-}
-EXPORT_SYMBOL_GPL(wlp_remove);
-
-/**
- * wlp_reset_all - reset the WLP hardware
- * @wlp: the WLP device to reset.
- *
- * This schedules a full hardware reset of the WLP device.  The radio
- * controller and any other PALs will also be reset.
- */
-void wlp_reset_all(struct wlp *wlp)
-{
-       uwb_rc_reset_all(wlp->rc);
-}
-EXPORT_SYMBOL_GPL(wlp_reset_all);
diff --git a/drivers/uwb/wlp/wss-lc.c b/drivers/uwb/wlp/wss-lc.c
deleted file mode 100644 (file)
index 67872c8..0000000
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- *
- * Copyright (C) 2007 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Implementation of the WLP association protocol.
- *
- * FIXME: Docs
- *
- * A UWB network interface will configure a WSS through wlp_wss_setup() after
- * the interface has been assigned a MAC address, typically after
- * "ifconfig" has been called. When the interface goes down it should call
- * wlp_wss_remove().
- *
- * When the WSS is ready for use the user interacts via sysfs to create,
- * discover, and activate WSS.
- *
- * wlp_wss_enroll_activate()
- *
- * wlp_wss_create_activate()
- *     wlp_wss_set_wssid_hash()
- *             wlp_wss_comp_wssid_hash()
- *     wlp_wss_sel_bcast_addr()
- *     wlp_wss_sysfs_add()
- *
- * Called when no more references to WSS exist:
- *     wlp_wss_release()
- *             wlp_wss_reset()
- */
-#include <linux/etherdevice.h> /* for is_valid_ether_addr */
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/wlp.h>
-
-#include "wlp-internal.h"
-
-size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key)
-{
-       size_t result;
-
-       result = scnprintf(buf, bufsize,
-                         "%02x %02x %02x %02x %02x %02x "
-                         "%02x %02x %02x %02x %02x %02x "
-                         "%02x %02x %02x %02x",
-                         key[0], key[1], key[2], key[3],
-                         key[4], key[5], key[6], key[7],
-                         key[8], key[9], key[10], key[11],
-                         key[12], key[13], key[14], key[15]);
-       return result;
-}
-
-/**
- * Compute WSSID hash
- * WLP Draft 0.99 [7.2.1]
- *
- * The WSSID hash for a WSSID is the result of an octet-wise exclusive-OR
- * of all octets in the WSSID.
- */
-static
-u8 wlp_wss_comp_wssid_hash(struct wlp_uuid *wssid)
-{
-       return wssid->data[0]  ^ wssid->data[1]  ^ wssid->data[2]
-              ^ wssid->data[3]  ^ wssid->data[4]  ^ wssid->data[5]
-              ^ wssid->data[6]  ^ wssid->data[7]  ^ wssid->data[8]
-              ^ wssid->data[9]  ^ wssid->data[10] ^ wssid->data[11]
-              ^ wssid->data[12] ^ wssid->data[13] ^ wssid->data[14]
-              ^ wssid->data[15];
-}
-
-/**
- * Select a multicast EUI-48 for the WSS broadcast address.
- * WLP Draft 0.99 [7.2.1]
- *
- * Selected based on the WiMedia Alliance OUI, 00-13-88, within the WLP
- * range, [01-13-88-00-01-00, 01-13-88-00-01-FF] inclusive.
- *
- * This address is currently hardcoded.
- * FIXME?
- */
-static
-struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss)
-{
-       struct uwb_mac_addr bcast = {
-               .data = { 0x01, 0x13, 0x88, 0x00, 0x01, 0x00 }
-       };
-       return bcast;
-}
-
-/**
- * Clear the contents of the WSS structure - all except kobj, mutex, virtual
- *
- * We do not want to reinitialize - the internal kobj should not change as
- * it still points to the parent received during setup. The mutex should
- * remain also. We thus just reset values individually.
- * The virutal address assigned to WSS will remain the same for the
- * lifetime of the WSS. We only reset the fields that can change during its
- * lifetime.
- */
-void wlp_wss_reset(struct wlp_wss *wss)
-{
-       memset(&wss->wssid, 0, sizeof(wss->wssid));
-       wss->hash = 0;
-       memset(&wss->name[0], 0, sizeof(wss->name));
-       memset(&wss->bcast, 0, sizeof(wss->bcast));
-       wss->secure_status = WLP_WSS_UNSECURE;
-       memset(&wss->master_key[0], 0, sizeof(wss->master_key));
-       wss->tag = 0;
-       wss->state = WLP_WSS_STATE_NONE;
-}
-
-/**
- * Create sysfs infrastructure for WSS
- *
- * The WSS is configured to have the interface as parent (see wlp_wss_setup())
- * a new sysfs directory that includes wssid as its name is created in the
- * interface's sysfs directory. The group of files interacting with WSS are
- * created also.
- */
-static
-int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result;
-
-       result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str);
-       if (result < 0)
-               return result;
-       wss->kobj.ktype = &wss_ktype;
-       result = kobject_init_and_add(&wss->kobj,
-                       &wss_ktype, wss->kobj.parent, "wlp");
-       if (result < 0) {
-               dev_err(dev, "WLP: Cannot register WSS kobject.\n");
-               goto error_kobject_register;
-       }
-       result = sysfs_create_group(&wss->kobj, &wss_attr_group);
-       if (result < 0) {
-               dev_err(dev, "WLP: Cannot register WSS attributes: %d\n",
-                       result);
-               goto error_sysfs_create_group;
-       }
-       return 0;
-error_sysfs_create_group:
-
-       kobject_put(&wss->kobj); /* will free name if needed */
-       return result;
-error_kobject_register:
-       kfree(wss->kobj.name);
-       wss->kobj.name = NULL;
-       wss->kobj.ktype = NULL;
-       return result;
-}
-
-
-/**
- * Release WSS
- *
- * No more references exist to this WSS. We should undo everything that was
- * done in wlp_wss_create_activate() except removing the group. The group
- * is not removed because an object can be unregistered before the group is
- * created. We also undo any additional operations on the WSS after this
- * (addition of members).
- *
- * If memory was allocated for the kobject's name then it will
- * be freed by the kobject system during this time.
- *
- * The EDA cache is removed and reinitialized when the WSS is removed. We
- * thus loose knowledge of members of this WSS at that time and need not do
- * it here.
- */
-void wlp_wss_release(struct kobject *kobj)
-{
-       struct wlp_wss *wss = container_of(kobj, struct wlp_wss, kobj);
-
-       wlp_wss_reset(wss);
-}
-
-/**
- * Enroll into a WSS using provided neighbor as registrar
- *
- * First search the neighborhood information to learn which neighbor is
- * referred to, next proceed with enrollment.
- *
- * &wss->mutex is held
- */
-static
-int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid,
-                         struct uwb_dev_addr *dest)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_neighbor_e *neighbor;
-       int result = -ENXIO;
-       struct uwb_dev_addr *dev_addr;
-
-       mutex_lock(&wlp->nbmutex);
-       list_for_each_entry(neighbor, &wlp->neighbors, node) {
-               dev_addr = &neighbor->uwb_dev->dev_addr;
-               if (!memcmp(dest, dev_addr, sizeof(*dest))) {
-                       result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid);
-                       break;
-               }
-       }
-       if (result == -ENXIO)
-               dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n",
-                       dest->data[1], dest->data[0]);
-       mutex_unlock(&wlp->nbmutex);
-       return result;
-}
-
-/**
- * Enroll into a WSS previously discovered
- *
- * User provides WSSID of WSS, search for neighbor that has this WSS
- * activated and attempt to enroll.
- *
- * &wss->mutex is held
- */
-static
-int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_neighbor_e *neighbor;
-       struct wlp_wssid_e *wssid_e;
-       char buf[WLP_WSS_UUID_STRSIZE];
-       int result = -ENXIO;
-
-
-       mutex_lock(&wlp->nbmutex);
-       list_for_each_entry(neighbor, &wlp->neighbors, node) {
-               list_for_each_entry(wssid_e, &neighbor->wssid, node) {
-                       if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) {
-                               result = wlp_enroll_neighbor(wlp, neighbor,
-                                                            wss, wssid);
-                               if (result == 0) /* enrollment success */
-                                       goto out;
-                               break;
-                       }
-               }
-       }
-out:
-       if (result == -ENXIO) {
-               wlp_wss_uuid_print(buf, sizeof(buf), wssid);
-               dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf);
-       }
-       mutex_unlock(&wlp->nbmutex);
-       return result;
-}
-
-/**
- * Enroll into WSS with provided WSSID, registrar may be provided
- *
- * @wss: out WSS that will be enrolled
- * @wssid: wssid of neighboring WSS that we want to enroll in
- * @devaddr: registrar can be specified, will be broadcast (ff:ff) if any
- *           neighbor can be used as registrar.
- *
- * &wss->mutex is held
- */
-static
-int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid,
-                  struct uwb_dev_addr *devaddr)
-{
-       int result;
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       char buf[WLP_WSS_UUID_STRSIZE];
-       struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };
-
-       wlp_wss_uuid_print(buf, sizeof(buf), wssid);
-
-       if (wss->state != WLP_WSS_STATE_NONE) {
-               dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf);
-               result = -EEXIST;
-               goto error;
-       }
-       if (!memcmp(&bcast, devaddr, sizeof(bcast)))
-               result = wlp_wss_enroll_discovered(wss, wssid);
-       else
-               result = wlp_wss_enroll_target(wss, wssid, devaddr);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n",
-                       buf, result);
-               goto error;
-       }
-       dev_dbg(dev, "Successfully enrolled into WSS %s \n", buf);
-       result = wlp_wss_sysfs_add(wss, buf);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n");
-               wlp_wss_reset(wss);
-       }
-error:
-       return result;
-
-}
-
-/**
- * Activate given WSS
- *
- * Prior to activation a WSS must be enrolled. To activate a WSS a device
- * includes the WSS hash in the WLP IE in its beacon in each superframe.
- * WLP 0.99 [7.2.5].
- *
- * The WSS tag is also computed at this time. We only support one activated
- * WSS so we can use the hash as a tag - there will never be a conflict.
- *
- * We currently only support one activated WSS so only one WSS hash is
- * included in the WLP IE.
- */
-static
-int wlp_wss_activate(struct wlp_wss *wss)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct uwb_rc *uwb_rc = wlp->rc;
-       int result;
-       struct {
-               struct wlp_ie wlp_ie;
-               u8 hash; /* only include one hash */
-       } ie_data;
-
-       BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED);
-       wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid);
-       wss->tag = wss->hash;
-       memset(&ie_data, 0, sizeof(ie_data));
-       ie_data.wlp_ie.hdr.element_id = UWB_IE_WLP;
-       ie_data.wlp_ie.hdr.length = sizeof(ie_data) - sizeof(struct uwb_ie_hdr);
-       wlp_ie_set_hash_length(&ie_data.wlp_ie, sizeof(ie_data.hash));
-       ie_data.hash = wss->hash;
-       result = uwb_rc_ie_add(uwb_rc, &ie_data.wlp_ie.hdr,
-                              sizeof(ie_data));
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to add WLP IE to beacon. "
-                       "result = %d.\n", result);
-               goto error_wlp_ie;
-       }
-       wss->state = WLP_WSS_STATE_ACTIVE;
-       result = 0;
-error_wlp_ie:
-       return result;
-}
-
-/**
- * Enroll in and activate WSS identified by provided WSSID
- *
- * The neighborhood cache should contain a list of all neighbors and the
- * WSS they have activated. Based on that cache we search which neighbor we
- * can perform the association process with. The user also has option to
- * specify which neighbor it prefers as registrar.
- * Successful enrollment is followed by activation.
- * Successful activation will create the sysfs directory containing
- * specific information regarding this WSS.
- */
-int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
-                           struct uwb_dev_addr *devaddr)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-       char buf[WLP_WSS_UUID_STRSIZE];
-
-       mutex_lock(&wss->mutex);
-       result = wlp_wss_enroll(wss, wssid, devaddr);
-       if (result < 0) {
-               wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid);
-               dev_err(dev, "WLP: Enrollment into WSS %s failed.\n", buf);
-               goto error_enroll;
-       }
-       result = wlp_wss_activate(wss);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to activate WSS. Undoing enrollment "
-                       "result = %d \n", result);
-               /* Undo enrollment */
-               wlp_wss_reset(wss);
-               goto error_activate;
-       }
-error_activate:
-error_enroll:
-       mutex_unlock(&wss->mutex);
-       return result;
-}
-
-/**
- * Create, enroll, and activate a new WSS
- *
- * @wssid: new wssid provided by user
- * @name:  WSS name requested by used.
- * @sec_status: security status requested by user
- *
- * A user requested the creation of a new WSS. All operations are done
- * locally. The new WSS will be stored locally, the hash will be included
- * in the WLP IE, and the sysfs infrastructure for this WSS will be
- * created.
- */
-int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
-                           char *name, unsigned sec_status, unsigned accept)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-       char buf[WLP_WSS_UUID_STRSIZE];
-
-       result = wlp_wss_uuid_print(buf, sizeof(buf), wssid);
-
-       if (!mutex_trylock(&wss->mutex)) {
-               dev_err(dev, "WLP: WLP association session in progress.\n");
-               return -EBUSY;
-       }
-       if (wss->state != WLP_WSS_STATE_NONE) {
-               dev_err(dev, "WLP: WSS already exists. Not creating new.\n");
-               result = -EEXIST;
-               goto out;
-       }
-       if (wss->kobj.parent == NULL) {
-               dev_err(dev, "WLP: WSS parent not ready. Is network interface "
-                      "up?\n");
-               result = -ENXIO;
-               goto out;
-       }
-       if (sec_status == WLP_WSS_SECURE) {
-               dev_err(dev, "WLP: FIXME Creation of secure WSS not "
-                       "supported yet.\n");
-               result = -EINVAL;
-               goto out;
-       }
-       wss->wssid = *wssid;
-       memcpy(wss->name, name, sizeof(wss->name));
-       wss->bcast = wlp_wss_sel_bcast_addr(wss);
-       wss->secure_status = sec_status;
-       wss->accept_enroll = accept;
-       /*wss->virtual_addr is initialized in call to wlp_wss_setup*/
-       /* sysfs infrastructure */
-       result = wlp_wss_sysfs_add(wss, buf);
-       if (result < 0) {
-               dev_err(dev, "Cannot set up sysfs for WSS kobject.\n");
-               wlp_wss_reset(wss);
-               goto out;
-       } else
-               result = 0;
-       wss->state = WLP_WSS_STATE_ENROLLED;
-       result = wlp_wss_activate(wss);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to activate WSS. Undoing "
-                       "enrollment\n");
-               wlp_wss_reset(wss);
-               goto out;
-       }
-       result = 0;
-out:
-       mutex_unlock(&wss->mutex);
-       return result;
-}
-
-/**
- * Determine if neighbor has WSS activated
- *
- * @returns: 1 if neighbor has WSS activated, zero otherwise
- *
- * This can be done in two ways:
- * - send a C1 frame, parse C2/F0 response
- * - examine the WLP IE sent by the neighbor
- *
- * The WLP IE is not fully supported in hardware so we use the C1/C2 frame
- * exchange to determine if a WSS is activated. Using the WLP IE should be
- * faster and should be used when it becomes possible.
- */
-int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss,
-                     struct uwb_dev_addr *dev_addr)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       DECLARE_COMPLETION_ONSTACK(completion);
-       struct wlp_session session;
-       struct sk_buff  *skb;
-       struct wlp_frame_assoc *resp;
-       struct wlp_uuid wssid;
-
-       mutex_lock(&wlp->mutex);
-       /* Send C1 association frame */
-       result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1);
-       if (result < 0) {
-               dev_err(dev, "Unable to send C1 frame to neighbor "
-                       "%02x:%02x (%d)\n", dev_addr->data[1],
-                       dev_addr->data[0], result);
-               result = 0;
-               goto out;
-       }
-       /* Create session, wait for response */
-       session.exp_message = WLP_ASSOC_C2;
-       session.cb = wlp_session_cb;
-       session.cb_priv = &completion;
-       session.neighbor_addr = *dev_addr;
-       BUG_ON(wlp->session != NULL);
-       wlp->session = &session;
-       /* Wait for C2/F0 frame */
-       result = wait_for_completion_interruptible_timeout(&completion,
-                                                  WLP_PER_MSG_TIMEOUT * HZ);
-       if (result == 0) {
-               dev_err(dev, "Timeout while sending C1 to neighbor "
-                            "%02x:%02x.\n", dev_addr->data[1],
-                            dev_addr->data[0]);
-               goto out;
-       }
-       if (result < 0) {
-               dev_err(dev, "Unable to send C1 to neighbor %02x:%02x.\n",
-                       dev_addr->data[1], dev_addr->data[0]);
-               result = 0;
-               goto out;
-       }
-       /* Parse message in session->data: it will be either C2 or F0 */
-       skb = session.data;
-       resp = (void *) skb->data;
-       if (resp->type == WLP_ASSOC_F0) {
-               result = wlp_parse_f0(wlp, skb);
-               if (result < 0)
-                       dev_err(dev, "WLP:  unable to parse incoming F0 "
-                               "frame from neighbor %02x:%02x.\n",
-                               dev_addr->data[1], dev_addr->data[0]);
-               result = 0;
-               goto error_resp_parse;
-       }
-       /* WLP version and message type fields have already been parsed */
-       result = wlp_get_wssid(wlp, (void *)resp + sizeof(*resp), &wssid,
-                              skb->len - sizeof(*resp));
-       if (result < 0) {
-               dev_err(dev, "WLP: unable to obtain WSSID from C2 frame.\n");
-               result = 0;
-               goto error_resp_parse;
-       }
-       if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)))
-               result = 1;
-       else {
-               dev_err(dev, "WLP: Received a C2 frame without matching "
-                       "WSSID.\n");
-               result = 0;
-       }
-error_resp_parse:
-       kfree_skb(skb);
-out:
-       wlp->session = NULL;
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-
-/**
- * Activate connection with neighbor by updating EDA cache
- *
- * @wss:       local WSS to which neighbor wants to connect
- * @dev_addr:  neighbor's address
- * @wssid:     neighbor's WSSID - must be same as our WSS's WSSID
- * @tag:       neighbor's WSS tag used to identify frames transmitted by it
- * @virt_addr: neighbor's virtual EUI-48
- */
-static
-int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss,
-                               struct uwb_dev_addr *dev_addr,
-                               struct wlp_uuid *wssid, u8 *tag,
-                               struct uwb_mac_addr *virt_addr)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-
-       if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) {
-               /* Update EDA cache */
-               result = wlp_eda_update_node(&wlp->eda, dev_addr, wss,
-                                            (void *) virt_addr->data, *tag,
-                                            WLP_WSS_CONNECTED);
-               if (result < 0)
-                       dev_err(dev, "WLP: Unable to update EDA cache "
-                               "with new connected neighbor information.\n");
-       } else {
-               dev_err(dev, "WLP: Neighbor does not have matching WSSID.\n");
-               result = -EINVAL;
-       }
-       return result;
-}
-
-/**
- * Connect to WSS neighbor
- *
- * Use C3/C4 exchange to determine if neighbor has WSS activated and
- * retrieve the WSS tag and virtual EUI-48 of the neighbor.
- */
-static
-int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss,
-                            struct uwb_dev_addr *dev_addr)
-{
-       int result;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct wlp_uuid wssid;
-       u8 tag;
-       struct uwb_mac_addr virt_addr;
-       DECLARE_COMPLETION_ONSTACK(completion);
-       struct wlp_session session;
-       struct wlp_frame_assoc *resp;
-       struct sk_buff *skb;
-
-       mutex_lock(&wlp->mutex);
-       /* Send C3 association frame */
-       result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3);
-       if (result < 0) {
-               dev_err(dev, "Unable to send C3 frame to neighbor "
-                       "%02x:%02x (%d)\n", dev_addr->data[1],
-                       dev_addr->data[0], result);
-               goto out;
-       }
-       /* Create session, wait for response */
-       session.exp_message = WLP_ASSOC_C4;
-       session.cb = wlp_session_cb;
-       session.cb_priv = &completion;
-       session.neighbor_addr = *dev_addr;
-       BUG_ON(wlp->session != NULL);
-       wlp->session = &session;
-       /* Wait for C4/F0 frame */
-       result = wait_for_completion_interruptible_timeout(&completion,
-                                                  WLP_PER_MSG_TIMEOUT * HZ);
-       if (result == 0) {
-               dev_err(dev, "Timeout while sending C3 to neighbor "
-                            "%02x:%02x.\n", dev_addr->data[1],
-                            dev_addr->data[0]);
-               result = -ETIMEDOUT;
-               goto out;
-       }
-       if (result < 0) {
-               dev_err(dev, "Unable to send C3 to neighbor %02x:%02x.\n",
-                       dev_addr->data[1], dev_addr->data[0]);
-               goto out;
-       }
-       /* Parse message in session->data: it will be either C4 or F0 */
-       skb = session.data;
-       resp = (void *) skb->data;
-       if (resp->type == WLP_ASSOC_F0) {
-               result = wlp_parse_f0(wlp, skb);
-               if (result < 0)
-                       dev_err(dev, "WLP: unable to parse incoming F0 "
-                               "frame from neighbor %02x:%02x.\n",
-                               dev_addr->data[1], dev_addr->data[0]);
-               result = -EINVAL;
-               goto error_resp_parse;
-       }
-       result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to parse C4 frame from neighbor.\n");
-               goto error_resp_parse;
-       }
-       result = wlp_wss_activate_connection(wlp, wss, dev_addr, &wssid, &tag,
-                                            &virt_addr);
-       if (result < 0) {
-               dev_err(dev, "WLP: Unable to activate connection to "
-                       "neighbor %02x:%02x.\n", dev_addr->data[1],
-                       dev_addr->data[0]);
-               goto error_resp_parse;
-       }
-error_resp_parse:
-       kfree_skb(skb);
-out:
-       /* Record that we unsuccessfully tried to connect to this neighbor */
-       if (result < 0)
-               wlp_eda_update_node_state(&wlp->eda, dev_addr,
-                                         WLP_WSS_CONNECT_FAILED);
-       wlp->session = NULL;
-       mutex_unlock(&wlp->mutex);
-       return result;
-}
-
-/**
- * Connect to neighbor with common WSS, send pending frame
- *
- * This function is scheduled when a frame is destined to a neighbor with
- * which we do not have a connection. A copy of the EDA cache entry is
- * provided - not the actual cache entry (because it is protected by a
- * spinlock).
- *
- * First determine if neighbor has the same WSS activated, connect if it
- * does. The C3/C4 exchange is dual purpose to determine if neighbor has
- * WSS activated and proceed with the connection.
- *
- * The frame that triggered the connection setup is sent after connection
- * setup.
- *
- * network queue is stopped - we need to restart when done
- *
- */
-static
-void wlp_wss_connect_send(struct work_struct *ws)
-{
-       struct wlp_assoc_conn_ctx *conn_ctx = container_of(ws,
-                                                 struct wlp_assoc_conn_ctx,
-                                                 ws);
-       struct wlp *wlp = conn_ctx->wlp;
-       struct sk_buff *skb = conn_ctx->skb;
-       struct wlp_eda_node *eda_entry = &conn_ctx->eda_entry;
-       struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
-       struct wlp_wss *wss = &wlp->wss;
-       int result;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-
-       mutex_lock(&wss->mutex);
-       if (wss->state < WLP_WSS_STATE_ACTIVE) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Attempting to connect with "
-                               "WSS that is not active or connected.\n");
-               dev_kfree_skb(skb);
-               goto out;
-       }
-       /* Establish connection - send C3 rcv C4 */
-       result = wlp_wss_connect_neighbor(wlp, wss, dev_addr);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to establish connection "
-                               "with neighbor %02x:%02x.\n",
-                               dev_addr->data[1], dev_addr->data[0]);
-               dev_kfree_skb(skb);
-               goto out;
-       }
-       /* EDA entry changed, update the local copy being used */
-       result = wlp_copy_eda_node(&wlp->eda, dev_addr, eda_entry);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Cannot find EDA entry for "
-                               "neighbor %02x:%02x \n",
-                               dev_addr->data[1], dev_addr->data[0]);
-       }
-       result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to prepare frame header for "
-                               "transmission (neighbor %02x:%02x). \n",
-                               dev_addr->data[1], dev_addr->data[0]);
-               dev_kfree_skb(skb);
-               goto out;
-       }
-       BUG_ON(wlp->xmit_frame == NULL);
-       result = wlp->xmit_frame(wlp, skb, dev_addr);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to transmit frame: %d\n",
-                               result);
-               if (result == -ENXIO)
-                       dev_err(dev, "WLP: Is network interface up? \n");
-               /* We could try again ... */
-               dev_kfree_skb(skb);/*we need to free if tx fails */
-       }
-out:
-       kfree(conn_ctx);
-       BUG_ON(wlp->start_queue == NULL);
-       wlp->start_queue(wlp);
-       mutex_unlock(&wss->mutex);
-}
-
-/**
- * Add WLP header to outgoing skb
- *
- * @eda_entry: pointer to neighbor's entry in the EDA cache
- * @_skb:      skb containing data destined to the neighbor
- */
-int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry,
-                    void *_skb)
-{
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-       unsigned char *eth_addr = eda_entry->eth_addr;
-       struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
-       struct sk_buff *skb = _skb;
-       struct wlp_frame_std_abbrv_hdr *std_hdr;
-
-       if (eda_entry->state == WLP_WSS_CONNECTED) {
-               /* Add WLP header */
-               BUG_ON(skb_headroom(skb) < sizeof(*std_hdr));
-               std_hdr = (void *) __skb_push(skb, sizeof(*std_hdr));
-               std_hdr->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
-               std_hdr->hdr.type = WLP_FRAME_STANDARD;
-               std_hdr->tag = eda_entry->wss->tag;
-       } else {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Destination neighbor (Ethernet: "
-                               "%pM, Dev: %02x:%02x) is not connected.\n",
-                               eth_addr, dev_addr->data[1], dev_addr->data[0]);
-               result = -EINVAL;
-       }
-       return result;
-}
-
-
-/**
- * Prepare skb for neighbor: connect if not already and prep WLP header
- *
- * This function is called in interrupt context, but it needs to sleep. We
- * temporarily stop the net queue to establish the WLP connection.
- * Setup of the WLP connection and restart of queue is scheduled
- * on the default work queue.
- *
- * run with eda->lock held (spinlock)
- */
-int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry,
-                        void *_skb)
-{
-       int result = 0;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct sk_buff *skb = _skb;
-       struct wlp_assoc_conn_ctx *conn_ctx;
-
-       if (eda_entry->state == WLP_WSS_UNCONNECTED) {
-               /* We don't want any more packets while we set up connection */
-               BUG_ON(wlp->stop_queue == NULL);
-               wlp->stop_queue(wlp);
-               conn_ctx = kmalloc(sizeof(*conn_ctx), GFP_ATOMIC);
-               if (conn_ctx == NULL) {
-                       if (printk_ratelimit())
-                               dev_err(dev, "WLP: Unable to allocate memory "
-                                       "for connection handling.\n");
-                       result = -ENOMEM;
-                       goto out;
-               }
-               conn_ctx->wlp = wlp;
-               conn_ctx->skb = skb;
-               conn_ctx->eda_entry = *eda_entry;
-               INIT_WORK(&conn_ctx->ws, wlp_wss_connect_send);
-               schedule_work(&conn_ctx->ws);
-               result = 1;
-       } else if (eda_entry->state == WLP_WSS_CONNECT_FAILED) {
-               /* Previous connection attempts failed, don't retry - see
-                * conditions for connection in WLP 0.99 [7.6.2] */
-               if (printk_ratelimit())
-                       dev_err(dev, "Could not connect to neighbor "
-                        "previously. Not retrying. \n");
-               result = -ENONET;
-               goto out;
-       } else /* eda_entry->state == WLP_WSS_CONNECTED */
-               result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
-out:
-       return result;
-}
-
-/**
- * Emulate broadcast: copy skb, send copy to neighbor (connect if not already)
- *
- * We need to copy skbs in the case where we emulate broadcast through
- * unicast. We copy instead of clone because we are modifying the data of
- * the frame after copying ... clones share data so we cannot emulate
- * broadcast using clones.
- *
- * run with eda->lock held (spinlock)
- */
-int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry,
-                     void *_skb)
-{
-       int result = -ENOMEM;
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       struct sk_buff *skb = _skb;
-       struct sk_buff *copy;
-       struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
-
-       copy = skb_copy(skb, GFP_ATOMIC);
-       if (copy == NULL) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to copy skb for "
-                               "transmission.\n");
-               goto out;
-       }
-       result = wlp_wss_connect_prep(wlp, eda_entry, copy);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to connect/send skb "
-                               "to neighbor.\n");
-               dev_kfree_skb_irq(copy);
-               goto out;
-       } else if (result == 1)
-               /* Frame will be transmitted separately */
-               goto out;
-       BUG_ON(wlp->xmit_frame == NULL);
-       result = wlp->xmit_frame(wlp, copy, dev_addr);
-       if (result < 0) {
-               if (printk_ratelimit())
-                       dev_err(dev, "WLP: Unable to transmit frame: %d\n",
-                               result);
-               if ((result == -ENXIO) && printk_ratelimit())
-                       dev_err(dev, "WLP: Is network interface up? \n");
-               /* We could try again ... */
-               dev_kfree_skb_irq(copy);/*we need to free if tx fails */
-       }
-out:
-       return result;
-}
-
-
-/**
- * Setup WSS
- *
- * Should be called by network driver after the interface has been given a
- * MAC address.
- */
-int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-       struct device *dev = &wlp->rc->uwb_dev.dev;
-       int result = 0;
-
-       mutex_lock(&wss->mutex);
-       wss->kobj.parent = &net_dev->dev.kobj;
-       if (!is_valid_ether_addr(net_dev->dev_addr)) {
-               dev_err(dev, "WLP: Invalid MAC address. Cannot use for"
-                      "virtual.\n");
-               result = -EINVAL;
-               goto out;
-       }
-       memcpy(wss->virtual_addr.data, net_dev->dev_addr,
-              sizeof(wss->virtual_addr.data));
-out:
-       mutex_unlock(&wss->mutex);
-       return result;
-}
-EXPORT_SYMBOL_GPL(wlp_wss_setup);
-
-/**
- * Remove WSS
- *
- * Called by client that configured WSS through wlp_wss_setup(). This
- * function is called when client no longer needs WSS, eg. client shuts
- * down.
- *
- * We remove the WLP IE from the beacon before initiating local cleanup.
- */
-void wlp_wss_remove(struct wlp_wss *wss)
-{
-       struct wlp *wlp = container_of(wss, struct wlp, wss);
-
-       mutex_lock(&wss->mutex);
-       if (wss->state == WLP_WSS_STATE_ACTIVE)
-               uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP);
-       if (wss->state != WLP_WSS_STATE_NONE) {
-               sysfs_remove_group(&wss->kobj, &wss_attr_group);
-               kobject_put(&wss->kobj);
-       }
-       wss->kobj.parent = NULL;
-       memset(&wss->virtual_addr, 0, sizeof(wss->virtual_addr));
-       /* Cleanup EDA cache */
-       wlp_eda_release(&wlp->eda);
-       wlp_eda_init(&wlp->eda);
-       mutex_unlock(&wss->mutex);
-}
-EXPORT_SYMBOL_GPL(wlp_wss_remove);
index dc06ff1..596ef6b 100644 (file)
@@ -1919,6 +1919,9 @@ config FB_SH_MOBILE_HDMI
        tristate "SuperH Mobile HDMI controller support"
        depends on FB_SH_MOBILE_LCDC
        select FB_MODE_HELPERS
+       select SOUND
+       select SND
+       select SND_SOC
        ---help---
          Driver for the on-chip SH-Mobile HDMI controller.
 
index f8d69ad..5bf9123 100644 (file)
@@ -2970,7 +2970,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
        struct atyfb_par *par = info->par;
        struct device_node *dp;
        char prop[128];
-       int node, len, i, j, ret;
+       phandle node;
+       int len, i, j, ret;
        u32 mem, chip_id;
 
        /*
index 2fde08c..ef989d9 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
 
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
@@ -222,6 +224,58 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
        return ioread8(hdmi->base + reg);
 }
 
+/*
+ *     HDMI sound
+ */
+static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
+                                    unsigned int reg)
+{
+       struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
+
+       return hdmi_read(hdmi, reg);
+}
+
+static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
+                            unsigned int reg,
+                            unsigned int value)
+{
+       struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
+
+       hdmi_write(hdmi, value, reg);
+       return 0;
+}
+
+static struct snd_soc_dai_driver sh_hdmi_dai = {
+       .name = "sh_mobile_hdmi-hifi",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100  |
+                        SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200  |
+                        SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
+                        SNDRV_PCM_RATE_192000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+};
+
+static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
+{
+       dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
+       .probe          = sh_hdmi_snd_probe,
+       .read           = sh_hdmi_snd_read,
+       .write          = sh_hdmi_snd_write,
+};
+
+/*
+ *     HDMI video
+ */
+
 /* External video parameter settings */
 static void hdmi_external_video_param(struct sh_hdmi *hdmi)
 {
@@ -318,6 +372,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
  */
 static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
 {
+       u8 data;
+       struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
+
        /*
         * [7:4] L/R data swap control
         * [3:0] appropriate N[19:16]
@@ -335,7 +392,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
         * [6:5] set required down sampling rate if required
         * [4:3] set required audio source
         */
-       hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1);
+       switch (pdata->flags & HDMI_SND_SRC_MASK) {
+       default:
+               /* fall through */
+       case HDMI_SND_SRC_I2S:
+               data = 0x0 << 3;
+               break;
+       case HDMI_SND_SRC_SPDIF:
+               data = 0x1 << 3;
+               break;
+       case HDMI_SND_SRC_DSD:
+               data = 0x2 << 3;
+               break;
+       case HDMI_SND_SRC_HBR:
+               data = 0x3 << 3;
+               break;
+       }
+       hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
 
        /* [3:0] set sending channel number for channel status */
        hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
@@ -891,6 +964,11 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       ret =  snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
+       if (ret < 0)
+               goto esndreg;
+
        hdmi->dev = &pdev->dev;
 
        hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
@@ -976,6 +1054,8 @@ eclkenable:
 erate:
        clk_put(hdmi->hdmi_clk);
 egetclk:
+       snd_soc_unregister_codec(&pdev->dev);
+esndreg:
        kfree(hdmi);
 
        return ret;
@@ -988,6 +1068,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        int irq = platform_get_irq(pdev, 0);
 
+       snd_soc_unregister_codec(&pdev->dev);
+
        pdata->lcd_chan->board_cfg.display_on = NULL;
        pdata->lcd_chan->board_cfg.display_off = NULL;
        pdata->lcd_chan->board_cfg.board_data = NULL;
index d72075a..7a14192 100644 (file)
@@ -1243,8 +1243,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
                if (priv->ch[i].sglist)
                        vfree(priv->ch[i].sglist);
 
-               dma_free_coherent(&pdev->dev, info->fix.smem_len,
-                                 info->screen_base, priv->ch[i].dma_handle);
+               if (info->screen_base)
+                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
+                                         info->screen_base,
+                                         priv->ch[i].dma_handle);
                fb_dealloc_cmap(&info->cmap);
                framebuffer_release(info);
        }
index 0c9ce88..68bd234 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/xilinxfb.h>
 #include <linux/slab.h>
+
+#ifdef CONFIG_PPC_DCR
 #include <asm/dcr.h>
+#endif
 
 #define DRIVER_NAME            "xilinxfb"
 
@@ -123,10 +127,10 @@ struct xilinxfb_drvdata {
                                                registers */
        void __iomem    *regs;          /* virt. address of the control
                                                registers */
-
+#ifdef CONFIG_PPC_DCR
        dcr_host_t      dcr_host;
        unsigned int    dcr_len;
-
+#endif
        void            *fb_virt;       /* virt. address of the frame buffer */
        dma_addr_t      fb_phys;        /* phys. address of the frame buffer */
        int             fb_alloced;     /* Flag, was the fb memory alloced? */
@@ -152,9 +156,10 @@ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset,
 {
        if (drvdata->flags & PLB_ACCESS_FLAG)
                out_be32(drvdata->regs + (offset << 2), val);
+#ifdef CONFIG_PPC_DCR
        else
                dcr_write(drvdata->dcr_host, offset, val);
-
+#endif
 }
 
 static int
@@ -383,8 +388,11 @@ static int xilinxfb_release(struct device *dev)
        if (drvdata->flags & PLB_ACCESS_FLAG) {
                iounmap(drvdata->regs);
                release_mem_region(drvdata->regs_phys, 8);
-       } else
+       }
+#ifdef CONFIG_PPC_DCR
+       else
                dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
+#endif
 
        kfree(drvdata);
        dev_set_drvdata(dev, NULL);
@@ -404,7 +412,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
        u32 tft_access;
        struct xilinxfb_platform_data pdata;
        struct resource res;
-       int size, rc, start;
+       int size, rc;
        struct xilinxfb_drvdata *drvdata;
 
        /* Copy with the default pdata (not a ptr reference!) */
@@ -437,7 +445,10 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
                        dev_err(&op->dev, "invalid address\n");
                        goto err;
                }
-       } else {
+       }
+#ifdef CONFIG_PPC_DCR
+       else {
+               int start;
                res.start = 0;
                start = dcr_resource_start(op->dev.of_node, 0);
                drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0);
@@ -447,6 +458,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
                        goto err;
                }
        }
+#endif
 
        prop = of_get_property(op->dev.of_node, "phys-size", &size);
        if ((prop) && (size >= sizeof(u32)*2)) {
index 81e3d61..3dd4971 100644 (file)
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
-#include <linux/clk.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <plat/prcm.h>
 
@@ -61,8 +61,6 @@ struct omap_wdt_dev {
        void __iomem    *base;          /* physical */
        struct device   *dev;
        int             omap_wdt_users;
-       struct clk      *ick;
-       struct clk      *fck;
        struct resource *mem;
        struct miscdevice omap_wdt_miscdev;
 };
@@ -146,8 +144,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
        if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
                return -EBUSY;
 
-       clk_enable(wdev->ick);    /* Enable the interface clock */
-       clk_enable(wdev->fck);    /* Enable the functional clock */
+       pm_runtime_get_sync(wdev->dev);
 
        /* initialize prescaler */
        while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -177,8 +174,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
 
        omap_wdt_disable(wdev);
 
-       clk_disable(wdev->ick);
-       clk_disable(wdev->fck);
+       pm_runtime_put_sync(wdev->dev);
 #else
        printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
 #endif
@@ -293,19 +289,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
 
        wdev->omap_wdt_users = 0;
        wdev->mem = mem;
-
-       wdev->ick = clk_get(&pdev->dev, "ick");
-       if (IS_ERR(wdev->ick)) {
-               ret = PTR_ERR(wdev->ick);
-               wdev->ick = NULL;
-               goto err_clk;
-       }
-       wdev->fck = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(wdev->fck)) {
-               ret = PTR_ERR(wdev->fck);
-               wdev->fck = NULL;
-               goto err_clk;
-       }
+       wdev->dev = &pdev->dev;
 
        wdev->base = ioremap(res->start, resource_size(res));
        if (!wdev->base) {
@@ -315,8 +299,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, wdev);
 
-       clk_enable(wdev->ick);
-       clk_enable(wdev->fck);
+       pm_runtime_enable(wdev->dev);
+       pm_runtime_get_sync(wdev->dev);
 
        omap_wdt_disable(wdev);
        omap_wdt_adjust_timeout(timer_margin);
@@ -334,11 +318,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
                __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
                timer_margin);
 
-       /* autogate OCP interface clock */
-       __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG);
-
-       clk_disable(wdev->ick);
-       clk_disable(wdev->fck);
+       pm_runtime_put_sync(wdev->dev);
 
        omap_wdt_dev = pdev;
 
@@ -350,12 +330,6 @@ err_misc:
 
 err_ioremap:
        wdev->base = NULL;
-
-err_clk:
-       if (wdev->ick)
-               clk_put(wdev->ick);
-       if (wdev->fck)
-               clk_put(wdev->fck);
        kfree(wdev);
 
 err_kzalloc:
@@ -387,8 +361,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
        release_mem_region(res->start, resource_size(res));
        platform_set_drvdata(pdev, NULL);
 
-       clk_put(wdev->ick);
-       clk_put(wdev->fck);
        iounmap(wdev->base);
 
        kfree(wdev);
index a5bf577..9060f08 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -31,19 +32,23 @@ void coda_cache_enter(struct inode *inode, int mask)
 {
        struct coda_inode_info *cii = ITOC(inode);
 
+       spin_lock(&cii->c_lock);
        cii->c_cached_epoch = atomic_read(&permission_epoch);
        if (cii->c_uid != current_fsuid()) {
                cii->c_uid = current_fsuid();
                 cii->c_cached_perm = mask;
         } else
                 cii->c_cached_perm |= mask;
+       spin_unlock(&cii->c_lock);
 }
 
 /* remove cached acl from an inode */
 void coda_cache_clear_inode(struct inode *inode)
 {
        struct coda_inode_info *cii = ITOC(inode);
+       spin_lock(&cii->c_lock);
        cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
+       spin_unlock(&cii->c_lock);
 }
 
 /* remove all acl caches */
@@ -57,13 +62,15 @@ void coda_cache_clear_all(struct super_block *sb)
 int coda_cache_check(struct inode *inode, int mask)
 {
        struct coda_inode_info *cii = ITOC(inode);
-        int hit;
+       int hit;
        
-        hit = (mask & cii->c_cached_perm) == mask &&
-               cii->c_uid == current_fsuid() &&
-               cii->c_cached_epoch == atomic_read(&permission_epoch);
+       spin_lock(&cii->c_lock);
+       hit = (mask & cii->c_cached_perm) == mask &&
+           cii->c_uid == current_fsuid() &&
+           cii->c_cached_epoch == atomic_read(&permission_epoch);
+       spin_unlock(&cii->c_lock);
 
-        return hit;
+       return hit;
 }
 
 
index a7a7809..6022405 100644 (file)
@@ -45,13 +45,15 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
 static int coda_test_inode(struct inode *inode, void *data)
 {
        struct CodaFid *fid = (struct CodaFid *)data;
-       return coda_fideq(&(ITOC(inode)->c_fid), fid);
+       struct coda_inode_info *cii = ITOC(inode);
+       return coda_fideq(&cii->c_fid, fid);
 }
 
 static int coda_set_inode(struct inode *inode, void *data)
 {
        struct CodaFid *fid = (struct CodaFid *)data;
-       ITOC(inode)->c_fid = *fid;
+       struct coda_inode_info *cii = ITOC(inode);
+       cii->c_fid = *fid;
        return 0;
 }
 
@@ -71,6 +73,7 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
                cii = ITOC(inode);
                /* we still need to set i_ino for things like stat(2) */
                inode->i_ino = hash;
+               /* inode is locked and unique, no need to grab cii->c_lock */
                cii->c_mapcount = 0;
                unlock_new_inode(inode);
        }
@@ -107,14 +110,20 @@ int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_bloc
 }
 
 
+/* Although we treat Coda file identifiers as immutable, there is one
+ * special case for files created during a disconnection where they may
+ * not be globally unique. When an identifier collision is detected we
+ * first try to flush the cached inode from the kernel and finally
+ * resort to renaming/rehashing in-place. Userspace remembers both old
+ * and new values of the identifier to handle any in-flight upcalls.
+ * The real solution is to use globally unique UUIDs as identifiers, but
+ * retrofitting the existing userspace code for this is non-trivial. */
 void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
                      struct CodaFid *newfid)
 {
-       struct coda_inode_info *cii;
+       struct coda_inode_info *cii = ITOC(inode);
        unsigned long hash = coda_f2i(newfid);
        
-       cii = ITOC(inode);
-
        BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
 
        /* replace fid and rehash inode */
index ccd98b0..96fbeab 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 
@@ -116,15 +116,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
                goto exit;
        }
 
-       lock_kernel();
-
        error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
                             &type, &resfid);
        if (!error)
                error = coda_cnode_make(&inode, &resfid, dir->i_sb);
 
-       unlock_kernel();
-
        if (error && error != -ENOENT)
                return ERR_PTR(error);
 
@@ -140,28 +136,24 @@ exit:
 
 int coda_permission(struct inode *inode, int mask)
 {
-        int error = 0;
+       int error;
 
        mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  
        if (!mask)
-               return 0; 
+               return 0;
 
        if ((mask & MAY_EXEC) && !execute_ok(inode))
                return -EACCES;
 
-       lock_kernel();
-
        if (coda_cache_check(inode, mask))
-               goto out; 
+               return 0;
 
-        error = venus_access(inode->i_sb, coda_i2f(inode), mask);
+       error = venus_access(inode->i_sb, coda_i2f(inode), mask);
     
        if (!error)
                coda_cache_enter(inode, mask);
 
- out:
-       unlock_kernel();
        return error;
 }
 
@@ -200,41 +192,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
 /* creation routines: create, mknod, mkdir, link, symlink */
 static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
 {
-        int error=0;
+       int error;
        const char *name=de->d_name.name;
        int length=de->d_name.len;
        struct inode *inode;
        struct CodaFid newfid;
        struct coda_vattr attrs;
 
-       lock_kernel();
-
-       if (coda_isroot(dir) && coda_iscontrol(name, length)) {
-               unlock_kernel();
+       if (coda_isroot(dir) && coda_iscontrol(name, length))
                return -EPERM;
-       }
 
        error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
                                0, mode, &newfid, &attrs);
-
-        if ( error ) {
-               unlock_kernel();
-               d_drop(de);
-               return error;
-       }
+       if (error)
+               goto err_out;
 
        inode = coda_iget(dir->i_sb, &newfid, &attrs);
-       if ( IS_ERR(inode) ) {
-               unlock_kernel();
-               d_drop(de);
-               return PTR_ERR(inode);
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
+               goto err_out;
        }
 
        /* invalidate the directory cnode's attributes */
        coda_dir_update_mtime(dir);
-       unlock_kernel();
        d_instantiate(de, inode);
        return 0;
+err_out:
+       d_drop(de);
+       return error;
 }
 
 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
@@ -246,36 +231,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
        int error;
        struct CodaFid newfid;
 
-       lock_kernel();
-
-       if (coda_isroot(dir) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        attrs.va_mode = mode;
        error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
                               name, len, &newfid, &attrs);
-        
-        if ( error ) {
-               unlock_kernel();
-               d_drop(de);
-               return error;
-        }
+       if (error)
+               goto err_out;
          
        inode = coda_iget(dir->i_sb, &newfid, &attrs);
-       if ( IS_ERR(inode) ) {
-               unlock_kernel();
-               d_drop(de);
-               return PTR_ERR(inode);
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
+               goto err_out;
        }
 
        /* invalidate the directory cnode's attributes */
        coda_dir_inc_nlink(dir);
        coda_dir_update_mtime(dir);
-       unlock_kernel();
        d_instantiate(de, inode);
        return 0;
+err_out:
+       d_drop(de);
+       return error;
 }
 
 /* try to make de an entry in dir_inodde linked to source_de */ 
@@ -287,52 +265,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
        int len = de->d_name.len;
        int error;
 
-       lock_kernel();
-
-       if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        error = venus_link(dir_inode->i_sb, coda_i2f(inode),
                           coda_i2f(dir_inode), (const char *)name, len);
-
        if (error) {
                d_drop(de);
-               goto out;
+               return error;
        }
 
        coda_dir_update_mtime(dir_inode);
        atomic_inc(&inode->i_count);
        d_instantiate(de, inode);
        inc_nlink(inode);
-
-out:
-       unlock_kernel();
-       return(error);
+       return 0;
 }
 
 
 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
                        const char *symname)
 {
-        const char *name = de->d_name.name;
+       const char *name = de->d_name.name;
        int len = de->d_name.len;
        int symlen;
-       int error = 0;
-
-       lock_kernel();
+       int error;
 
-       if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        symlen = strlen(symname);
-       if ( symlen > CODA_MAXPATHLEN ) {
-               unlock_kernel();
+       if (symlen > CODA_MAXPATHLEN)
                return -ENAMETOOLONG;
-       }
 
        /*
         * This entry is now negative. Since we do not create
@@ -343,10 +307,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
                              symname, symlen);
 
        /* mtime is no good anymore */
-       if ( !error )
+       if (!error)
                coda_dir_update_mtime(dir_inode);
 
-       unlock_kernel();
        return error;
 }
 
@@ -357,17 +320,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
        const char *name = de->d_name.name;
        int len = de->d_name.len;
 
-       lock_kernel();
-
        error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
-       if ( error ) {
-               unlock_kernel();
+       if (error)
                return error;
-       }
 
        coda_dir_update_mtime(dir);
        drop_nlink(de->d_inode);
-       unlock_kernel();
        return 0;
 }
 
@@ -377,8 +335,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
        int len = de->d_name.len;
        int error;
 
-       lock_kernel();
-
        error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
        if (!error) {
                /* VFS may delete the child */
@@ -389,7 +345,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
                coda_dir_drop_nlink(dir);
                coda_dir_update_mtime(dir);
        }
-       unlock_kernel();
        return error;
 }
 
@@ -403,15 +358,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
        int new_length = new_dentry->d_name.len;
        int error;
 
-       lock_kernel();
-
        error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
                             coda_i2f(new_dir), old_length, new_length,
                             (const char *) old_name, (const char *)new_name);
-
-       if ( !error ) {
-               if ( new_dentry->d_inode ) {
-                       if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
+       if (!error) {
+               if (new_dentry->d_inode) {
+                       if (S_ISDIR(new_dentry->d_inode->i_mode)) {
                                coda_dir_drop_nlink(old_dir);
                                coda_dir_inc_nlink(new_dir);
                        }
@@ -423,8 +375,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
                        coda_flag_inode(new_dir, C_VATTR);
                }
        }
-       unlock_kernel();
-
        return error;
 }
 
@@ -594,10 +544,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
        struct inode *inode = de->d_inode;
        struct coda_inode_info *cii;
 
-       if (!inode)
-               return 1;
-       lock_kernel();
-       if (coda_isroot(inode))
+       if (!inode || coda_isroot(inode))
                goto out;
        if (is_bad_inode(inode))
                goto bad;
@@ -617,13 +564,12 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
                goto out;
 
        /* clear the flags. */
+       spin_lock(&cii->c_lock);
        cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
-
+       spin_unlock(&cii->c_lock);
 bad:
-       unlock_kernel();
        return 0;
 out:
-       unlock_kernel();
        return 1;
 }
 
@@ -656,20 +602,19 @@ static int coda_dentry_delete(struct dentry * dentry)
 int coda_revalidate_inode(struct dentry *dentry)
 {
        struct coda_vattr attr;
-       int error = 0;
+       int error;
        int old_mode;
        ino_t old_ino;
        struct inode *inode = dentry->d_inode;
        struct coda_inode_info *cii = ITOC(inode);
 
-       lock_kernel();
-       if ( !cii->c_flags )
-               goto ok;
+       if (!cii->c_flags)
+               return 0;
 
        if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
                error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
-               if ( error )
-                       goto return_bad;
+               if (error)
+                       return -EIO;
 
                /* this inode may be lost if:
                   - it's ino changed 
@@ -688,17 +633,13 @@ int coda_revalidate_inode(struct dentry *dentry)
                /* the following can happen when a local fid is replaced 
                   with a global one, here we lose and declare the inode bad */
                if (inode->i_ino != old_ino)
-                       goto return_bad;
+                       return -EIO;
                
                coda_flag_inode_children(inode, C_FLUSH);
+
+               spin_lock(&cii->c_lock);
                cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
+               spin_unlock(&cii->c_lock);
        }
-
-ok:
-       unlock_kernel();
        return 0;
-
-return_bad:
-       unlock_kernel();
-       return -EIO;
 }
index ad3cd2a..c8b50ba 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/cred.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -109,19 +109,24 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
 
        coda_inode = coda_file->f_path.dentry->d_inode;
        host_inode = host_file->f_path.dentry->d_inode;
+
+       cii = ITOC(coda_inode);
+       spin_lock(&cii->c_lock);
        coda_file->f_mapping = host_file->f_mapping;
        if (coda_inode->i_mapping == &coda_inode->i_data)
                coda_inode->i_mapping = host_inode->i_mapping;
 
        /* only allow additional mmaps as long as userspace isn't changing
         * the container file on us! */
-       else if (coda_inode->i_mapping != host_inode->i_mapping)
+       else if (coda_inode->i_mapping != host_inode->i_mapping) {
+               spin_unlock(&cii->c_lock);
                return -EBUSY;
+       }
 
        /* keep track of how often the coda_inode/host_file has been mmapped */
-       cii = ITOC(coda_inode);
        cii->c_mapcount++;
        cfi->cfi_mapcount++;
+       spin_unlock(&cii->c_lock);
 
        return host_file->f_op->mmap(host_file, vma);
 }
@@ -138,8 +143,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
        if (!cfi)
                return -ENOMEM;
 
-       lock_kernel();
-
        error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
                           &host_file);
        if (!host_file)
@@ -147,7 +150,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
 
        if (error) {
                kfree(cfi);
-               unlock_kernel();
                return error;
        }
 
@@ -159,8 +161,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
 
        BUG_ON(coda_file->private_data != NULL);
        coda_file->private_data = cfi;
-
-       unlock_kernel();
        return 0;
 }
 
@@ -171,9 +171,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
        struct coda_file_info *cfi;
        struct coda_inode_info *cii;
        struct inode *host_inode;
-       int err = 0;
-
-       lock_kernel();
+       int err;
 
        cfi = CODA_FTOC(coda_file);
        BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -185,18 +183,18 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
        cii = ITOC(coda_inode);
 
        /* did we mmap this file? */
+       spin_lock(&cii->c_lock);
        if (coda_inode->i_mapping == &host_inode->i_data) {
                cii->c_mapcount -= cfi->cfi_mapcount;
                if (!cii->c_mapcount)
                        coda_inode->i_mapping = &coda_inode->i_data;
        }
+       spin_unlock(&cii->c_lock);
 
        fput(cfi->cfi_container);
        kfree(coda_file->private_data);
        coda_file->private_data = NULL;
 
-       unlock_kernel();
-
        /* VFS fput ignores the return value from file_operations->release, so
         * there is no use returning an error here */
        return 0;
@@ -207,7 +205,7 @@ int coda_fsync(struct file *coda_file, int datasync)
        struct file *host_file;
        struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
        struct coda_file_info *cfi;
-       int err = 0;
+       int err;
 
        if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
              S_ISLNK(coda_inode->i_mode)))
@@ -218,11 +216,8 @@ int coda_fsync(struct file *coda_file, int datasync)
        host_file = cfi->cfi_container;
 
        err = vfs_fsync(host_file, datasync);
-       if ( !err && !datasync ) {
-               lock_kernel();
+       if (!err && !datasync)
                err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
-               unlock_kernel();
-       }
 
        return err;
 }
index bfe8179..7993b96 100644 (file)
@@ -15,7 +15,8 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/file.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
@@ -51,6 +52,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
        ei->c_flags = 0;
        ei->c_uid = 0;
        ei->c_cached_perm = 0;
+       spin_lock_init(&ei->c_lock);
        return &ei->vfs_inode;
 }
 
@@ -143,13 +145,11 @@ static int get_device_index(struct coda_mount_data *data)
 static int coda_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *root = NULL;
-       struct venus_comm *vc = NULL;
+       struct venus_comm *vc;
        struct CodaFid fid;
        int error;
        int idx;
 
-       lock_kernel();
-
        idx = get_device_index((struct coda_mount_data *) data);
 
        /* Ignore errors in data, for backward compatibility */
@@ -159,23 +159,26 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
 
        vc = &coda_comms[idx];
+       mutex_lock(&vc->vc_mutex);
+
        if (!vc->vc_inuse) {
                printk("coda_read_super: No pseudo device\n");
-               unlock_kernel();
-               return -EINVAL;
+               error = -EINVAL;
+               goto unlock_out;
        }
 
-        if ( vc->vc_sb ) {
+       if (vc->vc_sb) {
                printk("coda_read_super: Device already mounted\n");
-               unlock_kernel();
-               return -EBUSY;
+               error = -EBUSY;
+               goto unlock_out;
        }
 
        error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
        if (error)
-               goto bdi_err;
+               goto unlock_out;
 
        vc->vc_sb = sb;
+       mutex_unlock(&vc->vc_mutex);
 
        sb->s_fs_info = vc;
        sb->s_flags |= MS_NOATIME;
@@ -204,28 +207,33 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        printk("coda_read_super: rootinode is %ld dev %s\n", 
               root->i_ino, root->i_sb->s_id);
        sb->s_root = d_alloc_root(root);
-       if (!sb->s_root)
+       if (!sb->s_root) {
+               error = -EINVAL;
                goto error;
-       unlock_kernel();
+       }
        return 0;
 
- error:
-       bdi_destroy(&vc->bdi);
- bdi_err:
+error:
        if (root)
                iput(root);
-       if (vc)
-               vc->vc_sb = NULL;
 
-       unlock_kernel();
-       return -EINVAL;
+       mutex_lock(&vc->vc_mutex);
+       bdi_destroy(&vc->bdi);
+       vc->vc_sb = NULL;
+       sb->s_fs_info = NULL;
+unlock_out:
+       mutex_unlock(&vc->vc_mutex);
+       return error;
 }
 
 static void coda_put_super(struct super_block *sb)
 {
-       bdi_destroy(&coda_vcp(sb)->bdi);
-       coda_vcp(sb)->vc_sb = NULL;
+       struct venus_comm *vcp = coda_vcp(sb);
+       mutex_lock(&vcp->vc_mutex);
+       bdi_destroy(&vcp->bdi);
+       vcp->vc_sb = NULL;
        sb->s_fs_info = NULL;
+       mutex_unlock(&vcp->vc_mutex);
 
        printk("Coda: Bye bye.\n");
 }
@@ -251,8 +259,6 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
        struct coda_vattr vattr;
        int error;
 
-       lock_kernel();
-       
        memset(&vattr, 0, sizeof(vattr)); 
 
        inode->i_ctime = CURRENT_TIME_SEC;
@@ -262,13 +268,10 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
        /* Venus is responsible for truncating the container-file!!! */
        error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
 
-       if ( !error ) {
+       if (!error) {
                coda_vattr_to_iattr(inode, &vattr); 
                coda_cache_clear_inode(inode);
        }
-
-       unlock_kernel();
-
        return error;
 }
 
@@ -282,12 +285,8 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        int error;
        
-       lock_kernel();
-
        error = venus_statfs(dentry, buf);
 
-       unlock_kernel();
-
        if (error) {
                /* fake something like AFS does */
                buf->f_blocks = 9000000;
index 028a9a0..2fd89b5 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/coda_fs_i.h>
 #include <linux/coda_psdev.h>
 
-#include <linux/smp_lock.h>
-
 /* pioctl ops */
 static int coda_ioctl_permission(struct inode *inode, int mask);
 static long coda_pioctl(struct file *filp, unsigned int cmd,
@@ -58,13 +56,9 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
        struct inode *target_inode = NULL;
        struct coda_inode_info *cnp;
 
-       lock_kernel();
-
        /* get the Pioctl data arguments from user space */
-       if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) {
-               error = -EINVAL;
-               goto out;
-       }
+       if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
+               return -EINVAL;
 
        /*
         * Look up the pathname. Note that the pathname is in
@@ -76,13 +70,12 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
                error = user_lpath(data.path, &path);
 
        if (error)
-               goto out;
-       else
-               target_inode = path.dentry->d_inode;
+               return error;
+
+       target_inode = path.dentry->d_inode;
 
        /* return if it is not a Coda inode */
        if (target_inode->i_sb != inode->i_sb) {
-               path_put(&path);
                error = -EINVAL;
                goto out;
        }
@@ -91,10 +84,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
        cnp = ITOC(target_inode);
 
        error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
-
-       path_put(&path);
-
 out:
-       unlock_kernel();
+       path_put(&path);
        return error;
 }
index fdc2f3e..62647a8 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -67,8 +67,10 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
        unsigned int mask = POLLOUT | POLLWRNORM;
 
        poll_wait(file, &vcp->vc_waitq, wait);
+       mutex_lock(&vcp->vc_mutex);
        if (!list_empty(&vcp->vc_pending))
                 mask |= POLLIN | POLLRDNORM;
+       mutex_unlock(&vcp->vc_mutex);
 
        return mask;
 }
@@ -108,16 +110,9 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                return -EFAULT;
 
         if (DOWNCALL(hdr.opcode)) {
-               struct super_block *sb = NULL;
-                union outputArgs *dcbuf;
+               union outputArgs *dcbuf;
                int size = sizeof(*dcbuf);
 
-               sb = vcp->vc_sb;
-               if ( !sb ) {
-                        count = nbytes;
-                        goto out;
-               }
-
                if  ( nbytes < sizeof(struct coda_out_hdr) ) {
                        printk("coda_downcall opc %d uniq %d, not enough!\n",
                               hdr.opcode, hdr.unique);
@@ -137,9 +132,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                }
 
                /* what downcall errors does Venus handle ? */
-               lock_kernel();
-               error = coda_downcall(hdr.opcode, dcbuf, sb);
-               unlock_kernel();
+               error = coda_downcall(vcp, hdr.opcode, dcbuf);
 
                CODA_FREE(dcbuf, nbytes);
                if (error) {
@@ -152,7 +145,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
        }
         
        /* Look for the message on the processing queue. */
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
        list_for_each(lh, &vcp->vc_processing) {
                tmp = list_entry(lh, struct upc_req , uc_chain);
                if (tmp->uc_unique == hdr.unique) {
@@ -161,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                        break;
                }
        }
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
 
        if (!req) {
                printk("psdev_write: msg (%d, %d) not found\n", 
@@ -216,7 +209,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        if (nbytes == 0)
                return 0;
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        add_wait_queue(&vcp->vc_waitq, &wait);
        set_current_state(TASK_INTERRUPTIBLE);
@@ -230,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
                        retval = -ERESTARTSYS;
                        break;
                }
+               mutex_unlock(&vcp->vc_mutex);
                schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
 
        set_current_state(TASK_RUNNING);
@@ -263,7 +258,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
        kfree(req);
 out:
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return (count ? count : retval);
 }
 
@@ -276,10 +271,10 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
        if (idx < 0 || idx >= MAX_CODADEVS)
                return -ENODEV;
 
-       lock_kernel();
-
        err = -EBUSY;
        vcp = &coda_comms[idx];
+       mutex_lock(&vcp->vc_mutex);
+
        if (!vcp->vc_inuse) {
                vcp->vc_inuse++;
 
@@ -293,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
                err = 0;
        }
 
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return err;
 }
 
@@ -308,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
                return -1;
        }
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        /* Wakeup clients so they can return. */
        list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
@@ -333,7 +328,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
 
        file->private_data = NULL;
        vcp->vc_inuse--;
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return 0;
 }
 
@@ -362,9 +357,11 @@ static int init_coda_psdev(void)
                err = PTR_ERR(coda_psdev_class);
                goto out_chrdev;
        }               
-       for (i = 0; i < MAX_CODADEVS; i++)
+       for (i = 0; i < MAX_CODADEVS; i++) {
+               mutex_init(&(&coda_comms[i])->vc_mutex);
                device_create(coda_psdev_class, NULL,
                              MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
+       }
        coda_sysctl_init();
        goto out;
 
index 4513b72..af78f00 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -29,11 +28,9 @@ static int coda_symlink_filler(struct file *file, struct page *page)
        unsigned int len = PAGE_SIZE;
        char *p = kmap(page);
 
-       lock_kernel();
        cii = ITOC(inode);
 
        error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
-       unlock_kernel();
        if (error)
                goto fail;
        SetPageUptodate(page);
index b8893ab..c3563ca 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
@@ -606,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old)
                                 (r)->uc_opcode != CODA_RELEASE) || \
                                (r)->uc_flags & CODA_REQ_READ))
 
-static inline void coda_waitfor_upcall(struct upc_req *req)
+static inline void coda_waitfor_upcall(struct venus_comm *vcp,
+                                      struct upc_req *req)
 {
        DECLARE_WAITQUEUE(wait, current);
        unsigned long timeout = jiffies + coda_timeout * HZ;
@@ -639,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
                        break;
                }
 
+               mutex_unlock(&vcp->vc_mutex);
                if (blocked)
                        schedule_timeout(HZ);
                else
                        schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
        if (blocked)
                coda_unblock_signals(&old);
@@ -667,18 +671,23 @@ static int coda_upcall(struct venus_comm *vcp,
 {
        union outputArgs *out;
        union inputArgs *sig_inputArgs;
-       struct upc_req *req, *sig_req;
-       int error = 0;
+       struct upc_req *req = NULL, *sig_req;
+       int error;
+
+       mutex_lock(&vcp->vc_mutex);
 
        if (!vcp->vc_inuse) {
                printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
-               return -ENXIO;
+               error = -ENXIO;
+               goto exit;
        }
 
        /* Format the request message. */
        req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
-       if (!req)
-               return -ENOMEM;
+       if (!req) {
+               error = -ENOMEM;
+               goto exit;
+       }
 
        req->uc_data = (void *)buffer;
        req->uc_flags = 0;
@@ -705,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp,
         * ENODEV.  */
 
        /* Go to sleep.  Wake up on signals only after the timeout. */
-       coda_waitfor_upcall(req);
+       coda_waitfor_upcall(vcp, req);
 
        /* Op went through, interrupt or not... */
        if (req->uc_flags & CODA_REQ_WRITE) {
@@ -759,6 +768,7 @@ static int coda_upcall(struct venus_comm *vcp,
 
 exit:
        kfree(req);
+       mutex_unlock(&vcp->vc_mutex);
        return error;
 }
 
@@ -796,21 +806,24 @@ exit:
  *
  * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
 
-int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
+int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
 {
        struct inode *inode = NULL;
-       struct CodaFid *fid, *newfid;
+       struct CodaFid *fid = NULL, *newfid;
+       struct super_block *sb;
 
        /* Handle invalidation requests. */
-       if ( !sb || !sb->s_root)
-               return 0;
+       mutex_lock(&vcp->vc_mutex);
+       sb = vcp->vc_sb;
+       if (!sb || !sb->s_root)
+               goto unlock_out;
 
        switch (opcode) {
        case CODA_FLUSH:
                coda_cache_clear_all(sb);
                shrink_dcache_sb(sb);
                if (sb->s_root->d_inode)
-                   coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
+                       coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
                break;
 
        case CODA_PURGEUSER:
@@ -819,45 +832,53 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 
        case CODA_ZAPDIR:
                fid = &out->coda_zapdir.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
-                       coda_flag_inode(inode, C_VATTR);
-               }
                break;
 
        case CODA_ZAPFILE:
                fid = &out->coda_zapfile.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_flag_inode(inode, C_VATTR);
                break;
 
        case CODA_PURGEFID:
                fid = &out->coda_purgefid.CodaFid;
+               break;
+
+       case CODA_REPLACE:
+               fid = &out->coda_replace.OldFid;
+               break;
+       }
+       if (fid)
                inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
 
-                       /* catch the dentries later if some are still busy */
-                       coda_flag_inode(inode, C_PURGE);
-                       d_prune_aliases(inode);
+unlock_out:
+       mutex_unlock(&vcp->vc_mutex);
 
-               }
+       if (!inode)
+               return 0;
+
+       switch (opcode) {
+       case CODA_ZAPDIR:
+               coda_flag_inode_children(inode, C_PURGE);
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_ZAPFILE:
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_PURGEFID:
+               coda_flag_inode_children(inode, C_PURGE);
+
+               /* catch the dentries later if some are still busy */
+               coda_flag_inode(inode, C_PURGE);
+               d_prune_aliases(inode);
                break;
 
        case CODA_REPLACE:
-               fid = &out->coda_replace.OldFid;
                newfid = &out->coda_replace.NewFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_replace_fid(inode, fid, newfid);
+               coda_replace_fid(inode, fid, newfid);
                break;
        }
-
-       if (inode)
-               iput(inode);
-
+       iput(inode);
        return 0;
 }
 
index d91e9d8..dcc941d 100644 (file)
@@ -420,7 +420,7 @@ int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de,
        err = exofs_write_begin(NULL, page->mapping, pos, len,
                                AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
        if (err)
-               EXOFS_ERR("exofs_set_link: exofs_write_begin FAILD => %d\n",
+               EXOFS_ERR("exofs_set_link: exofs_write_begin FAILED => %d\n",
                          err);
 
        de->inode_no = cpu_to_le64(inode->i_ino);
@@ -556,7 +556,7 @@ int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page)
        err = exofs_write_begin(NULL, page->mapping, pos, to - from, 0,
                                                        &page, NULL);
        if (err)
-               EXOFS_ERR("exofs_delete_entry: exofs_write_begin FAILD => %d\n",
+               EXOFS_ERR("exofs_delete_entry: exofs_write_begin FAILED => %d\n",
                          err);
        if (pde)
                pde->rec_len = cpu_to_le16(to - from);
index 4460275..4268542 100644 (file)
@@ -185,7 +185,7 @@ static void update_write_page(struct page *page, int ret)
 /* Called at the end of reads, to optionally unlock pages and update their
  * status.
  */
-static int __readpages_done(struct page_collect *pcol, bool do_unlock)
+static int __readpages_done(struct page_collect *pcol)
 {
        int i;
        u64 resid;
@@ -221,7 +221,7 @@ static int __readpages_done(struct page_collect *pcol, bool do_unlock)
                          page_stat ? "bad_bytes" : "good_bytes");
 
                ret = update_read_page(page, page_stat);
-               if (do_unlock)
+               if (!pcol->read_4_write)
                        unlock_page(page);
                length += PAGE_SIZE;
        }
@@ -236,7 +236,7 @@ static void readpages_done(struct exofs_io_state *ios, void *p)
 {
        struct page_collect *pcol = p;
 
-       __readpages_done(pcol, true);
+       __readpages_done(pcol);
        atomic_dec(&pcol->sbi->s_curr_pending);
        kfree(pcol);
 }
@@ -257,7 +257,7 @@ static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw)
        }
 }
 
-static int read_exec(struct page_collect *pcol, bool is_sync)
+static int read_exec(struct page_collect *pcol)
 {
        struct exofs_i_info *oi = exofs_i(pcol->inode);
        struct exofs_io_state *ios = pcol->ios;
@@ -267,17 +267,14 @@ static int read_exec(struct page_collect *pcol, bool is_sync)
        if (!pcol->pages)
                return 0;
 
-       /* see comment in _readpage() about sync reads */
-       WARN_ON(is_sync && (pcol->nr_pages != 1));
-
        ios->pages = pcol->pages;
        ios->nr_pages = pcol->nr_pages;
        ios->length = pcol->length;
        ios->offset = pcol->pg_first << PAGE_CACHE_SHIFT;
 
-       if (is_sync) {
+       if (pcol->read_4_write) {
                exofs_oi_read(oi, pcol->ios);
-               return __readpages_done(pcol, false);
+               return __readpages_done(pcol);
        }
 
        pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL);
@@ -303,7 +300,7 @@ static int read_exec(struct page_collect *pcol, bool is_sync)
        return 0;
 
 err:
-       if (!is_sync)
+       if (!pcol->read_4_write)
                _unlock_pcol_pages(pcol, ret, READ);
 
        pcol_free(pcol);
@@ -356,7 +353,7 @@ static int readpage_strip(void *data, struct page *page)
                EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page,"
                             " splitting\n", inode->i_ino, page->index);
 
-               return read_exec(pcol, false);
+               return read_exec(pcol);
        }
 
 try_again:
@@ -366,7 +363,7 @@ try_again:
        } else if (unlikely((pcol->pg_first + pcol->nr_pages) !=
                   page->index)) {
                /* Discontinuity detected, split the request */
-               ret = read_exec(pcol, false);
+               ret = read_exec(pcol);
                if (unlikely(ret))
                        goto fail;
                goto try_again;
@@ -391,7 +388,7 @@ try_again:
                          page, len, pcol->nr_pages, pcol->length);
 
                /* split the request, and start again with current page */
-               ret = read_exec(pcol, false);
+               ret = read_exec(pcol);
                if (unlikely(ret))
                        goto fail;
 
@@ -420,27 +417,24 @@ static int exofs_readpages(struct file *file, struct address_space *mapping,
                return ret;
        }
 
-       return read_exec(&pcol, false);
+       return read_exec(&pcol);
 }
 
-static int _readpage(struct page *page, bool is_sync)
+static int _readpage(struct page *page, bool read_4_write)
 {
        struct page_collect pcol;
        int ret;
 
        _pcol_init(&pcol, 1, page->mapping->host);
 
-       /* readpage_strip might call read_exec(,is_sync==false) at several
-        * places but not if we have a single page.
-        */
-       pcol.read_4_write = is_sync;
+       pcol.read_4_write = read_4_write;
        ret = readpage_strip(&pcol, page);
        if (ret) {
                EXOFS_ERR("_readpage => %d\n", ret);
                return ret;
        }
 
-       return read_exec(&pcol, is_sync);
+       return read_exec(&pcol);
 }
 
 /*
@@ -1036,6 +1030,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
                memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data));
        }
 
+       inode->i_mapping->backing_dev_info = sb->s_bdi;
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &exofs_file_inode_operations;
                inode->i_fop = &exofs_file_operations;
@@ -1072,8 +1067,10 @@ bad_inode:
 int __exofs_wait_obj_created(struct exofs_i_info *oi)
 {
        if (!obj_created(oi)) {
+               EXOFS_DBGMSG("!obj_created\n");
                BUG_ON(!obj_2bcreated(oi));
                wait_event(oi->i_wq, obj_created(oi));
+               EXOFS_DBGMSG("wait_event done\n");
        }
        return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0;
 }
@@ -1107,7 +1104,6 @@ static void create_done(struct exofs_io_state *ios, void *p)
 
        set_obj_created(oi);
 
-       atomic_dec(&inode->i_count);
        wake_up(&oi->i_wq);
 }
 
@@ -1135,6 +1131,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
 
        sbi = sb->s_fs_info;
 
+       inode->i_mapping->backing_dev_info = sb->s_bdi;
        sb->s_dirt = 1;
        inode_init_owner(inode, dir, mode);
        inode->i_ino = sbi->s_nextid++;
@@ -1157,17 +1154,11 @@ struct inode *exofs_new_inode(struct inode *dir, int mode)
        ios->obj.id = exofs_oi_objno(oi);
        exofs_make_credential(oi->i_cred, &ios->obj);
 
-       /* increment the refcount so that the inode will still be around when we
-        * reach the callback
-        */
-       atomic_inc(&inode->i_count);
-
        ios->done = create_done;
        ios->private = inode;
        ios->cred = oi->i_cred;
        ret = exofs_sbi_create(ios);
        if (ret) {
-               atomic_dec(&inode->i_count);
                exofs_put_io_state(ios);
                return ERR_PTR(ret);
        }
@@ -1257,12 +1248,7 @@ static int exofs_update_inode(struct inode *inode, int do_sync)
        ios->out_attr_len = 1;
        ios->out_attr = &attr;
 
-       if (!obj_created(oi)) {
-               EXOFS_DBGMSG("!obj_created\n");
-               BUG_ON(!obj_2bcreated(oi));
-               wait_event(oi->i_wq, obj_created(oi));
-               EXOFS_DBGMSG("wait_event done\n");
-       }
+       wait_obj_created(oi);
 
        if (!do_sync) {
                args->sbi = sbi;
@@ -1325,12 +1311,12 @@ void exofs_evict_inode(struct inode *inode)
        inode->i_size = 0;
        end_writeback(inode);
 
-       /* if we are deleting an obj that hasn't been created yet, wait */
-       if (!obj_created(oi)) {
-               BUG_ON(!obj_2bcreated(oi));
-               wait_event(oi->i_wq, obj_created(oi));
-               /* ignore the error attempt a remove anyway */
-       }
+       /* if we are deleting an obj that hasn't been created yet, wait.
+        * This also makes sure that create_done cannot be called with an
+        * already evicted inode.
+        */
+       wait_obj_created(oi);
+       /* ignore the error, attempt a remove anyway */
 
        /* Now Remove the OSD objects */
        ret = exofs_get_io_state(&sbi->layout, &ios);
index 64fd427..d5bb868 100644 (file)
@@ -42,6 +42,7 @@ struct nlm_wait {
 };
 
 static LIST_HEAD(nlm_blocked);
+static DEFINE_SPINLOCK(nlm_blocked_lock);
 
 /**
  * nlmclnt_init - Set up per-NFS mount point lockd data structures
@@ -97,7 +98,10 @@ struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *
                block->b_lock = fl;
                init_waitqueue_head(&block->b_wait);
                block->b_status = nlm_lck_blocked;
+
+               spin_lock(&nlm_blocked_lock);
                list_add(&block->b_list, &nlm_blocked);
+               spin_unlock(&nlm_blocked_lock);
        }
        return block;
 }
@@ -106,7 +110,9 @@ void nlmclnt_finish_block(struct nlm_wait *block)
 {
        if (block == NULL)
                return;
+       spin_lock(&nlm_blocked_lock);
        list_del(&block->b_list);
+       spin_unlock(&nlm_blocked_lock);
        kfree(block);
 }
 
@@ -154,6 +160,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
         * Look up blocked request based on arguments. 
         * Warning: must not use cookie to match it!
         */
+       spin_lock(&nlm_blocked_lock);
        list_for_each_entry(block, &nlm_blocked, b_list) {
                struct file_lock *fl_blocked = block->b_lock;
 
@@ -178,6 +185,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
                wake_up(&block->b_wait);
                res = nlm_granted;
        }
+       spin_unlock(&nlm_blocked_lock);
        return res;
 }
 
@@ -216,10 +224,6 @@ reclaimer(void *ptr)
        allow_signal(SIGKILL);
 
        down_write(&host->h_rwsem);
-
-       /* This one ensures that our parent doesn't terminate while the
-        * reclaim is in progress */
-       lock_kernel();
        lockd_up();     /* note: this cannot fail as lockd is already running */
 
        dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
@@ -260,16 +264,17 @@ restart:
        dprintk("NLM: done reclaiming locks for host %s\n", host->h_name);
 
        /* Now, wake up all processes that sleep on a blocked lock */
+       spin_lock(&nlm_blocked_lock);
        list_for_each_entry(block, &nlm_blocked, b_list) {
                if (block->b_host == host) {
                        block->b_status = nlm_lck_denied_grace_period;
                        wake_up(&block->b_wait);
                }
        }
+       spin_unlock(&nlm_blocked_lock);
 
        /* Release host handle after use */
        nlm_release_host(host);
        lockd_down();
-       unlock_kernel();
        return 0;
 }
index 7932c39..47ea1e1 100644 (file)
@@ -166,7 +166,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
 
-       lock_kernel();
        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
                if (fl->fl_type != F_UNLCK) {
                        call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
@@ -177,10 +176,8 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
                status = nlmclnt_test(call, fl);
        else
                status = -EINVAL;
-
        fl->fl_ops->fl_release_private(fl);
        fl->fl_ops = NULL;
-       unlock_kernel();
 
        dprintk("lockd: clnt proc returns %d\n", status);
        return status;
@@ -226,9 +223,7 @@ void nlm_release_call(struct nlm_rqst *call)
 
 static void nlmclnt_rpc_release(void *data)
 {
-       lock_kernel();
        nlm_release_call(data);
-       unlock_kernel();
 }
 
 static int nlm_wait_on_grace(wait_queue_head_t *queue)
@@ -448,14 +443,18 @@ out:
 
 static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
+       spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state;
        new->fl_u.nfs_fl.owner = nlm_get_lockowner(fl->fl_u.nfs_fl.owner);
        list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted);
+       spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 }
 
 static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
+       spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        list_del(&fl->fl_u.nfs_fl.list);
+       spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
 }
 
@@ -721,9 +720,7 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 die:
        return;
  retry_rebind:
-       lock_kernel();
        nlm_rebind_host(req->a_host);
-       unlock_kernel();
  retry_unlock:
        rpc_restart_call(task);
 }
@@ -801,9 +798,7 @@ retry_cancel:
        /* Don't ever retry more than 3 times */
        if (req->a_retries++ >= NLMCLNT_MAX_RETRIES)
                goto die;
-       lock_kernel();
        nlm_rebind_host(req->a_host);
-       unlock_kernel();
        rpc_restart_call(task);
        rpc_delay(task, 30 * HZ);
 }
index b950415..5c55c26 100644 (file)
@@ -118,3 +118,14 @@ config NFS_USE_KERNEL_DNS
        select DNS_RESOLVER
        select KEYS
        default y
+
+config NFS_USE_NEW_IDMAPPER
+       bool "Use the new idmapper upcall routine"
+       depends on NFS_V4 && KEYS
+       help
+         Say Y here if you want NFS to use the new idmapper upcall functions.
+         You will need /sbin/request-key (usually provided by the keyutils
+         package).  For details, read
+         <file:Documentation/filesystems/nfs/idmapper.txt>.
+
+         If you are unsure, say N.
index e734072..a882785 100644 (file)
@@ -635,7 +635,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
  */
 static void nfs_destroy_server(struct nfs_server *server)
 {
-       if (!(server->flags & NFS_MOUNT_NONLM))
+       if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) ||
+                       !(server->flags & NFS_MOUNT_LOCAL_FCNTL))
                nlmclnt_done(server->nlm_host);
 }
 
@@ -657,7 +658,8 @@ static int nfs_start_lockd(struct nfs_server *server)
 
        if (nlm_init.nfs_version > 3)
                return 0;
-       if (server->flags & NFS_MOUNT_NONLM)
+       if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) &&
+                       (server->flags & NFS_MOUNT_LOCAL_FCNTL))
                return 0;
 
        switch (clp->cl_proto) {
@@ -901,8 +903,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
        server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
        server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
-       if (server->dtsize > PAGE_CACHE_SIZE)
-               server->dtsize = PAGE_CACHE_SIZE;
+       if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES)
+               server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES;
        if (server->dtsize > server->rsize)
                server->dtsize = server->rsize;
 
@@ -913,6 +915,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
 
        server->maxfilesize = fsinfo->maxfilesize;
 
+       server->time_delta = fsinfo->time_delta;
+
        /* We're airborne Set socket buffersize */
        rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 }
@@ -1356,8 +1360,9 @@ static int nfs4_init_server(struct nfs_server *server,
 
        /* Initialise the client representation from the mount data */
        server->flags = data->flags;
-       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|
-               NFS_CAP_POSIX_LOCK;
+       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+       if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+                       server->caps |= NFS_CAP_READDIRPLUS;
        server->options = data->options;
 
        /* Get a client record */
index e257172..257e405 100644 (file)
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
-#include "nfs4_fs.h"
 #include "delegation.h"
 #include "iostat.h"
 #include "internal.h"
+#include "fscache.h"
 
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -55,6 +56,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
+static int nfs_readdir_clear_array(struct page*, gfp_t);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -80,6 +82,10 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
+const struct address_space_operations nfs_dir_addr_space_ops = {
+       .releasepage = nfs_readdir_clear_array,
+};
+
 #ifdef CONFIG_NFS_V3
 const struct inode_operations nfs3_dir_inode_operations = {
        .create         = nfs_create,
@@ -104,8 +110,9 @@ const struct inode_operations nfs3_dir_inode_operations = {
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
 const struct inode_operations nfs4_dir_inode_operations = {
-       .create         = nfs_create,
+       .create         = nfs_open_create,
        .lookup         = nfs_atomic_lookup,
        .link           = nfs_link,
        .unlink         = nfs_unlink,
@@ -150,51 +157,197 @@ nfs_opendir(struct inode *inode, struct file *filp)
        return res;
 }
 
-typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
+struct nfs_cache_array_entry {
+       u64 cookie;
+       u64 ino;
+       struct qstr string;
+};
+
+struct nfs_cache_array {
+       unsigned int size;
+       int eof_index;
+       u64 last_cookie;
+       struct nfs_cache_array_entry array[0];
+};
+
+#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
+
+typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 typedef struct {
        struct file     *file;
        struct page     *page;
        unsigned long   page_index;
-       __be32          *ptr;
        u64             *dir_cookie;
        loff_t          current_index;
-       struct nfs_entry *entry;
        decode_dirent_t decode;
-       int             plus;
+
        unsigned long   timestamp;
        unsigned long   gencount;
-       int             timestamp_valid;
+       unsigned int    cache_entry_index;
+       unsigned int    plus:1;
+       unsigned int    eof:1;
 } nfs_readdir_descriptor_t;
 
-/* Now we cache directories properly, by stuffing the dirent
- * data directly in the page cache.
- *
- * Inode invalidation due to refresh etc. takes care of
- * _everything_, no sloppy entry flushing logic, no extraneous
- * copying, network direct to page cache, the way it was meant
- * to be.
- *
- * NOTE: Dirent information verification is done always by the
- *      page-in of the RPC reply, nowhere else, this simplies
- *      things substantially.
+/*
+ * The caller is responsible for calling nfs_readdir_release_array(page)
  */
 static
-int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
+{
+       if (page == NULL)
+               return ERR_PTR(-EIO);
+       return (struct nfs_cache_array *)kmap(page);
+}
+
+static
+void nfs_readdir_release_array(struct page *page)
+{
+       kunmap(page);
+}
+
+/*
+ * we are freeing strings created by nfs_add_to_readdir_array()
+ */
+static
+int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+{
+       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       int i;
+       for (i = 0; i < array->size; i++)
+               kfree(array->array[i].string.name);
+       nfs_readdir_release_array(page);
+       return 0;
+}
+
+/*
+ * the caller is responsible for freeing qstr.name
+ * when called by nfs_readdir_add_to_array, the strings will be freed in
+ * nfs_clear_readdir_array()
+ */
+static
+int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
+{
+       string->len = len;
+       string->name = kmemdup(name, len, GFP_KERNEL);
+       if (string->name == NULL)
+               return -ENOMEM;
+       string->hash = full_name_hash(name, len);
+       return 0;
+}
+
+static
+int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
+{
+       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array_entry *cache_entry;
+       int ret;
+
+       if (IS_ERR(array))
+               return PTR_ERR(array);
+       ret = -EIO;
+       if (array->size >= MAX_READDIR_ARRAY)
+               goto out;
+
+       cache_entry = &array->array[array->size];
+       cache_entry->cookie = entry->prev_cookie;
+       cache_entry->ino = entry->ino;
+       ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
+       if (ret)
+               goto out;
+       array->last_cookie = entry->cookie;
+       if (entry->eof == 1)
+               array->eof_index = array->size;
+       array->size++;
+out:
+       nfs_readdir_release_array(page);
+       return ret;
+}
+
+static
+int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+       loff_t diff = desc->file->f_pos - desc->current_index;
+       unsigned int index;
+
+       if (diff < 0)
+               goto out_eof;
+       if (diff >= array->size) {
+               if (array->eof_index > 0)
+                       goto out_eof;
+               desc->current_index += array->size;
+               return -EAGAIN;
+       }
+
+       index = (unsigned int)diff;
+       *desc->dir_cookie = array->array[index].cookie;
+       desc->cache_entry_index = index;
+       if (index == array->eof_index)
+               desc->eof = 1;
+       return 0;
+out_eof:
+       desc->eof = 1;
+       return -EBADCOOKIE;
+}
+
+static
+int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+       int i;
+       int status = -EAGAIN;
+
+       for (i = 0; i < array->size; i++) {
+               if (i == array->eof_index) {
+                       desc->eof = 1;
+                       status = -EBADCOOKIE;
+               }
+               if (array->array[i].cookie == *desc->dir_cookie) {
+                       desc->cache_entry_index = i;
+                       status = 0;
+                       break;
+               }
+       }
+
+       return status;
+}
+
+static
+int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
+{
+       struct nfs_cache_array *array;
+       int status = -EBADCOOKIE;
+
+       if (desc->dir_cookie == NULL)
+               goto out;
+
+       array = nfs_readdir_get_array(desc->page);
+       if (IS_ERR(array)) {
+               status = PTR_ERR(array);
+               goto out;
+       }
+
+       if (*desc->dir_cookie == 0)
+               status = nfs_readdir_search_for_pos(array, desc);
+       else
+               status = nfs_readdir_search_for_cookie(array, desc);
+
+       nfs_readdir_release_array(desc->page);
+out:
+       return status;
+}
+
+/* Fill a page with xdr information before transferring to the cache page */
+static
+int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc,
+                       struct nfs_entry *entry, struct file *file, struct inode *inode)
 {
-       struct file     *file = desc->file;
-       struct inode    *inode = file->f_path.dentry->d_inode;
        struct rpc_cred *cred = nfs_file_cred(file);
        unsigned long   timestamp, gencount;
        int             error;
 
-       dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
-                       __func__, (long long)desc->entry->cookie,
-                       page->index);
-
  again:
        timestamp = jiffies;
        gencount = nfs_inc_attr_generation_counter();
-       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
+       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages,
                                          NFS_SERVER(inode)->dtsize, desc->plus);
        if (error < 0) {
                /* We requested READDIRPLUS, but the server doesn't grok it */
@@ -208,190 +361,292 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
        }
        desc->timestamp = timestamp;
        desc->gencount = gencount;
-       desc->timestamp_valid = 1;
-       SetPageUptodate(page);
-       /* Ensure consistent page alignment of the data.
-        * Note: assumes we have exclusive access to this mapping either
-        *       through inode->i_mutex or some other mechanism.
-        */
-       if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
-               /* Should never happen */
-               nfs_zap_mapping(inode, inode->i_mapping);
-       }
-       unlock_page(page);
-       return 0;
- error:
-       unlock_page(page);
-       return -EIO;
+error:
+       return error;
 }
 
-static inline
-int dir_decode(nfs_readdir_descriptor_t *desc)
+/* Fill in an entry based on the xdr code stored in desc->page */
+static
+int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
 {
-       __be32  *p = desc->ptr;
-       p = desc->decode(p, desc->entry, desc->plus);
+       __be32 *p = desc->decode(stream, entry, NFS_SERVER(desc->file->f_path.dentry->d_inode), desc->plus);
        if (IS_ERR(p))
                return PTR_ERR(p);
-       desc->ptr = p;
-       if (desc->timestamp_valid) {
-               desc->entry->fattr->time_start = desc->timestamp;
-               desc->entry->fattr->gencount = desc->gencount;
-       } else
-               desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
+
+       entry->fattr->time_start = desc->timestamp;
+       entry->fattr->gencount = desc->gencount;
        return 0;
 }
 
-static inline
-void dir_page_release(nfs_readdir_descriptor_t *desc)
+static
+int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
 {
-       kunmap(desc->page);
-       page_cache_release(desc->page);
-       desc->page = NULL;
-       desc->ptr = NULL;
+       struct nfs_inode *node;
+       if (dentry->d_inode == NULL)
+               goto different;
+       node = NFS_I(dentry->d_inode);
+       if (node->fh.size != entry->fh->size)
+               goto different;
+       if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
+               goto different;
+       return 1;
+different:
+       return 0;
 }
 
-/*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the next entry with cookie '*desc->dir_cookie'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
- */
-static inline
-int find_dirent(nfs_readdir_descriptor_t *desc)
+static
+void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
 {
-       struct nfs_entry *entry = desc->entry;
-       int             loop_count = 0,
-                       status;
+       struct qstr filename = {
+               .len = entry->len,
+               .name = entry->name,
+       };
+       struct dentry *dentry;
+       struct dentry *alias;
+       struct inode *dir = parent->d_inode;
+       struct inode *inode;
 
-       while((status = dir_decode(desc)) == 0) {
-               dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
-                               __func__, (unsigned long long)entry->cookie);
-               if (entry->prev_cookie == *desc->dir_cookie)
-                       break;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
+       if (filename.name[0] == '.') {
+               if (filename.len == 1)
+                       return;
+               if (filename.len == 2 && filename.name[1] == '.')
+                       return;
+       }
+       filename.hash = full_name_hash(filename.name, filename.len);
+
+       dentry = d_lookup(parent, &filename);
+       if (dentry != NULL) {
+               if (nfs_same_file(dentry, entry)) {
+                       nfs_refresh_inode(dentry->d_inode, entry->fattr);
+                       goto out;
+               } else {
+                       d_drop(dentry);
+                       dput(dentry);
                }
        }
-       return status;
+
+       dentry = d_alloc(parent, &filename);
+       if (dentry == NULL)
+               return;
+
+       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+       inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
+       if (IS_ERR(inode))
+               goto out;
+
+       alias = d_materialise_unique(dentry, inode);
+       if (IS_ERR(alias))
+               goto out;
+       else if (alias) {
+               nfs_set_verifier(alias, nfs_save_change_attribute(dir));
+               dput(alias);
+       } else
+               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+
+out:
+       dput(dentry);
+}
+
+/* Perform conversion from xdr to cache array */
+static
+void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
+                               void *xdr_page, struct page *page, unsigned int buflen)
+{
+       struct xdr_stream stream;
+       struct xdr_buf buf;
+       __be32 *ptr = xdr_page;
+       int status;
+       struct nfs_cache_array *array;
+
+       buf.head->iov_base = xdr_page;
+       buf.head->iov_len = buflen;
+       buf.tail->iov_len = 0;
+       buf.page_base = 0;
+       buf.page_len = 0;
+       buf.buflen = buf.head->iov_len;
+       buf.len = buf.head->iov_len;
+
+       xdr_init_decode(&stream, &buf, ptr);
+
+
+       do {
+               status = xdr_decode(desc, entry, &stream);
+               if (status != 0)
+                       break;
+
+               if (nfs_readdir_add_to_array(entry, page) == -1)
+                       break;
+               if (desc->plus == 1)
+                       nfs_prime_dcache(desc->file->f_path.dentry, entry);
+       } while (!entry->eof);
+
+       if (status == -EBADCOOKIE && entry->eof) {
+               array = nfs_readdir_get_array(page);
+               array->eof_index = array->size - 1;
+               status = 0;
+               nfs_readdir_release_array(page);
+       }
+}
+
+static
+void nfs_readdir_free_pagearray(struct page **pages, unsigned int npages)
+{
+       unsigned int i;
+       for (i = 0; i < npages; i++)
+               put_page(pages[i]);
+}
+
+static
+void nfs_readdir_free_large_page(void *ptr, struct page **pages,
+               unsigned int npages)
+{
+       vm_unmap_ram(ptr, npages);
+       nfs_readdir_free_pagearray(pages, npages);
 }
 
 /*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the entry at offset 'desc->file->f_pos'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
+ * nfs_readdir_large_page will allocate pages that must be freed with a call
+ * to nfs_readdir_free_large_page
  */
-static inline
-int find_dirent_index(nfs_readdir_descriptor_t *desc)
+static
+void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
 {
-       struct nfs_entry *entry = desc->entry;
-       int             loop_count = 0,
-                       status;
+       void *ptr;
+       unsigned int i;
+
+       for (i = 0; i < npages; i++) {
+               struct page *page = alloc_page(GFP_KERNEL);
+               if (page == NULL)
+                       goto out_freepages;
+               pages[i] = page;
+       }
 
-       for(;;) {
-               status = dir_decode(desc);
-               if (status)
-                       break;
+       ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
+       if (!IS_ERR_OR_NULL(ptr))
+               return ptr;
+out_freepages:
+       nfs_readdir_free_pagearray(pages, i);
+       return NULL;
+}
+
+static
+int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
+{
+       struct page *pages[NFS_MAX_READDIR_PAGES];
+       void *pages_ptr = NULL;
+       struct nfs_entry entry;
+       struct file     *file = desc->file;
+       struct nfs_cache_array *array;
+       int status = 0;
+       unsigned int array_size = ARRAY_SIZE(pages);
+
+       entry.prev_cookie = 0;
+       entry.cookie = *desc->dir_cookie;
+       entry.eof = 0;
+       entry.fh = nfs_alloc_fhandle();
+       entry.fattr = nfs_alloc_fattr();
+       if (entry.fh == NULL || entry.fattr == NULL)
+               goto out;
 
-               dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n",
-                               (unsigned long long)entry->cookie, desc->current_index);
+       array = nfs_readdir_get_array(page);
+       memset(array, 0, sizeof(struct nfs_cache_array));
+       array->eof_index = -1;
 
-               if (desc->file->f_pos == desc->current_index) {
-                       *desc->dir_cookie = entry->cookie;
+       pages_ptr = nfs_readdir_large_page(pages, array_size);
+       if (!pages_ptr)
+               goto out_release_array;
+       do {
+               status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);
+
+               if (status < 0)
                        break;
-               }
-               desc->current_index++;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
-       }
+               nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE);
+       } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY);
+
+       nfs_readdir_free_large_page(pages_ptr, pages, array_size);
+out_release_array:
+       nfs_readdir_release_array(page);
+out:
+       nfs_free_fattr(entry.fattr);
+       nfs_free_fhandle(entry.fh);
        return status;
 }
 
 /*
- * Find the given page, and call find_dirent() or find_dirent_index in
- * order to try to return the next entry.
+ * Now we cache directories properly, by converting xdr information
+ * to an array that can be used for lookups later.  This results in
+ * fewer cache pages, since we can store more information on each page.
+ * We only need to convert from xdr once so future lookups are much simpler
  */
-static inline
-int find_dirent_page(nfs_readdir_descriptor_t *desc)
+static
+int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 {
        struct inode    *inode = desc->file->f_path.dentry->d_inode;
-       struct page     *page;
-       int             status;
 
-       dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n",
-                       __func__, desc->page_index,
-                       (long long) *desc->dir_cookie);
+       if (nfs_readdir_xdr_to_array(desc, page, inode) < 0)
+               goto error;
+       SetPageUptodate(page);
 
-       /* If we find the page in the page_cache, we cannot be sure
-        * how fresh the data is, so we will ignore readdir_plus attributes.
-        */
-       desc->timestamp_valid = 0;
-       page = read_cache_page(inode->i_mapping, desc->page_index,
-                              (filler_t *)nfs_readdir_filler, desc);
-       if (IS_ERR(page)) {
-               status = PTR_ERR(page);
-               goto out;
+       if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
+               /* Should never happen */
+               nfs_zap_mapping(inode, inode->i_mapping);
        }
+       unlock_page(page);
+       return 0;
+ error:
+       unlock_page(page);
+       return -EIO;
+}
 
-       /* NOTE: Someone else may have changed the READDIRPLUS flag */
-       desc->page = page;
-       desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
-       if (*desc->dir_cookie != 0)
-               status = find_dirent(desc);
-       else
-               status = find_dirent_index(desc);
-       if (status < 0)
-               dir_page_release(desc);
- out:
-       dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status);
-       return status;
+static
+void cache_page_release(nfs_readdir_descriptor_t *desc)
+{
+       page_cache_release(desc->page);
+       desc->page = NULL;
+}
+
+static
+struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
+{
+       struct page *page;
+       page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
+                       desc->page_index, (filler_t *)nfs_readdir_filler, desc);
+       if (IS_ERR(page))
+               desc->eof = 1;
+       return page;
 }
 
 /*
- * Recurse through the page cache pages, and return a
- * filled nfs_entry structure of the next directory entry if possible.
- *
- * The target for the search is '*desc->dir_cookie' if non-0,
- * 'desc->file->f_pos' otherwise
+ * Returns 0 if desc->dir_cookie was found on page desc->page_index
  */
+static
+int find_cache_page(nfs_readdir_descriptor_t *desc)
+{
+       int res;
+
+       desc->page = get_cache_page(desc);
+       if (IS_ERR(desc->page))
+               return PTR_ERR(desc->page);
+
+       res = nfs_readdir_search_array(desc);
+       if (res == 0)
+               return 0;
+       cache_page_release(desc);
+       return res;
+}
+
+/* Search for desc->dir_cookie from the beginning of the page cache */
 static inline
 int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
-       int             loop_count = 0;
-       int             res;
-
-       /* Always search-by-index from the beginning of the cache */
-       if (*desc->dir_cookie == 0) {
-               dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
-                               (long long)desc->file->f_pos);
-               desc->page_index = 0;
-               desc->entry->cookie = desc->entry->prev_cookie = 0;
-               desc->entry->eof = 0;
-               desc->current_index = 0;
-       } else
-               dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
-                               (unsigned long long)*desc->dir_cookie);
+       int res = -EAGAIN;
 
-       for (;;) {
-               res = find_dirent_page(desc);
+       while (1) {
+               res = find_cache_page(desc);
                if (res != -EAGAIN)
                        break;
-               /* Align to beginning of next page */
-               desc->page_index ++;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
+               desc->page_index++;
        }
-
-       dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res);
        return res;
 }
 
@@ -400,8 +655,6 @@ static inline unsigned int dt_type(struct inode *inode)
        return (inode->i_mode >> 12) & 15;
 }
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc);
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -410,49 +663,36 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                   filldir_t filldir)
 {
        struct file     *file = desc->file;
-       struct nfs_entry *entry = desc->entry;
-       struct dentry   *dentry = NULL;
-       u64             fileid;
-       int             loop_count = 0,
-                       res;
-
-       dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
-                       (unsigned long long)entry->cookie);
-
-       for(;;) {
-               unsigned d_type = DT_UNKNOWN;
-               /* Note: entry->prev_cookie contains the cookie for
-                *       retrieving the current dirent on the server */
-               fileid = entry->ino;
-
-               /* Get a dentry if we have one */
-               if (dentry != NULL)
-                       dput(dentry);
-               dentry = nfs_readdir_lookup(desc);
+       int i = 0;
+       int res = 0;
+       struct nfs_cache_array *array = NULL;
+       unsigned int d_type = DT_UNKNOWN;
+       struct dentry *dentry = NULL;
 
-               /* Use readdirplus info */
-               if (dentry != NULL && dentry->d_inode != NULL) {
-                       d_type = dt_type(dentry->d_inode);
-                       fileid = NFS_FILEID(dentry->d_inode);
-               }
+       array = nfs_readdir_get_array(desc->page);
 
-               res = filldir(dirent, entry->name, entry->len, 
-                             file->f_pos, nfs_compat_user_ino64(fileid),
-                             d_type);
+       for (i = desc->cache_entry_index; i < array->size; i++) {
+               d_type = DT_UNKNOWN;
+
+               res = filldir(dirent, array->array[i].string.name,
+                       array->array[i].string.len, file->f_pos,
+                       nfs_compat_user_ino64(array->array[i].ino), d_type);
                if (res < 0)
                        break;
                file->f_pos++;
-               *desc->dir_cookie = entry->cookie;
-               if (dir_decode(desc) != 0) {
-                       desc->page_index ++;
+               desc->cache_entry_index = i;
+               if (i < (array->size-1))
+                       *desc->dir_cookie = array->array[i+1].cookie;
+               else
+                       *desc->dir_cookie = array->last_cookie;
+               if (i == array->eof_index) {
+                       desc->eof = 1;
                        break;
                }
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
        }
-       dir_page_release(desc);
+
+       nfs_readdir_release_array(desc->page);
+       cache_page_release(desc);
        if (dentry != NULL)
                dput(dentry);
        dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
@@ -476,12 +716,9 @@ static inline
 int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                     filldir_t filldir)
 {
-       struct file     *file = desc->file;
-       struct inode    *inode = file->f_path.dentry->d_inode;
-       struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        int             status;
-       unsigned long   timestamp, gencount;
+       struct inode *inode = desc->file->f_path.dentry->d_inode;
 
        dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
                        (unsigned long long)*desc->dir_cookie);
@@ -491,38 +728,22 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                status = -ENOMEM;
                goto out;
        }
-       timestamp = jiffies;
-       gencount = nfs_inc_attr_generation_counter();
-       status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
-                                               *desc->dir_cookie, page,
-                                               NFS_SERVER(inode)->dtsize,
-                                               desc->plus);
-       desc->page = page;
-       desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
-       if (status >= 0) {
-               desc->timestamp = timestamp;
-               desc->gencount = gencount;
-               desc->timestamp_valid = 1;
-               if ((status = dir_decode(desc)) == 0)
-                       desc->entry->prev_cookie = *desc->dir_cookie;
-       } else
+
+       if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
                status = -EIO;
-       if (status < 0)
                goto out_release;
+       }
 
+       desc->page_index = 0;
+       desc->page = page;
        status = nfs_do_filldir(desc, dirent, filldir);
 
-       /* Reset read descriptor so it searches the page cache from
-        * the start upon the next call to readdir_search_pagecache() */
-       desc->page_index = 0;
-       desc->entry->cookie = desc->entry->prev_cookie = 0;
-       desc->entry->eof = 0;
  out:
        dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
                        __func__, status);
        return status;
  out_release:
-       dir_page_release(desc);
+       cache_page_release(desc);
        goto out;
 }
 
@@ -536,7 +757,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       struct nfs_entry my_entry;
        int res = -ENOMEM;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
@@ -557,26 +777,17 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        desc->decode = NFS_PROTO(inode)->decode_dirent;
        desc->plus = NFS_USE_READDIRPLUS(inode);
 
-       my_entry.cookie = my_entry.prev_cookie = 0;
-       my_entry.eof = 0;
-       my_entry.fh = nfs_alloc_fhandle();
-       my_entry.fattr = nfs_alloc_fattr();
-       if (my_entry.fh == NULL || my_entry.fattr == NULL)
-               goto out_alloc_failed;
-
-       desc->entry = &my_entry;
-
        nfs_block_sillyrename(dentry);
        res = nfs_revalidate_mapping(inode, filp->f_mapping);
        if (res < 0)
                goto out;
 
-       while(!desc->entry->eof) {
+       while (desc->eof != 1) {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
                        /* This means either end of directory */
-                       if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
+                       if (*desc->dir_cookie && desc->eof == 0) {
                                /* Or that the server has 'lost' a cookie */
                                res = uncached_readdir(desc, dirent, filldir);
                                if (res >= 0)
@@ -588,8 +799,9 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                if (res == -ETOOSMALL && desc->plus) {
                        clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        nfs_zap_caches(inode);
+                       desc->page_index = 0;
                        desc->plus = 0;
-                       desc->entry->eof = 0;
+                       desc->eof = 0;
                        continue;
                }
                if (res < 0)
@@ -605,9 +817,6 @@ out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
                res = 0;
-out_alloc_failed:
-       nfs_free_fattr(my_entry.fattr);
-       nfs_free_fhandle(my_entry.fh);
        dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        res);
@@ -1029,10 +1238,63 @@ static int is_atomic_open(struct nameidata *nd)
        return 1;
 }
 
+static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+{
+       struct path path = {
+               .mnt = nd->path.mnt,
+               .dentry = dentry,
+       };
+       struct nfs_open_context *ctx;
+       struct rpc_cred *cred;
+       fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+
+       cred = rpc_lookup_cred();
+       if (IS_ERR(cred))
+               return ERR_CAST(cred);
+       ctx = alloc_nfs_open_context(&path, cred, fmode);
+       put_rpccred(cred);
+       if (ctx == NULL)
+               return ERR_PTR(-ENOMEM);
+       return ctx;
+}
+
+static int do_open(struct inode *inode, struct file *filp)
+{
+       nfs_fscache_set_inode_cookie(inode, filp);
+       return 0;
+}
+
+static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+{
+       struct file *filp;
+       int ret = 0;
+
+       /* If the open_intent is for execute, we have an extra check to make */
+       if (ctx->mode & FMODE_EXEC) {
+               ret = nfs_may_open(ctx->path.dentry->d_inode,
+                               ctx->cred,
+                               nd->intent.open.flags);
+               if (ret < 0)
+                       goto out;
+       }
+       filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+       if (IS_ERR(filp))
+               ret = PTR_ERR(filp);
+       else
+               nfs_file_set_open_context(filp, ctx);
+out:
+       put_nfs_open_context(ctx);
+       return ret;
+}
+
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       struct nfs_open_context *ctx;
+       struct iattr attr;
        struct dentry *res = NULL;
-       int error;
+       struct inode *inode;
+       int open_flags;
+       int err;
 
        dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1054,13 +1316,32 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                goto out;
        }
 
+       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       res = ERR_CAST(ctx);
+       if (IS_ERR(ctx))
+               goto out;
+
+       open_flags = nd->intent.open.flags;
+       if (nd->flags & LOOKUP_CREATE) {
+               attr.ia_mode = nd->intent.open.create_mode;
+               attr.ia_valid = ATTR_MODE;
+               if (!IS_POSIXACL(dir))
+                       attr.ia_mode &= ~current_umask();
+       } else {
+               open_flags &= ~(O_EXCL | O_CREAT);
+               attr.ia_valid = 0;
+       }
+
        /* Open the file on the server */
-       res = nfs4_atomic_open(dir, dentry, nd);
-       if (IS_ERR(res)) {
-               error = PTR_ERR(res);
-               switch (error) {
+       nfs_block_sillyrename(dentry->d_parent);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+       if (IS_ERR(inode)) {
+               nfs_unblock_sillyrename(dentry->d_parent);
+               put_nfs_open_context(ctx);
+               switch (PTR_ERR(inode)) {
                        /* Make a negative dentry */
                        case -ENOENT:
+                               d_add(dentry, NULL);
                                res = NULL;
                                goto out;
                        /* This turned out not to be a regular file */
@@ -1072,11 +1353,25 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                                        goto no_open;
                        /* case -EINVAL: */
                        default:
+                               res = ERR_CAST(inode);
                                goto out;
                }
-       } else if (res != NULL)
+       }
+       res = d_add_unique(dentry, inode);
+       nfs_unblock_sillyrename(dentry->d_parent);
+       if (res != NULL) {
+               dput(ctx->path.dentry);
+               ctx->path.dentry = dget(res);
                dentry = res;
+       }
+       err = nfs_intent_set_file(nd, ctx);
+       if (err < 0) {
+               if (res != NULL)
+                       dput(res);
+               return ERR_PTR(err);
+       }
 out:
+       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        return res;
 no_open:
        return nfs_lookup(dir, dentry, nd);
@@ -1087,12 +1382,15 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct dentry *parent = NULL;
        struct inode *inode = dentry->d_inode;
        struct inode *dir;
+       struct nfs_open_context *ctx;
        int openflags, ret = 0;
 
        if (!is_atomic_open(nd) || d_mountpoint(dentry))
                goto no_open;
+
        parent = dget_parent(dentry);
        dir = parent->d_inode;
+
        /* We can't create new files in nfs_open_revalidate(), so we
         * optimize away revalidation of negative dentries.
         */
@@ -1112,99 +1410,96 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* We can't create new files, or truncate existing ones here */
        openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
+       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       ret = PTR_ERR(ctx);
+       if (IS_ERR(ctx))
+               goto out;
        /*
         * Note: we're not holding inode->i_mutex and so may be racing with
         * operations that change the directory. We therefore save the
         * change attribute *before* we do the RPC call.
         */
-       ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
+       if (IS_ERR(inode)) {
+               ret = PTR_ERR(inode);
+               switch (ret) {
+               case -EPERM:
+               case -EACCES:
+               case -EDQUOT:
+               case -ENOSPC:
+               case -EROFS:
+                       goto out_put_ctx;
+               default:
+                       goto out_drop;
+               }
+       }
+       iput(inode);
+       if (inode != dentry->d_inode)
+               goto out_drop;
+
+       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+       ret = nfs_intent_set_file(nd, ctx);
+       if (ret >= 0)
+               ret = 1;
 out:
        dput(parent);
-       if (!ret)
-               d_drop(dentry);
        return ret;
+out_drop:
+       d_drop(dentry);
+       ret = 0;
+out_put_ctx:
+       put_nfs_open_context(ctx);
+       goto out;
+
 no_open_dput:
        dput(parent);
 no_open:
        return nfs_lookup_revalidate(dentry, nd);
 }
-#endif /* CONFIG_NFSV4 */
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
+               struct nameidata *nd)
 {
-       struct dentry *parent = desc->file->f_path.dentry;
-       struct inode *dir = parent->d_inode;
-       struct nfs_entry *entry = desc->entry;
-       struct dentry *dentry, *alias;
-       struct qstr name = {
-               .name = entry->name,
-               .len = entry->len,
-       };
-       struct inode *inode;
-       unsigned long verf = nfs_save_change_attribute(dir);
+       struct nfs_open_context *ctx = NULL;
+       struct iattr attr;
+       int error;
+       int open_flags = 0;
 
-       switch (name.len) {
-               case 2:
-                       if (name.name[0] == '.' && name.name[1] == '.')
-                               return dget_parent(parent);
-                       break;
-               case 1:
-                       if (name.name[0] == '.')
-                               return dget(parent);
-       }
+       dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+                       dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-       spin_lock(&dir->i_lock);
-       if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) {
-               spin_unlock(&dir->i_lock);
-               return NULL;
-       }
-       spin_unlock(&dir->i_lock);
+       attr.ia_mode = mode;
+       attr.ia_valid = ATTR_MODE;
 
-       name.hash = full_name_hash(name.name, name.len);
-       dentry = d_lookup(parent, &name);
-       if (dentry != NULL) {
-               /* Is this a positive dentry that matches the readdir info? */
-               if (dentry->d_inode != NULL &&
-                               (NFS_FILEID(dentry->d_inode) == entry->ino ||
-                               d_mountpoint(dentry))) {
-                       if (!desc->plus || entry->fh->size == 0)
-                               return dentry;
-                       if (nfs_compare_fh(NFS_FH(dentry->d_inode),
-                                               entry->fh) == 0)
-                               goto out_renew;
-               }
-               /* No, so d_drop to allow one to be created */
-               d_drop(dentry);
-               dput(dentry);
-       }
-       if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
-               return NULL;
-       if (name.len > NFS_SERVER(dir)->namelen)
-               return NULL;
-       /* Note: caller is already holding the dir->i_mutex! */
-       dentry = d_alloc(parent, &name);
-       if (dentry == NULL)
-               return NULL;
-       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
-       inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
-       if (IS_ERR(inode)) {
-               dput(dentry);
-               return NULL;
-       }
+       if ((nd->flags & LOOKUP_CREATE) != 0) {
+               open_flags = nd->intent.open.flags;
 
-       alias = d_materialise_unique(dentry, inode);
-       if (alias != NULL) {
-               dput(dentry);
-               if (IS_ERR(alias))
-                       return NULL;
-               dentry = alias;
+               ctx = nameidata_to_nfs_open_context(dentry, nd);
+               error = PTR_ERR(ctx);
+               if (IS_ERR(ctx))
+                       goto out_err_drop;
        }
 
-out_renew:
-       nfs_set_verifier(dentry, verf);
-       return dentry;
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
+       if (error != 0)
+               goto out_put_ctx;
+       if (ctx != NULL) {
+               error = nfs_intent_set_file(nd, ctx);
+               if (error < 0)
+                       goto out_err;
+       }
+       return 0;
+out_put_ctx:
+       if (ctx != NULL)
+               put_nfs_open_context(ctx);
+out_err_drop:
+       d_drop(dentry);
+out_err:
+       return error;
 }
 
+#endif /* CONFIG_NFSV4 */
+
 /*
  * Code common to create, mkdir, and mknod.
  */
@@ -1258,7 +1553,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
        struct iattr attr;
        int error;
-       int open_flags = 0;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1266,10 +1560,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if ((nd->flags & LOOKUP_CREATE) != 0)
-               open_flags = nd->intent.open.flags;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, 0, NULL);
        if (error != 0)
                goto out_err;
        return 0;
@@ -1351,76 +1642,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
        return error;
 }
 
-static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
-{
-       static unsigned int sillycounter;
-       const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
-       const int      countersize = sizeof(sillycounter)*2;
-       const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
-       char           silly[slen+1];
-       struct qstr    qsilly;
-       struct dentry *sdentry;
-       int            error = -EIO;
-
-       dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
-               dentry->d_parent->d_name.name, dentry->d_name.name, 
-               atomic_read(&dentry->d_count));
-       nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
-
-       /*
-        * We don't allow a dentry to be silly-renamed twice.
-        */
-       error = -EBUSY;
-       if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
-               goto out;
-
-       sprintf(silly, ".nfs%*.*Lx",
-               fileidsize, fileidsize,
-               (unsigned long long)NFS_FILEID(dentry->d_inode));
-
-       /* Return delegation in anticipation of the rename */
-       nfs_inode_return_delegation(dentry->d_inode);
-
-       sdentry = NULL;
-       do {
-               char *suffix = silly + slen - countersize;
-
-               dput(sdentry);
-               sillycounter++;
-               sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
-
-               dfprintk(VFS, "NFS: trying to rename %s to %s\n",
-                               dentry->d_name.name, silly);
-               
-               sdentry = lookup_one_len(silly, dentry->d_parent, slen);
-               /*
-                * N.B. Better to return EBUSY here ... it could be
-                * dangerous to delete the file while it's in use.
-                */
-               if (IS_ERR(sdentry))
-                       goto out;
-       } while(sdentry->d_inode != NULL); /* need negative lookup */
-
-       qsilly.name = silly;
-       qsilly.len  = strlen(silly);
-       if (dentry->d_inode) {
-               error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-                               dir, &qsilly);
-               nfs_mark_for_revalidate(dentry->d_inode);
-       } else
-               error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-                               dir, &qsilly);
-       if (!error) {
-               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               d_move(dentry, sdentry);
-               error = nfs_async_unlink(dir, dentry);
-               /* If we return 0 we don't unlink */
-       }
-       dput(sdentry);
-out:
-       return error;
-}
-
 /*
  * Remove a file after making sure there are no pending writes,
  * and after checking that the file has only one user. 
@@ -1711,14 +1932,14 @@ static void nfs_access_free_list(struct list_head *head)
 int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 {
        LIST_HEAD(head);
-       struct nfs_inode *nfsi;
+       struct nfs_inode *nfsi, *next;
        struct nfs_access_entry *cache;
 
        if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
                return (nr_to_scan == 0) ? 0 : -1;
 
        spin_lock(&nfs_access_lru_lock);
-       list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
+       list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) {
                struct inode *inode;
 
                if (nr_to_scan-- == 0)
index 05bf3c0..e18c31e 100644 (file)
@@ -551,7 +551,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct file *filp = vma->vm_file;
        struct dentry *dentry = filp->f_path.dentry;
        unsigned pagelen;
-       int ret = -EINVAL;
+       int ret = VM_FAULT_NOPAGE;
        struct address_space *mapping;
 
        dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
@@ -567,21 +567,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (mapping != dentry->d_inode->i_mapping)
                goto out_unlock;
 
-       ret = 0;
        pagelen = nfs_page_length(page);
        if (pagelen == 0)
                goto out_unlock;
 
-       ret = nfs_flush_incompatible(filp, page);
-       if (ret != 0)
-               goto out_unlock;
+       ret = VM_FAULT_LOCKED;
+       if (nfs_flush_incompatible(filp, page) == 0 &&
+           nfs_updatepage(filp, page, 0, pagelen) == 0)
+               goto out;
 
-       ret = nfs_updatepage(filp, page, 0, pagelen);
+       ret = VM_FAULT_SIGBUS;
 out_unlock:
-       if (!ret)
-               return VM_FAULT_LOCKED;
        unlock_page(page);
-       return VM_FAULT_SIGBUS;
+out:
+       return ret;
 }
 
 static const struct vm_operations_struct nfs_file_vm_ops = {
@@ -684,7 +683,8 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
        return ret;
 }
 
-static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
@@ -699,7 +699,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
 
-       if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
+       if (is_local)
                goto out_noconflict;
 
        status = NFS_PROTO(inode)->lock(filp, cmd, fl);
@@ -726,7 +726,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
        return res;
 }
 
-static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status;
@@ -741,15 +742,24 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
         *      If we're signalled while cleaning up locks on process exit, we
         *      still need to complete the unlock.
         */
-       /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+       /*
+        * Use local locking if mounted with "-onolock" or with appropriate
+        * "-olocal_lock="
+        */
+       if (!is_local)
                status = NFS_PROTO(inode)->lock(filp, cmd, fl);
        else
                status = do_vfs_lock(filp, fl);
        return status;
 }
 
-static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+is_time_granular(struct timespec *ts) {
+       return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
+}
+
+static int
+do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status;
@@ -762,20 +772,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
        if (status != 0)
                goto out;
 
-       /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+       /*
+        * Use local locking if mounted with "-onolock" or with appropriate
+        * "-olocal_lock="
+        */
+       if (!is_local)
                status = NFS_PROTO(inode)->lock(filp, cmd, fl);
        else
                status = do_vfs_lock(filp, fl);
        if (status < 0)
                goto out;
+
        /*
-        * Make sure we clear the cache whenever we try to get the lock.
+        * Revalidate the cache if the server has time stamps granular
+        * enough to detect subsecond changes.  Otherwise, clear the
+        * cache to prevent missing any changes.
+        *
         * This makes locking act as a cache coherency point.
         */
        nfs_sync_mapping(filp->f_mapping);
-       if (!nfs_have_delegation(inode, FMODE_READ))
-               nfs_zap_caches(inode);
+       if (!nfs_have_delegation(inode, FMODE_READ)) {
+               if (is_time_granular(&NFS_SERVER(inode)->time_delta))
+                       __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+               else
+                       nfs_zap_caches(inode);
+       }
 out:
        return status;
 }
@@ -787,6 +808,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
        struct inode *inode = filp->f_mapping->host;
        int ret = -ENOLCK;
+       int is_local = 0;
 
        dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n",
                        filp->f_path.dentry->d_parent->d_name.name,
@@ -800,6 +822,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
                goto out_err;
 
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL)
+               is_local = 1;
+
        if (NFS_PROTO(inode)->lock_check_bounds != NULL) {
                ret = NFS_PROTO(inode)->lock_check_bounds(fl);
                if (ret < 0)
@@ -807,11 +832,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
        }
 
        if (IS_GETLK(cmd))
-               ret = do_getlk(filp, cmd, fl);
+               ret = do_getlk(filp, cmd, fl, is_local);
        else if (fl->fl_type == F_UNLCK)
-               ret = do_unlk(filp, cmd, fl);
+               ret = do_unlk(filp, cmd, fl, is_local);
        else
-               ret = do_setlk(filp, cmd, fl);
+               ret = do_setlk(filp, cmd, fl, is_local);
 out_err:
        return ret;
 }
@@ -821,6 +846,9 @@ out_err:
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
+       struct inode *inode = filp->f_mapping->host;
+       int is_local = 0;
+
        dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n",
                        filp->f_path.dentry->d_parent->d_name.name,
                        filp->f_path.dentry->d_name.name,
@@ -829,14 +857,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
 
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
+               is_local = 1;
+
        /* We're simulating flock() locks using posix locks on the server */
        fl->fl_owner = (fl_owner_t)filp;
        fl->fl_start = 0;
        fl->fl_end = OFFSET_MAX;
 
        if (fl->fl_type == F_UNLCK)
-               return do_unlk(filp, cmd, fl);
-       return do_setlk(filp, cmd, fl);
+               return do_unlk(filp, cmd, fl, is_local);
+       return do_setlk(filp, cmd, fl, is_local);
 }
 
 /*
index 21a84d4..dec47ed 100644 (file)
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+#include <linux/slab.h>
+#include <linux/cred.h>
+#include <linux/nfs_idmap.h>
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include <keys/user-type.h>
+
+#define NFS_UINT_MAXLEN 11
+
+const struct cred *id_resolver_cache;
+
+struct key_type key_type_id_resolver = {
+       .name           = "id_resolver",
+       .instantiate    = user_instantiate,
+       .match          = user_match,
+       .revoke         = user_revoke,
+       .destroy        = user_destroy,
+       .describe       = user_describe,
+       .read           = user_read,
+};
+
+int nfs_idmap_init(void)
+{
+       struct cred *cred;
+       struct key *keyring;
+       int ret = 0;
+
+       printk(KERN_NOTICE "Registering the %s key type\n", key_type_id_resolver.name);
+
+       cred = prepare_kernel_cred(NULL);
+       if (!cred)
+               return -ENOMEM;
+
+       keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
+                            (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                            KEY_USR_VIEW | KEY_USR_READ,
+                            KEY_ALLOC_NOT_IN_QUOTA);
+       if (IS_ERR(keyring)) {
+               ret = PTR_ERR(keyring);
+               goto failed_put_cred;
+       }
+
+       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
+       if (ret < 0)
+               goto failed_put_key;
+
+       ret = register_key_type(&key_type_id_resolver);
+       if (ret < 0)
+               goto failed_put_key;
+
+       cred->thread_keyring = keyring;
+       cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+       id_resolver_cache = cred;
+       return 0;
+
+failed_put_key:
+       key_put(keyring);
+failed_put_cred:
+       put_cred(cred);
+       return ret;
+}
+
+void nfs_idmap_quit(void)
+{
+       key_revoke(id_resolver_cache->thread_keyring);
+       unregister_key_type(&key_type_id_resolver);
+       put_cred(id_resolver_cache);
+}
+
+/*
+ * Assemble the description to pass to request_key()
+ * This function will allocate a new string and update dest to point
+ * at it.  The caller is responsible for freeing dest.
+ *
+ * On error 0 is returned.  Otherwise, the length of dest is returned.
+ */
+static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
+                               const char *type, size_t typelen, char **desc)
+{
+       char *cp;
+       size_t desclen = typelen + namelen + 2;
+
+       *desc = kmalloc(desclen, GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       cp = *desc;
+       memcpy(cp, type, typelen);
+       cp += typelen;
+       *cp++ = ':';
+
+       memcpy(cp, name, namelen);
+       cp += namelen;
+       *cp = '\0';
+       return desclen;
+}
+
+static ssize_t nfs_idmap_request_key(const char *name, size_t namelen,
+               const char *type, void *data, size_t data_size)
+{
+       const struct cred *saved_cred;
+       struct key *rkey;
+       char *desc;
+       struct user_key_payload *payload;
+       ssize_t ret;
+
+       ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
+       if (ret <= 0)
+               goto out;
+
+       saved_cred = override_creds(id_resolver_cache);
+       rkey = request_key(&key_type_id_resolver, desc, "");
+       revert_creds(saved_cred);
+       kfree(desc);
+       if (IS_ERR(rkey)) {
+               ret = PTR_ERR(rkey);
+               goto out;
+       }
+
+       rcu_read_lock();
+       rkey->perm |= KEY_USR_VIEW;
+
+       ret = key_validate(rkey);
+       if (ret < 0)
+               goto out_up;
+
+       payload = rcu_dereference(rkey->payload.data);
+       if (IS_ERR_OR_NULL(payload)) {
+               ret = PTR_ERR(payload);
+               goto out_up;
+       }
+
+       ret = payload->datalen;
+       if (ret > 0 && ret <= data_size)
+               memcpy(data, payload->data, ret);
+       else
+               ret = -EINVAL;
+
+out_up:
+       rcu_read_unlock();
+       key_put(rkey);
+out:
+       return ret;
+}
+
+
+/* ID -> Name */
+static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, size_t buflen)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       int id_len;
+       ssize_t ret;
+
+       id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+       ret = nfs_idmap_request_key(id_str, id_len, type, buf, buflen);
+       if (ret < 0)
+               return -EINVAL;
+       return ret;
+}
+
+/* Name -> ID */
+static int nfs_idmap_lookup_id(const char *name, size_t namelen,
+                               const char *type, __u32 *id)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       long id_long;
+       ssize_t data_size;
+       int ret = 0;
+
+       data_size = nfs_idmap_request_key(name, namelen, type, id_str, NFS_UINT_MAXLEN);
+       if (data_size <= 0) {
+               ret = -EINVAL;
+       } else {
+               ret = strict_strtol(id_str, 10, &id_long);
+               *id = (__u32)id_long;
+       }
+       return ret;
+}
+
+int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+{
+       return nfs_idmap_lookup_id(name, namelen, "uid", uid);
+}
+
+int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid)
+{
+       return nfs_idmap_lookup_id(name, namelen, "gid", gid);
+}
+
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+{
+       return nfs_idmap_lookup_name(uid, "user", buf, buflen);
+}
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen)
+{
+       return nfs_idmap_lookup_name(gid, "group", buf, buflen);
+}
+
+#else  /* CONFIG_NFS_USE_IDMAPPER not defined */
+
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
@@ -503,16 +709,17 @@ int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namele
        return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
 }
 
-int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
        struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
 }
-int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
        struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
 }
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
index 7d2d6c7..6eec286 100644 (file)
@@ -234,9 +234,6 @@ nfs_init_locked(struct inode *inode, void *opaque)
        return 0;
 }
 
-/* Don't use READDIRPLUS on directories that we believe are too large */
-#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
-
 /*
  * This is our front-end to iget that looks up inodes by file handle
  * instead of inode number.
@@ -291,8 +288,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
-                       if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
-                           && fattr->size <= NFS_LIMIT_READDIRPLUS)
+                       if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
                        if ((fattr->valid & NFS_ATTR_FATTR_FSID)
@@ -623,7 +619,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
        nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
+struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
 {
        struct nfs_open_context *ctx;
 
@@ -633,11 +629,13 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
                path_get(&ctx->path);
                ctx->cred = get_rpccred(cred);
                ctx->state = NULL;
+               ctx->mode = f_mode;
                ctx->flags = 0;
                ctx->error = 0;
                ctx->dir_cookie = 0;
                nfs_init_lock_context(&ctx->lock_context);
                ctx->lock_context.open_context = ctx;
+               INIT_LIST_HEAD(&ctx->list);
        }
        return ctx;
 }
@@ -653,11 +651,15 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 {
        struct inode *inode = ctx->path.dentry->d_inode;
 
-       if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+       if (!list_empty(&ctx->list)) {
+               if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+                       return;
+               list_del(&ctx->list);
+               spin_unlock(&inode->i_lock);
+       } else if (!atomic_dec_and_test(&ctx->lock_context.count))
                return;
-       list_del(&ctx->list);
-       spin_unlock(&inode->i_lock);
-       NFS_PROTO(inode)->close_context(ctx, is_sync);
+       if (inode != NULL)
+               NFS_PROTO(inode)->close_context(ctx, is_sync);
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        path_put(&ctx->path);
@@ -673,7 +675,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
 {
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -730,11 +732,10 @@ int nfs_open(struct inode *inode, struct file *filp)
        cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(&filp->f_path, cred);
+       ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
        put_rpccred(cred);
        if (ctx == NULL)
                return -ENOMEM;
-       ctx->mode = filp->f_mode;
        nfs_file_set_open_context(filp, ctx);
        put_nfs_open_context(ctx);
        nfs_fscache_set_inode_cookie(inode, filp);
@@ -1493,7 +1494,7 @@ static int nfsiod_start(void)
 {
        struct workqueue_struct *wq;
        dprintk("RPC:       creating workqueue nfsiod\n");
-       wq = create_singlethread_workqueue("nfsiod");
+       wq = alloc_workqueue("nfsiod", WQ_RESCUER, 0);
        if (wq == NULL)
                return -ENOMEM;
        nfsiod_workqueue = wq;
@@ -1521,6 +1522,10 @@ static int __init init_nfs_fs(void)
 {
        int err;
 
+       err = nfs_idmap_init();
+       if (err < 0)
+               goto out9;
+
        err = nfs_dns_resolver_init();
        if (err < 0)
                goto out8;
@@ -1585,6 +1590,8 @@ out6:
 out7:
        nfs_dns_resolver_destroy();
 out8:
+       nfs_idmap_quit();
+out9:
        return err;
 }
 
@@ -1597,6 +1604,7 @@ static void __exit exit_nfs_fs(void)
        nfs_destroy_nfspagecache();
        nfs_fscache_unregister();
        nfs_dns_resolver_destroy();
+       nfs_idmap_quit();
 #ifdef CONFIG_PROC_FS
        rpc_proc_unregister("nfs");
 #endif
index c961bc9..db08ff3 100644 (file)
@@ -63,6 +63,12 @@ struct nfs_clone_mount {
 #define NFS_UNSPEC_PORT                (-1)
 
 /*
+ * Maximum number of pages that readdir can use for creating
+ * a vmapped array of pages.
+ */
+#define NFS_MAX_READDIR_PAGES 8
+
+/*
  * In-kernel mount arguments
  */
 struct nfs_parsed_mount_data {
@@ -181,15 +187,15 @@ extern void nfs_destroy_directcache(void);
 /* nfs2xdr.c */
 extern int nfs_stat_to_errno(int);
 extern struct rpc_procinfo nfs_procedures[];
-extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs3xdr.c */
 extern struct rpc_procinfo nfs3_procedures[];
-extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs4xdr.c */
 #ifdef CONFIG_NFS_V4
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 #endif
 #ifdef CONFIG_NFS_V4_1
 extern const u32 nfs41_maxread_overhead;
index 59047f8..d610203 100644 (file)
@@ -436,7 +436,7 @@ static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
 
        for (i = 0; i < entries; i++) {
                flavors[i] = ntohl(*p++);
-               dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]);
+               dprintk("NFS:   auth flavor[%u]: %d\n", i, flavors[i]);
        }
        *count = i;
 
index db8846a..e6bf457 100644 (file)
@@ -337,10 +337,10 @@ nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
 static int
 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-       p = xdr_encode_fhandle(p, args->fromfh);
-       p = xdr_encode_array(p, args->fromname, args->fromlen);
-       p = xdr_encode_fhandle(p, args->tofh);
-       p = xdr_encode_array(p, args->toname, args->tolen);
+       p = xdr_encode_fhandle(p, args->old_dir);
+       p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+       p = xdr_encode_fhandle(p, args->new_dir);
+       p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
        return 0;
 }
@@ -423,9 +423,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        struct page **page;
        size_t hdrlen;
        unsigned int pglen, recvd;
-       u32 len;
        int status, nr = 0;
-       __be32 *end, *entry, *kaddr;
 
        if ((status = ntohl(*p++)))
                return nfs_stat_to_errno(status);
@@ -445,80 +443,59 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        if (pglen > recvd)
                pglen = recvd;
        page = rcvbuf->pages;
-       kaddr = p = kmap_atomic(*page, KM_USER0);
-       end = (__be32 *)((char *)p + pglen);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               if (p + 2 > end)
-                       goto short_pkt;
-               p++; /* fileid */
-               len = ntohl(*p++);
-               p += XDR_QUADLEN(len) + 1;      /* name plus cookie */
-               if (len > NFS2_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-                                               len);
-                       goto err_unmap;
-               }
-               if (p + 2 > end)
-                       goto short_pkt;
-               entry = p;
-       }
-
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
- out:
-       kunmap_atomic(kaddr, KM_USER0);
        return nr;
- short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       entry[0] = entry[1] = 0;
-       if (!nr)
-               nr = -errno_NFSERR_IO;
-       goto out;
-err_unmap:
-       nr = -errno_NFSERR_IO;
-       goto out;
+}
+
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+       dprintk("nfs: %s: prematurely hit end of receive buffer. "
+               "Remaining buffer length is %tu words.\n",
+               func, xdr->end - xdr->p);
 }
 
 __be32 *
-nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
-       if (!*p++) {
-               if (!*p)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+               goto out_overflow;
+
        entry->ino        = ntohl(*p++);
        entry->len        = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len + 4);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name       = (const char *) p;
        p                += XDR_QUADLEN(entry->len);
        entry->prev_cookie        = entry->cookie;
        entry->cookie     = ntohl(*p++);
-       entry->eof        = !p[0] && p[1];
+
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
 
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
 }
 
 /*
@@ -596,7 +573,6 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
        struct kvec *iov = rcvbuf->head;
        size_t hdrlen;
        u32 len, recvd;
-       char    *kaddr;
        int     status;
 
        if ((status = ntohl(*p++)))
@@ -623,10 +599,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
                return -EIO;
        }
 
-       /* NULL terminate the string we got */
-       kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 }
 
index fabb4f2..ce939c0 100644 (file)
@@ -313,7 +313,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                int flags, struct nameidata *nd)
+                int flags, struct nfs_open_context *ctx)
 {
        struct nfs3_createdata *data;
        mode_t mode = sattr->ia_mode;
@@ -438,19 +438,38 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void
+nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
+}
+
+static int
+nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                     struct inode *new_dir)
+{
+       struct nfs_renameres *res;
+
+       if (nfs3_async_handle_jukebox(task, old_dir))
+               return 0;
+       res = task->tk_msg.rpc_resp;
+
+       nfs_post_op_update_inode(old_dir, res->old_fattr);
+       nfs_post_op_update_inode(new_dir, res->new_fattr);
+       return 1;
+}
+
 static int
 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
                 struct inode *new_dir, struct qstr *new_name)
 {
-       struct nfs3_renameargs  arg = {
-               .fromfh         = NFS_FH(old_dir),
-               .fromname       = old_name->name,
-               .fromlen        = old_name->len,
-               .tofh           = NFS_FH(new_dir),
-               .toname         = new_name->name,
-               .tolen          = new_name->len
+       struct nfs_renameargs   arg = {
+               .old_dir        = NFS_FH(old_dir),
+               .old_name       = old_name,
+               .new_dir        = NFS_FH(new_dir),
+               .new_name       = new_name,
        };
-       struct nfs3_renameres res;
+       struct nfs_renameres res;
        struct rpc_message msg = {
                .rpc_proc       = &nfs3_procedures[NFS3PROC_RENAME],
                .rpc_argp       = &arg,
@@ -460,17 +479,17 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
 
-       res.fromattr = nfs_alloc_fattr();
-       res.toattr = nfs_alloc_fattr();
-       if (res.fromattr == NULL || res.toattr == NULL)
+       res.old_fattr = nfs_alloc_fattr();
+       res.new_fattr = nfs_alloc_fattr();
+       if (res.old_fattr == NULL || res.new_fattr == NULL)
                goto out;
 
        status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
-       nfs_post_op_update_inode(old_dir, res.fromattr);
-       nfs_post_op_update_inode(new_dir, res.toattr);
+       nfs_post_op_update_inode(old_dir, res.old_fattr);
+       nfs_post_op_update_inode(new_dir, res.new_fattr);
 out:
-       nfs_free_fattr(res.toattr);
-       nfs_free_fattr(res.fromattr);
+       nfs_free_fattr(res.old_fattr);
+       nfs_free_fattr(res.new_fattr);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
@@ -611,7 +630,7 @@ out:
  */
 static int
 nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                 u64 cookie, struct page *page, unsigned int count, int plus)
+                 u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        __be32                  *verf = NFS_COOKIEVERF(dir);
@@ -621,7 +640,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                .verf           = {verf[0], verf[1]},
                .plus           = plus,
                .count          = count,
-               .pages          = &page
+               .pages          = pages
        };
        struct nfs3_readdirres  res = {
                .verf           = verf,
@@ -652,7 +671,8 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
        nfs_free_fattr(res.dir_attr);
 out:
-       dprintk("NFS reply readdir: %d\n", status);
+       dprintk("NFS reply readdir%s: %d\n",
+                       plus? "plus" : "", status);
        return status;
 }
 
@@ -722,7 +742,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
        dprintk("NFS call  fsstat\n");
        nfs_fattr_init(stat->fattr);
        status = rpc_call_sync(server->client, &msg, 0);
-       dprintk("NFS reply statfs: %d\n", status);
+       dprintk("NFS reply fsstat: %d\n", status);
        return status;
 }
 
@@ -844,6 +864,8 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .unlink_setup   = nfs3_proc_unlink_setup,
        .unlink_done    = nfs3_proc_unlink_done,
        .rename         = nfs3_proc_rename,
+       .rename_setup   = nfs3_proc_rename_setup,
+       .rename_done    = nfs3_proc_rename_done,
        .link           = nfs3_proc_link,
        .symlink        = nfs3_proc_symlink,
        .mkdir          = nfs3_proc_mkdir,
index 9769704..d9a5e83 100644 (file)
@@ -100,6 +100,13 @@ static const umode_t nfs_type2fmt[] = {
        [NF3FIFO] = S_IFIFO,
 };
 
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+       dprintk("nfs: %s: prematurely hit end of receive buffer. "
+               "Remaining buffer length is %tu words.\n",
+               func, xdr->end - xdr->p);
+}
+
 /*
  * Common NFS XDR functions as inlines
  */
@@ -119,6 +126,29 @@ xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
        return NULL;
 }
 
+static inline __be32 *
+xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       fh->size = ntohl(*p++);
+
+       if (fh->size <= NFS3_FHSIZE) {
+               p = xdr_inline_decode(xdr, fh->size);
+               if (unlikely(!p))
+                       goto out_overflow;
+               memcpy(fh->data, p, fh->size);
+               return p + XDR_QUADLEN(fh->size);
+       }
+       return NULL;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
+}
+
 /*
  * Encode/decode time.
  */
@@ -241,6 +271,26 @@ xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
 }
 
 static inline __be32 *
+xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+{
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 84);
+               if (unlikely(!p))
+                       goto out_overflow;
+               p = xdr_decode_fattr(p, fattr);
+       }
+       return p;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
+}
+
+static inline __be32 *
 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
 {
        if (*p++)
@@ -442,12 +492,12 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
  * Encode RENAME arguments
  */
 static int
-nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
+nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-       p = xdr_encode_fhandle(p, args->fromfh);
-       p = xdr_encode_array(p, args->fromname, args->fromlen);
-       p = xdr_encode_fhandle(p, args->tofh);
-       p = xdr_encode_array(p, args->toname, args->tolen);
+       p = xdr_encode_fhandle(p, args->old_dir);
+       p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+       p = xdr_encode_fhandle(p, args->new_dir);
+       p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
        return 0;
 }
@@ -504,9 +554,8 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        struct kvec *iov = rcvbuf->head;
        struct page **page;
        size_t hdrlen;
-       u32 len, recvd, pglen;
+       u32 recvd, pglen;
        int status, nr = 0;
-       __be32 *entry, *end, *kaddr;
 
        status = ntohl(*p++);
        /* Decode post_op_attrs */
@@ -536,99 +585,38 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        if (pglen > recvd)
                pglen = recvd;
        page = rcvbuf->pages;
-       kaddr = p = kmap_atomic(*page, KM_USER0);
-       end = (__be32 *)((char *)p + pglen);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               if (p + 3 > end)
-                       goto short_pkt;
-               p += 2;                         /* inode # */
-               len = ntohl(*p++);              /* string length */
-               p += XDR_QUADLEN(len) + 2;      /* name + cookie */
-               if (len > NFS3_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-                                               len);
-                       goto err_unmap;
-               }
 
-               if (res->plus) {
-                       /* post_op_attr */
-                       if (p + 2 > end)
-                               goto short_pkt;
-                       if (*p++) {
-                               p += 21;
-                               if (p + 1 > end)
-                                       goto short_pkt;
-                       }
-                       /* post_op_fh3 */
-                       if (*p++) {
-                               if (p + 1 > end)
-                                       goto short_pkt;
-                               len = ntohl(*p++);
-                               if (len > NFS3_FHSIZE) {
-                                       dprintk("NFS: giant filehandle in "
-                                               "readdir (len 0x%x)!\n", len);
-                                       goto err_unmap;
-                               }
-                               p += XDR_QUADLEN(len);
-                       }
-               }
-
-               if (p + 2 > end)
-                       goto short_pkt;
-               entry = p;
-       }
-
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
- out:
-       kunmap_atomic(kaddr, KM_USER0);
        return nr;
- short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       entry[0] = entry[1] = 0;
-       if (!nr)
-               nr = -errno_NFSERR_IO;
-       goto out;
-err_unmap:
-       nr = -errno_NFSERR_IO;
-       goto out;
 }
 
 __be32 *
-nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
+       __be32 *p;
        struct nfs_entry old = *entry;
 
-       if (!*p++) {
-               if (!*p)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+               goto out_overflow;
        p = xdr_decode_hyper(p, &entry->ino);
        entry->len  = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len + 8);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name = (const char *) p;
        p += XDR_QUADLEN(entry->len);
        entry->prev_cookie = entry->cookie;
@@ -636,10 +624,17 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 
        if (plus) {
                entry->fattr->valid = 0;
-               p = xdr_decode_post_op_attr(p, entry->fattr);
+               p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
+               if (IS_ERR(p))
+                       goto out_overflow_exit;
                /* In fact, a post_op_fh3: */
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
                if (*p++) {
-                       p = xdr_decode_fhandle(p, entry->fh);
+                       p = xdr_decode_fhandle_stream(xdr, entry->fh);
+                       if (IS_ERR(p))
+                               goto out_overflow_exit;
                        /* Ugh -- server reply was truncated */
                        if (p == NULL) {
                                dprintk("NFS: FH truncated\n");
@@ -650,8 +645,18 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
                        memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
        }
 
-       entry->eof = !p[0] && p[1];
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
+
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+out_overflow_exit:
+       return ERR_PTR(-EIO);
 }
 
 /*
@@ -824,7 +829,6 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        struct kvec *iov = rcvbuf->head;
        size_t hdrlen;
        u32 len, recvd;
-       char    *kaddr;
        int     status;
 
        status = ntohl(*p++);
@@ -857,10 +861,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
                return -EIO;
        }
 
-       /* NULL terminate the string we got */
-       kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 }
 
@@ -970,14 +971,14 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
  * Decode RENAME reply
  */
 static int
-nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
+nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
 {
        int     status;
 
        if ((status = ntohl(*p++)) != 0)
                status = nfs_stat_to_errno(status);
-       p = xdr_decode_wcc_data(p, res->fromattr);
-       p = xdr_decode_wcc_data(p, res->toattr);
+       p = xdr_decode_wcc_data(p, res->old_fattr);
+       p = xdr_decode_wcc_data(p, res->new_fattr);
        return status;
 }
 
@@ -1043,8 +1044,9 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
        res->wtmult = ntohl(*p++);
        res->dtpref = ntohl(*p++);
        p = xdr_decode_hyper(p, &res->maxfilesize);
+       p = xdr_decode_time3(p, &res->time_delta);
 
-       /* ignore time_delta and properties */
+       /* ignore properties */
        res->lease_time = 0;
        return 0;
 }
index 311e15c..9fa4963 100644 (file)
@@ -242,8 +242,6 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
                struct nfs4_fs_locations *fs_locations, struct page *page);
@@ -333,7 +331,7 @@ extern void nfs_free_seqid(struct nfs_seqid *seqid);
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 extern struct rpc_procinfo nfs4_procedures[];
 
 struct nfs4_mount_data;
index 089da5b..e87fe61 100644 (file)
@@ -129,7 +129,7 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
                        | FATTR4_WORD0_MAXREAD
                        | FATTR4_WORD0_MAXWRITE
                        | FATTR4_WORD0_LEASE_TIME,
-                       0
+                       FATTR4_WORD1_TIME_DELTA
 };
 
 const u32 nfs4_fs_locations_bitmap[2] = {
@@ -255,9 +255,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                        nfs4_state_mark_reclaim_nograce(clp, state);
                        goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
-                       if (state == NULL)
-                               break;
-                       nfs4_state_mark_reclaim_reboot(clp, state);
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_EXPIRED:
                        goto do_state_recovery;
@@ -334,10 +331,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
  * Must be called while holding tbl->slot_tbl_lock
  */
 static void
-nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
+nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
 {
+       int free_slotid = free_slot - tbl->slots;
        int slotid = free_slotid;
 
+       BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
        /* clear used bit in bitmap */
        __clear_bit(slotid, tbl->used_slots);
 
@@ -379,7 +378,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
        struct nfs4_slot_table *tbl;
 
        tbl = &res->sr_session->fc_slot_table;
-       if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
+       if (!res->sr_slot) {
                /* just wake up the next guy waiting since
                 * we may have not consumed a slot after all */
                dprintk("%s: No slot\n", __func__);
@@ -387,17 +386,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
        }
 
        spin_lock(&tbl->slot_tbl_lock);
-       nfs4_free_slot(tbl, res->sr_slotid);
+       nfs4_free_slot(tbl, res->sr_slot);
        nfs41_check_drain_session_complete(res->sr_session);
        spin_unlock(&tbl->slot_tbl_lock);
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+       res->sr_slot = NULL;
 }
 
 static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
 {
        unsigned long timestamp;
-       struct nfs4_slot_table *tbl;
-       struct nfs4_slot *slot;
        struct nfs_client *clp;
 
        /*
@@ -410,17 +407,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
                res->sr_status = NFS_OK;
 
        /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-       if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
+       if (!res->sr_slot)
                goto out;
 
-       tbl = &res->sr_session->fc_slot_table;
-       slot = tbl->slots + res->sr_slotid;
-
        /* Check the SEQUENCE operation status */
        switch (res->sr_status) {
        case 0:
                /* Update the slot's sequence and clientid lease timer */
-               ++slot->seq_nr;
+               ++res->sr_slot->seq_nr;
                timestamp = res->sr_renewal_time;
                clp = res->sr_session->clp;
                do_renew_lease(clp, timestamp);
@@ -433,12 +427,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
                 * returned NFS4ERR_DELAY as per Section 2.10.6.2
                 * of RFC5661.
                 */
-               dprintk("%s: slot=%d seq=%d: Operation in progress\n",
-                               __func__, res->sr_slotid, slot->seq_nr);
+               dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
+                       __func__,
+                       res->sr_slot - res->sr_session->fc_slot_table.slots,
+                       res->sr_slot->seq_nr);
                goto out_retry;
        default:
                /* Just update the slot sequence no. */
-               ++slot->seq_nr;
+               ++res->sr_slot->seq_nr;
        }
 out:
        /* The session may be reset by one of the error handlers. */
@@ -505,10 +501,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
 
        dprintk("--> %s\n", __func__);
        /* slot already allocated? */
-       if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
+       if (res->sr_slot != NULL)
                return 0;
 
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
        tbl = &session->fc_slot_table;
 
        spin_lock(&tbl->slot_tbl_lock);
@@ -550,7 +545,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
        dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
 
        res->sr_session = session;
-       res->sr_slotid = slotid;
+       res->sr_slot = slot;
        res->sr_renewal_time = jiffies;
        res->sr_status_flags = 0;
        /*
@@ -576,8 +571,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
                goto out;
        }
 
-       dprintk("--> %s clp %p session %p sr_slotid %d\n",
-               __func__, session->clp, session, res->sr_slotid);
+       dprintk("--> %s clp %p session %p sr_slot %ld\n",
+               __func__, session->clp, session, res->sr_slot ?
+                       res->sr_slot - session->fc_slot_table.slots : -1);
 
        ret = nfs41_setup_sequence(session, args, res, cache_reply,
                                   task);
@@ -650,7 +646,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server,
                .callback_data = &data
        };
 
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+       res->sr_slot = NULL;
        if (privileged)
                task_setup.callback_ops = &nfs41_call_priv_sync_ops;
        task = rpc_run_task(&task_setup);
@@ -735,7 +731,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
        p->o_res.server = p->o_arg.server;
        nfs_fattr_init(&p->f_attr);
        nfs_fattr_init(&p->dir_attr);
-       p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
 
 static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
@@ -1120,6 +1115,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
        clear_bit(NFS_DELEGATED_STATE, &state->flags);
        smp_rmb();
        if (state->n_rdwr != 0) {
+               clear_bit(NFS_O_RDWR_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
@@ -1127,6 +1123,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
                        return -ESTALE;
        }
        if (state->n_wronly != 0) {
+               clear_bit(NFS_O_WRONLY_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
@@ -1134,6 +1131,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
                        return -ESTALE;
        }
        if (state->n_rdonly != 0) {
+               clear_bit(NFS_O_RDONLY_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
                if (ret != 0)
                        return ret;
@@ -1188,7 +1186,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
        int err;
        do {
                err = _nfs4_do_open_reclaim(ctx, state);
-               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+               if (err != -NFS4ERR_DELAY)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -1258,6 +1256,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
                        case -NFS4ERR_ADMIN_REVOKED:
                        case -NFS4ERR_BAD_STATEID:
                                nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
                        case -ENOMEM:
                                err = 0;
                                goto out;
@@ -1605,7 +1610,6 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
-               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -1975,7 +1979,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i
        calldata->res.fattr = &calldata->fattr;
        calldata->res.seqid = calldata->arg.seqid;
        calldata->res.server = server;
-       calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        path_get(path);
        calldata->path = *path;
 
@@ -1998,120 +2001,17 @@ out:
        return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
-{
-       struct file *filp;
-       int ret;
-
-       /* If the open_intent is for execute, we have an extra check to make */
-       if (fmode & FMODE_EXEC) {
-               ret = nfs_may_open(state->inode,
-                               state->owner->so_cred,
-                               nd->intent.open.flags);
-               if (ret < 0)
-                       goto out_close;
-       }
-       filp = lookup_instantiate_filp(nd, path->dentry, NULL);
-       if (!IS_ERR(filp)) {
-               struct nfs_open_context *ctx;
-               ctx = nfs_file_open_context(filp);
-               ctx->state = state;
-               return 0;
-       }
-       ret = PTR_ERR(filp);
-out_close:
-       nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
-       return ret;
-}
-
-struct dentry *
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct inode *
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
-       struct path path = {
-               .mnt = nd->path.mnt,
-               .dentry = dentry,
-       };
-       struct dentry *parent;
-       struct iattr attr;
-       struct rpc_cred *cred;
        struct nfs4_state *state;
-       struct dentry *res;
-       int open_flags = nd->intent.open.flags;
-       fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
-
-       if (nd->flags & LOOKUP_CREATE) {
-               attr.ia_mode = nd->intent.open.create_mode;
-               attr.ia_valid = ATTR_MODE;
-               if (!IS_POSIXACL(dir))
-                       attr.ia_mode &= ~current_umask();
-       } else {
-               open_flags &= ~O_EXCL;
-               attr.ia_valid = 0;
-               BUG_ON(open_flags & O_CREAT);
-       }
 
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return (struct dentry *)cred;
-       parent = dentry->d_parent;
        /* Protect against concurrent sillydeletes */
-       nfs_block_sillyrename(parent);
-       state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               if (PTR_ERR(state) == -ENOENT) {
-                       d_add(dentry, NULL);
-                       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               }
-               nfs_unblock_sillyrename(parent);
-               return (struct dentry *)state;
-       }
-       res = d_add_unique(dentry, igrab(state->inode));
-       if (res != NULL)
-               path.dentry = res;
-       nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
-       nfs_unblock_sillyrename(parent);
-       nfs4_intent_set_file(nd, &path, state, fmode);
-       return res;
-}
-
-int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
-{
-       struct path path = {
-               .mnt = nd->path.mnt,
-               .dentry = dentry,
-       };
-       struct rpc_cred *cred;
-       struct nfs4_state *state;
-       fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
-
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return PTR_ERR(cred);
-       state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               switch (PTR_ERR(state)) {
-                       case -EPERM:
-                       case -EACCES:
-                       case -EDQUOT:
-                       case -ENOSPC:
-                       case -EROFS:
-                               return PTR_ERR(state);
-                       default:
-                               goto out_drop;
-               }
-       }
-       if (state->inode == dentry->d_inode) {
-               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               nfs4_intent_set_file(nd, &path, state, fmode);
-               return 1;
-       }
-       nfs4_close_sync(&path, state, fmode);
-out_drop:
-       d_drop(dentry);
-       return 0;
+       state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
+       if (IS_ERR(state))
+               return ERR_CAST(state);
+       ctx->state = state;
+       return igrab(state->inode);
 }
 
 static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
@@ -2568,36 +2468,34 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nameidata *nd)
+                 int flags, struct nfs_open_context *ctx)
 {
-       struct path path = {
-               .mnt = nd->path.mnt,
+       struct path my_path = {
                .dentry = dentry,
        };
+       struct path *path = &my_path;
        struct nfs4_state *state;
-       struct rpc_cred *cred;
-       fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
+       struct rpc_cred *cred = NULL;
+       fmode_t fmode = 0;
        int status = 0;
 
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred)) {
-               status = PTR_ERR(cred);
-               goto out;
+       if (ctx != NULL) {
+               cred = ctx->cred;
+               path = &ctx->path;
+               fmode = ctx->mode;
        }
-       state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+       state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
        d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
-               goto out_putcred;
+               goto out;
        }
        d_add(dentry, igrab(state->inode));
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-               status = nfs4_intent_set_file(nd, &path, state, fmode);
+       if (ctx != NULL)
+               ctx->state = state;
        else
-               nfs4_close_sync(&path, state, fmode);
-out_putcred:
-       put_rpccred(cred);
+               nfs4_close_sync(path, state, fmode);
 out:
        return status;
 }
@@ -2655,6 +2553,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 
        args->bitmask = server->cache_consistency_bitmask;
        res->server = server;
+       res->seq_res.sr_slot = NULL;
        msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
 }
 
@@ -2671,18 +2570,46 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       struct nfs_server *server = NFS_SERVER(dir);
+       struct nfs_renameargs *arg = msg->rpc_argp;
+       struct nfs_renameres *res = msg->rpc_resp;
+
+       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
+       arg->bitmask = server->attr_bitmask;
+       res->server = server;
+}
+
+static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                                struct inode *new_dir)
+{
+       struct nfs_renameres *res = task->tk_msg.rpc_resp;
+
+       if (!nfs4_sequence_done(task, &res->seq_res))
+               return 0;
+       if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+               return 0;
+
+       update_changeattr(old_dir, &res->old_cinfo);
+       nfs_post_op_update_inode(old_dir, res->old_fattr);
+       update_changeattr(new_dir, &res->new_cinfo);
+       nfs_post_op_update_inode(new_dir, res->new_fattr);
+       return 1;
+}
+
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
                struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_server *server = NFS_SERVER(old_dir);
-       struct nfs4_rename_arg arg = {
+       struct nfs_renameargs arg = {
                .old_dir = NFS_FH(old_dir),
                .new_dir = NFS_FH(new_dir),
                .old_name = old_name,
                .new_name = new_name,
                .bitmask = server->attr_bitmask,
        };
-       struct nfs4_rename_res res = {
+       struct nfs_renameres res = {
                .server = server,
        };
        struct rpc_message msg = {
@@ -2896,15 +2823,16 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 }
 
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        struct nfs4_readdir_arg args = {
                .fh = NFS_FH(dir),
-               .pages = &page,
+               .pages = pages,
                .pgbase = 0,
                .count = count,
                .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+               .plus = plus,
        };
        struct nfs4_readdir_res res;
        struct rpc_message msg = {
@@ -2932,14 +2860,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
                                _nfs4_proc_readdir(dentry, cred, cookie,
-                                       page, count, plus),
+                                       pages, count, plus),
                                &exception);
        } while (exception.retry);
        return err;
@@ -3490,9 +3418,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        nfs4_state_mark_reclaim_nograce(clp, state);
                        goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
-                       if (state == NULL)
-                               break;
-                       nfs4_state_mark_reclaim_reboot(clp, state);
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_EXPIRED:
                        goto do_state_recovery;
@@ -3626,7 +3551,6 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                        case -NFS4ERR_RESOURCE:
                                /* The IBM lawyers misread another document! */
                        case -NFS4ERR_DELAY:
-                       case -EKEYEXPIRED:
                                err = nfs4_delay(clp->cl_rpcclient, &timeout);
                }
        } while (err == 0);
@@ -3721,7 +3645,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
        memcpy(&data->stateid, stateid, sizeof(data->stateid));
        data->res.fattr = &data->fattr;
        data->res.server = server;
-       data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        nfs_fattr_init(data->res.fattr);
        data->timestamp = jiffies;
        data->rpc_status = 0;
@@ -3874,7 +3797,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
        p->arg.fl = &p->fl;
        p->arg.seqid = seqid;
        p->res.seqid = seqid;
-       p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        p->arg.stateid = &lsp->ls_stateid;
        p->lsp = lsp;
        atomic_inc(&lsp->ls_count);
@@ -4054,7 +3976,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
        p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
        p->arg.lock_owner.id = lsp->ls_id.id;
        p->res.lock_seqid = p->arg.lock_seqid;
-       p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        p->lsp = lsp;
        p->server = server;
        atomic_inc(&lsp->ls_count);
@@ -4241,7 +4162,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
                if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
                        return 0;
                err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
-               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+               if (err != -NFS4ERR_DELAY)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -4266,7 +4187,6 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
-               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -4412,13 +4332,21 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
                                nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
                                err = 0;
                                goto out;
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
+                               err = 0;
+                               goto out;
                        case -ENOMEM:
                        case -NFS4ERR_DENIED:
                                /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                                err = 0;
                                goto out;
                        case -NFS4ERR_DELAY:
-                       case -EKEYEXPIRED:
                                break;
                }
                err = nfs4_handle_exception(server, err, &exception);
@@ -4647,7 +4575,6 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
        switch (task->tk_status) {
        case -NFS4ERR_DELAY:
        case -NFS4ERR_GRACE:
-       case -EKEYEXPIRED:
                dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
                rpc_delay(task, NFS4_POLL_RETRY_MIN);
                task->tk_status = 0;
@@ -4687,7 +4614,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
        };
        int status;
 
-       res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        dprintk("--> %s\n", __func__);
        task = rpc_run_task(&task_setup);
 
@@ -5111,7 +5037,6 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client
 {
        switch(task->tk_status) {
        case -NFS4ERR_DELAY:
-       case -EKEYEXPIRED:
                rpc_delay(task, NFS4_POLL_RETRY_MAX);
                return -EAGAIN;
        default:
@@ -5180,12 +5105,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
 
        if (!atomic_inc_not_zero(&clp->cl_count))
                return ERR_PTR(-EIO);
-       calldata = kmalloc(sizeof(*calldata), GFP_NOFS);
+       calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
        if (calldata == NULL) {
                nfs_put_client(clp);
                return ERR_PTR(-ENOMEM);
        }
-       calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        msg.rpc_argp = &calldata->args;
        msg.rpc_resp = &calldata->res;
        calldata->clp = clp;
@@ -5254,7 +5178,6 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
        case -NFS4ERR_WRONG_CRED: /* What to do here? */
                break;
        case -NFS4ERR_DELAY:
-       case -EKEYEXPIRED:
                rpc_delay(task, NFS4_POLL_RETRY_MAX);
                return -EAGAIN;
        default:
@@ -5317,7 +5240,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
                goto out;
        calldata->clp = clp;
        calldata->arg.one_fs = 0;
-       calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 
        msg.rpc_argp = &calldata->arg;
        msg.rpc_resp = &calldata->res;
@@ -5443,6 +5365,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .unlink_setup   = nfs4_proc_unlink_setup,
        .unlink_done    = nfs4_proc_unlink_done,
        .rename         = nfs4_proc_rename,
+       .rename_setup   = nfs4_proc_rename_setup,
+       .rename_done    = nfs4_proc_rename_done,
        .link           = nfs4_proc_link,
        .symlink        = nfs4_proc_symlink,
        .mkdir          = nfs4_proc_mkdir,
@@ -5463,6 +5387,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .lock           = nfs4_proc_lock,
        .clear_acl_cache = nfs4_zap_acl_attr,
        .close_context  = nfs4_close_context,
+       .open_context   = nfs4_atomic_open,
 };
 
 /*
index 96524c5..aa0b02a 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/ratelimit.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
@@ -1063,6 +1064,14 @@ restart:
                                /* Mark the file as being 'closed' */
                                state->state = 0;
                                break;
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
+                               break;
                        case -NFS4ERR_ADMIN_REVOKED:
                        case -NFS4ERR_STALE_STATEID:
                        case -NFS4ERR_BAD_STATEID:
@@ -1138,16 +1147,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp,
                (void)ops->reclaim_complete(clp);
 }
 
-static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
        struct rb_node *pos;
        struct nfs4_state *state;
 
        if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
-               return;
-
-       nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
+               return 0;
 
        for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
                sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
@@ -1161,6 +1168,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
        }
 
        nfs_delegation_reap_unclaimed(clp);
+       return 1;
+}
+
+static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+{
+       if (!nfs4_state_clear_reclaim_reboot(clp))
+               return;
+       nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
 }
 
 static void nfs_delegation_clear_all(struct nfs_client *clp)
@@ -1175,6 +1190,14 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
        nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
 }
 
+static void nfs4_warn_keyexpired(const char *s)
+{
+       printk_ratelimited(KERN_WARNING "Error: state manager"
+                       " encountered RPCSEC_GSS session"
+                       " expired against NFSv4 server %s.\n",
+                       s);
+}
+
 static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
 {
        switch (error) {
@@ -1187,7 +1210,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_LEASE_MOVED:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-                       nfs4_state_end_reclaim_reboot(clp);
+                       nfs4_state_clear_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED:
@@ -1204,6 +1227,10 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                        set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
                        /* Zero session reset errors */
                        return 0;
+               case -EKEYEXPIRED:
+                       /* Nothing we can do */
+                       nfs4_warn_keyexpired(clp->cl_hostname);
+                       return 0;
        }
        return error;
 }
@@ -1414,9 +1441,10 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
                case -NFS4ERR_DELAY:
                case -NFS4ERR_CLID_INUSE:
                case -EAGAIN:
-               case -EKEYEXPIRED:
                        break;
 
+               case -EKEYEXPIRED:
+                       nfs4_warn_keyexpired(clp->cl_hostname);
                case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
                                         * in nfs4_exchange_id */
                default:
index 08ef912..bd2101d 100644 (file)
@@ -816,7 +816,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
        if (iap->ia_valid & ATTR_MODE)
                len += 4;
        if (iap->ia_valid & ATTR_UID) {
-               owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
+               owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ);
                if (owner_namelen < 0) {
                        dprintk("nfs: couldn't resolve uid %d to string\n",
                                        iap->ia_uid);
@@ -828,7 +828,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
                len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
        }
        if (iap->ia_valid & ATTR_GID) {
-               owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
+               owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ);
                if (owner_grouplen < 0) {
                        dprintk("nfs: couldn't resolve gid %d to string\n",
                                        iap->ia_gid);
@@ -1385,24 +1385,35 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
 
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
-       uint32_t attrs[2] = {
-               FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
-               FATTR4_WORD1_MOUNTED_ON_FILEID,
-       };
+       uint32_t attrs[2] = {0, 0};
+       uint32_t dircount = readdir->count >> 1;
        __be32 *p;
 
+       if (readdir->plus) {
+               attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
+                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
+               attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
+                       FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
+                       FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
+                       FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+               dircount >>= 1;
+       }
+       attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
+       attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
+       /* Switch to mounted_on_fileid if the server supports it */
+       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
+               attrs[0] &= ~FATTR4_WORD0_FILEID;
+       else
+               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+
        p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
        *p++ = cpu_to_be32(OP_READDIR);
        p = xdr_encode_hyper(p, readdir->cookie);
        p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
-       *p++ = cpu_to_be32(readdir->count >> 1);  /* We're not doing readdirplus */
+       *p++ = cpu_to_be32(dircount);
        *p++ = cpu_to_be32(readdir->count);
        *p++ = cpu_to_be32(2);
-       /* Switch to mounted_on_fileid if the server supports it */
-       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
-               attrs[0] &= ~FATTR4_WORD0_FILEID;
-       else
-               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+
        *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
        *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
        hdr->nops++;
@@ -1823,7 +1834,7 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
 /*
  * Encode RENAME request
  */
-static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
+static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs_renameargs *args)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
@@ -2676,7 +2687,10 @@ out_overflow:
 static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
 {
        if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
-               decode_attr_bitmap(xdr, bitmask);
+               int ret;
+               ret = decode_attr_bitmap(xdr, bitmask);
+               if (unlikely(ret < 0))
+                       return ret;
                bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
        } else
                bitmask[0] = bitmask[1] = 0;
@@ -2848,6 +2862,56 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
+{
+       __be32 *p;
+
+       if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
+               return -EIO;
+       if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
+{
+       __be32 *p;
+       int len;
+
+       if (fh != NULL)
+               memset(fh, 0, sizeof(*fh));
+
+       if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
+               return -EIO;
+       if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               len = be32_to_cpup(p);
+               if (len > NFS4_FHSIZE)
+                       return -EIO;
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (fh != NULL) {
+                       memcpy(fh->data, p, len);
+                       fh->size = len;
+               }
+               bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
 static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
        __be32 *p;
@@ -3521,6 +3585,24 @@ static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, s
        return status;
 }
 
+static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
+                                 struct timespec *time)
+{
+       int status = 0;
+
+       time->tv_sec = 0;
+       time->tv_nsec = 0;
+       if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
+               return -EIO;
+       if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
+               status = decode_attr_time(xdr, time);
+               bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
+       }
+       dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec,
+               (long)time->tv_nsec);
+       return status;
+}
+
 static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
 {
        int status = 0;
@@ -3744,29 +3826,14 @@ xdr_error:
        return status;
 }
 
-static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+               struct nfs_fattr *fattr, struct nfs_fh *fh,
                const struct nfs_server *server, int may_sleep)
 {
-       __be32 *savep;
-       uint32_t attrlen,
-                bitmap[2] = {0},
-                type;
        int status;
        umode_t fmode = 0;
        uint64_t fileid;
-
-       status = decode_op_hdr(xdr, OP_GETATTR);
-       if (status < 0)
-               goto xdr_error;
-
-       status = decode_attr_bitmap(xdr, bitmap);
-       if (status < 0)
-               goto xdr_error;
-
-       status = decode_attr_length(xdr, &attrlen, &savep);
-       if (status < 0)
-               goto xdr_error;
-
+       uint32_t type;
 
        status = decode_attr_type(xdr, bitmap, &type);
        if (status < 0)
@@ -3792,6 +3859,14 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
                goto xdr_error;
        fattr->valid |= status;
 
+       status = decode_attr_error(xdr, bitmap);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_filehandle(xdr, bitmap, fh);
+       if (status < 0)
+               goto xdr_error;
+
        status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
        if (status < 0)
                goto xdr_error;
@@ -3862,12 +3937,46 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
                fattr->valid |= status;
        }
 
+xdr_error:
+       dprintk("%s: xdr returned %d\n", __func__, -status);
+       return status;
+}
+
+static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+               struct nfs_fh *fh, const struct nfs_server *server, int may_sleep)
+{
+       __be32 *savep;
+       uint32_t attrlen,
+                bitmap[2] = {0};
+       int status;
+
+       status = decode_op_hdr(xdr, OP_GETATTR);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_bitmap(xdr, bitmap);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_length(xdr, &attrlen, &savep);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep);
+       if (status < 0)
+               goto xdr_error;
+
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
        dprintk("%s: xdr returned %d\n", __func__, -status);
        return status;
 }
 
+static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+               const struct nfs_server *server, int may_sleep)
+{
+       return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep);
+}
 
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
@@ -3894,6 +4003,9 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
        if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
                goto xdr_error;
        fsinfo->wtpref = fsinfo->wtmax;
+       status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
+       if (status != 0)
+               goto xdr_error;
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -3950,13 +4062,13 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
        __be32 *p;
        uint32_t namelen, type;
 
-       p = xdr_inline_decode(xdr, 32);
+       p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
        if (unlikely(!p))
                goto out_overflow;
-       p = xdr_decode_hyper(p, &offset);
+       p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
        p = xdr_decode_hyper(p, &length);
-       type = be32_to_cpup(p++);
-       if (fl != NULL) {
+       type = be32_to_cpup(p++); /* 4 byte read */
+       if (fl != NULL) { /* manipulate file lock */
                fl->fl_start = (loff_t)offset;
                fl->fl_end = fl->fl_start + (loff_t)length - 1;
                if (length == ~(uint64_t)0)
@@ -3966,9 +4078,9 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
                        fl->fl_type = F_RDLCK;
                fl->fl_pid = 0;
        }
-       p = xdr_decode_hyper(p, &clientid);
-       namelen = be32_to_cpup(p);
-       p = xdr_inline_decode(xdr, namelen);
+       p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
+       namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
+       p = xdr_inline_decode(xdr, namelen); /* variable size field */
        if (likely(p))
                return -NFS4ERR_DENIED;
 out_overflow:
@@ -4200,12 +4312,9 @@ out_overflow:
 static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
 {
        struct xdr_buf  *rcvbuf = &req->rq_rcv_buf;
-       struct page     *page = *rcvbuf->pages;
        struct kvec     *iov = rcvbuf->head;
        size_t          hdrlen;
        u32             recvd, pglen = rcvbuf->page_len;
-       __be32          *end, *entry, *p, *kaddr;
-       unsigned int    nr = 0;
        int             status;
 
        status = decode_op_hdr(xdr, OP_READDIR);
@@ -4225,71 +4334,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
                pglen = recvd;
        xdr_read_pages(xdr, pglen);
 
-       BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
-       kaddr = p = kmap_atomic(page, KM_USER0);
-       end = p + ((pglen + readdir->pgbase) >> 2);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               u32 len, attrlen, xlen;
-               if (end - p < 3)
-                       goto short_pkt;
-               dprintk("cookie = %Lu, ", *((unsigned long long *)p));
-               p += 2;                 /* cookie */
-               len = ntohl(*p++);      /* filename length */
-               if (len > NFS4_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)\n",
-                                       len);
-                       goto err_unmap;
-               }
-               xlen = XDR_QUADLEN(len);
-               if (end - p < xlen + 1)
-                       goto short_pkt;
-               dprintk("filename = %*s\n", len, (char *)p);
-               p += xlen;
-               len = ntohl(*p++);      /* bitmap length */
-               if (end - p < len + 1)
-                       goto short_pkt;
-               p += len;
-               attrlen = XDR_QUADLEN(ntohl(*p++));
-               if (end - p < attrlen + 2)
-                       goto short_pkt;
-               p += attrlen;           /* attributes */
-               entry = p;
-       }
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
-out:
-       kunmap_atomic(kaddr, KM_USER0);
+
        return 0;
-short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       dprintk("%s: short packet at entry %d\n", __func__, nr);
-       entry[0] = entry[1] = 0;
-       if (nr)
-               goto out;
-err_unmap:
-       kunmap_atomic(kaddr, KM_USER0);
-       return -errno_NFSERR_IO;
 }
 
 static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
@@ -4299,7 +4345,6 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
        size_t hdrlen;
        u32 len, recvd;
        __be32 *p;
-       char *kaddr;
        int status;
 
        status = decode_op_hdr(xdr, OP_READLINK);
@@ -4330,9 +4375,7 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
         * and and null-terminate the text (the VFS expects
         * null-termination).
         */
-       kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 out_overflow:
        print_overflow_msg(__func__, xdr);
@@ -4668,7 +4711,6 @@ static int decode_sequence(struct xdr_stream *xdr,
                           struct rpc_rqst *rqstp)
 {
 #if defined(CONFIG_NFS_V4_1)
-       struct nfs4_slot *slot;
        struct nfs4_sessionid id;
        u32 dummy;
        int status;
@@ -4700,15 +4742,14 @@ static int decode_sequence(struct xdr_stream *xdr,
                goto out_overflow;
 
        /* seqid */
-       slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
        dummy = be32_to_cpup(p++);
-       if (dummy != slot->seq_nr) {
+       if (dummy != res->sr_slot->seq_nr) {
                dprintk("%s Invalid sequence number\n", __func__);
                goto out_err;
        }
        /* slot id */
        dummy = be32_to_cpup(p++);
-       if (dummy != res->sr_slotid) {
+       if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
                dprintk("%s Invalid slot id\n", __func__);
                goto out_err;
        }
@@ -4873,7 +4914,7 @@ out:
 /*
  * Decode RENAME response
  */
-static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
+static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs_renameres *res)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
@@ -5760,23 +5801,35 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
 }
 #endif /* CONFIG_NFS_V4_1 */
 
-__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+                          struct nfs_server *server, int plus)
 {
        uint32_t bitmap[2] = {0};
        uint32_t len;
-
-       if (!*p++) {
-               if (!*p)
+       __be32 *p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->prev_cookie = entry->cookie;
        p = xdr_decode_hyper(p, &entry->cookie);
        entry->len = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name = (const char *) p;
-       p += XDR_QUADLEN(entry->len);
 
        /*
         * In case the server doesn't return an inode number,
@@ -5784,32 +5837,33 @@ __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
         * since glibc seems to choke on it...)
         */
        entry->ino = 1;
+       entry->fattr->valid = 0;
 
-       len = ntohl(*p++);              /* bitmap length */
-       if (len-- > 0) {
-               bitmap[0] = ntohl(*p++);
-               if (len-- > 0) {
-                       bitmap[1] = ntohl(*p++);
-                       p += len;
-               }
-       }
-       len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
-       if (len > 0) {
-               if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
-                       bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
-                       /* Ignore the return value of rdattr_error for now */
-                       p++;
-                       len--;
-               }
-               if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
-                       xdr_decode_hyper(p, &entry->ino);
-               else if (bitmap[0] == FATTR4_WORD0_FILEID)
-                       xdr_decode_hyper(p, &entry->ino);
-               p += len;
-       }
+       if (decode_attr_bitmap(xdr, bitmap) < 0)
+               goto out_overflow;
+
+       if (decode_attr_length(xdr, &len, &p) < 0)
+               goto out_overflow;
+
+       if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0)
+               goto out_overflow;
+       if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+               entry->ino = entry->fattr->fileid;
+
+       if (verify_attr_len(xdr, p, len) < 0)
+               goto out_overflow;
+
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
 
-       entry->eof = !p[0] && p[1];
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
 }
 
 /*
index df101d9..460df36 100644 (file)
@@ -3,9 +3,10 @@
  *
  *  Allow an NFS filesystem to be mounted as root. The way this works is:
  *     (1) Use the IP autoconfig mechanism to set local IP addresses and routes.
- *     (2) Handle RPC negotiation with the system which replied to RARP or
- *         was reported as a boot server by BOOTP or manually.
- *     (3) The actual mounting is done later, when init() is running.
+ *     (2) Construct the device string and the options string using DHCP
+ *         option 17 and/or kernel command line options.
+ *     (3) When mount_root() sets up the root file system, pass these strings
+ *         to the NFS client's regular mount interface via sys_mount().
  *
  *
  *     Changes:
  *     Hua Qin         :       Support for mounting root file system via
  *                             NFS over TCP.
  *     Fabian Frederick:       Option parser rebuilt (using parser lib)
-*/
+ *     Chuck Lever     :       Use super.c's text-based mount option parsing
+ *     Chuck Lever     :       Add "nfsrootdebug".
+ */
 
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/xprtsock.h>
 #include <linux/nfs.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_mount.h>
-#include <linux/in.h>
-#include <linux/major.h>
 #include <linux/utsname.h>
-#include <linux/inet.h>
 #include <linux/root_dev.h>
 #include <net/ipconfig.h>
-#include <linux/parser.h>
 
 #include "internal.h"
 
-/* Define this to allow debugging output */
-#undef NFSROOT_DEBUG
 #define NFSDBG_FACILITY NFSDBG_ROOT
 
-/* Default port to use if server is not running a portmapper */
-#define NFS_MNT_PORT   627
-
 /* Default path we try to mount. "%s" gets replaced by our IP address */
 #define NFS_ROOT               "/tftpboot/%s"
 
 /* Parameters passed from the kernel command line */
-static char nfs_root_name[256] __initdata = "";
+static char nfs_root_parms[256] __initdata = "";
+
+/* Text-based mount options passed to super.c */
+static char nfs_root_options[256] __initdata = "";
 
 /* Address of NFS server */
-static __be32 servaddr __initdata = 0;
+static __be32 servaddr __initdata = htonl(INADDR_NONE);
 
 /* Name of directory to mount */
-static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, };
-
-/* NFS-related data */
-static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
-static int nfs_port __initdata = 0;            /* Port to connect to for NFS */
-static int mount_port __initdata = 0;          /* Mount daemon port number */
-
-
-/***************************************************************************
-
-                            Parsing of options
-
- ***************************************************************************/
-
-enum {
-       /* Options that take integer arguments */
-       Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin,
-       Opt_acregmax, Opt_acdirmin, Opt_acdirmax,
-       /* Options that take no arguments */
-       Opt_soft, Opt_hard, Opt_intr,
-       Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 
-       Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
-       Opt_acl, Opt_noacl,
-       /* Error token */
-       Opt_err
-};
-
-static const match_table_t tokens __initconst = {
-       {Opt_port, "port=%u"},
-       {Opt_rsize, "rsize=%u"},
-       {Opt_wsize, "wsize=%u"},
-       {Opt_timeo, "timeo=%u"},
-       {Opt_retrans, "retrans=%u"},
-       {Opt_acregmin, "acregmin=%u"},
-       {Opt_acregmax, "acregmax=%u"},
-       {Opt_acdirmin, "acdirmin=%u"},
-       {Opt_acdirmax, "acdirmax=%u"},
-       {Opt_soft, "soft"},
-       {Opt_hard, "hard"},
-       {Opt_intr, "intr"},
-       {Opt_nointr, "nointr"},
-       {Opt_posix, "posix"},
-       {Opt_noposix, "noposix"},
-       {Opt_cto, "cto"},
-       {Opt_nocto, "nocto"},
-       {Opt_ac, "ac"},
-       {Opt_noac, "noac"},
-       {Opt_lock, "lock"},
-       {Opt_nolock, "nolock"},
-       {Opt_v2, "nfsvers=2"},
-       {Opt_v2, "v2"},
-       {Opt_v3, "nfsvers=3"},
-       {Opt_v3, "v3"},
-       {Opt_udp, "proto=udp"},
-       {Opt_udp, "udp"},
-       {Opt_tcp, "proto=tcp"},
-       {Opt_tcp, "tcp"},
-       {Opt_acl, "acl"},
-       {Opt_noacl, "noacl"},
-       {Opt_err, NULL}
-       
-};
+static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = "";
+
+/* server:export path string passed to super.c */
+static char nfs_root_device[NFS_MAXPATHLEN + 1] __initdata = "";
 
 /*
- *  Parse option string.
+ * When the "nfsrootdebug" kernel command line option is specified,
+ * enable debugging messages for NFSROOT.
  */
-
-static int __init root_nfs_parse(char *name, char *buf)
+static int __init nfs_root_debug(char *__unused)
 {
-
-       char *p;
-       substring_t args[MAX_OPT_ARGS];
-       int option;
-
-       if (!name)
-               return 1;
-
-       /* Set the NFS remote path */
-       p = strsep(&name, ",");
-       if (p[0] != '\0' && strcmp(p, "default") != 0)
-               strlcpy(buf, p, NFS_MAXPATHLEN);
-
-       while ((p = strsep (&name, ",")) != NULL) {
-               int token; 
-               if (!*p)
-                       continue;
-               token = match_token(p, tokens, args);
-
-               /* %u tokens only. Beware if you add new tokens! */
-               if (token < Opt_soft && match_int(&args[0], &option))
-                       return 0;
-               switch (token) {
-                       case Opt_port:
-                               nfs_port = option;
-                               break;
-                       case Opt_rsize:
-                               nfs_data.rsize = option;
-                               break;
-                       case Opt_wsize:
-                               nfs_data.wsize = option;
-                               break;
-                       case Opt_timeo:
-                               nfs_data.timeo = option;
-                               break;
-                       case Opt_retrans:
-                               nfs_data.retrans = option;
-                               break;
-                       case Opt_acregmin:
-                               nfs_data.acregmin = option;
-                               break;
-                       case Opt_acregmax:
-                               nfs_data.acregmax = option;
-                               break;
-                       case Opt_acdirmin:
-                               nfs_data.acdirmin = option;
-                               break;
-                       case Opt_acdirmax:
-                               nfs_data.acdirmax = option;
-                               break;
-                       case Opt_soft:
-                               nfs_data.flags |= NFS_MOUNT_SOFT;
-                               break;
-                       case Opt_hard:
-                               nfs_data.flags &= ~NFS_MOUNT_SOFT;
-                               break;
-                       case Opt_intr:
-                       case Opt_nointr:
-                               break;
-                       case Opt_posix:
-                               nfs_data.flags |= NFS_MOUNT_POSIX;
-                               break;
-                       case Opt_noposix:
-                               nfs_data.flags &= ~NFS_MOUNT_POSIX;
-                               break;
-                       case Opt_cto:
-                               nfs_data.flags &= ~NFS_MOUNT_NOCTO;
-                               break;
-                       case Opt_nocto:
-                               nfs_data.flags |= NFS_MOUNT_NOCTO;
-                               break;
-                       case Opt_ac:
-                               nfs_data.flags &= ~NFS_MOUNT_NOAC;
-                               break;
-                       case Opt_noac:
-                               nfs_data.flags |= NFS_MOUNT_NOAC;
-                               break;
-                       case Opt_lock:
-                               nfs_data.flags &= ~NFS_MOUNT_NONLM;
-                               break;
-                       case Opt_nolock:
-                               nfs_data.flags |= NFS_MOUNT_NONLM;
-                               break;
-                       case Opt_v2:
-                               nfs_data.flags &= ~NFS_MOUNT_VER3;
-                               break;
-                       case Opt_v3:
-                               nfs_data.flags |= NFS_MOUNT_VER3;
-                               break;
-                       case Opt_udp:
-                               nfs_data.flags &= ~NFS_MOUNT_TCP;
-                               break;
-                       case Opt_tcp:
-                               nfs_data.flags |= NFS_MOUNT_TCP;
-                               break;
-                       case Opt_acl:
-                               nfs_data.flags &= ~NFS_MOUNT_NOACL;
-                               break;
-                       case Opt_noacl:
-                               nfs_data.flags |= NFS_MOUNT_NOACL;
-                               break;
-                       default:
-                               printk(KERN_WARNING "Root-NFS: unknown "
-                                       "option: %s\n", p);
-                               return 0;
-               }
-       }
-
+       nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
        return 1;
 }
 
+__setup("nfsrootdebug", nfs_root_debug);
+
 /*
- *  Prepare the NFS data structure and parse all options.
+ *  Parse NFS server and directory information passed on the kernel
+ *  command line.
+ *
+ *  nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
+ *
+ *  If there is a "%s" token in the <root-dir> string, it is replaced
+ *  by the ASCII-representation of the client's IP address.
  */
-static int __init root_nfs_name(char *name)
+static int __init nfs_root_setup(char *line)
 {
-       static char buf[NFS_MAXPATHLEN] __initdata;
-       char *cp;
-
-       /* Set some default values */
-       memset(&nfs_data, 0, sizeof(nfs_data));
-       nfs_port          = -1;
-       nfs_data.version  = NFS_MOUNT_VERSION;
-       nfs_data.flags    = NFS_MOUNT_NONLM;    /* No lockd in nfs root yet */
-       nfs_data.rsize    = NFS_DEF_FILE_IO_SIZE;
-       nfs_data.wsize    = NFS_DEF_FILE_IO_SIZE;
-       nfs_data.acregmin = NFS_DEF_ACREGMIN;
-       nfs_data.acregmax = NFS_DEF_ACREGMAX;
-       nfs_data.acdirmin = NFS_DEF_ACDIRMIN;
-       nfs_data.acdirmax = NFS_DEF_ACDIRMAX;
-       strcpy(buf, NFS_ROOT);
-
-       /* Process options received from the remote server */
-       root_nfs_parse(root_server_path, buf);
-
-       /* Override them by options set on kernel command-line */
-       root_nfs_parse(name, buf);
-
-       cp = utsname()->nodename;
-       if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
-               printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
-               return -1;
+       ROOT_DEV = Root_NFS;
+
+       if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
+               strlcpy(nfs_root_parms, line, sizeof(nfs_root_parms));
+       } else {
+               size_t n = strlen(line) + sizeof(NFS_ROOT) - 1;
+               if (n >= sizeof(nfs_root_parms))
+                       line[sizeof(nfs_root_parms) - sizeof(NFS_ROOT) - 2] = '\0';
+               sprintf(nfs_root_parms, NFS_ROOT, line);
        }
-       sprintf(nfs_export_path, buf, cp);
+
+       /*
+        * Extract the IP address of the NFS server containing our
+        * root file system, if one was specified.
+        *
+        * Note: root_nfs_parse_addr() removes the server-ip from
+        *       nfs_root_parms, if it exists.
+        */
+       root_server_addr = root_nfs_parse_addr(nfs_root_parms);
 
        return 1;
 }
 
+__setup("nfsroot=", nfs_root_setup);
 
-/*
- *  Get NFS server address.
- */
-static int __init root_nfs_addr(void)
+static int __init root_nfs_copy(char *dest, const char *src,
+                                    const size_t destlen)
 {
-       if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) {
-               printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
+       if (strlcpy(dest, src, destlen) > destlen)
                return -1;
-       }
+       return 0;
+}
 
-       snprintf(nfs_data.hostname, sizeof(nfs_data.hostname),
-                "%pI4", &servaddr);
+static int __init root_nfs_cat(char *dest, const char *src,
+                                 const size_t destlen)
+{
+       if (strlcat(dest, src, destlen) > destlen)
+               return -1;
        return 0;
 }
 
 /*
- *  Tell the user what's going on.
+ * Parse out root export path and mount options from
+ * passed-in string @incoming.
+ *
+ * Copy the export path into @exppath.
  */
-#ifdef NFSROOT_DEBUG
-static void __init root_nfs_print(void)
+static int __init root_nfs_parse_options(char *incoming, char *exppath,
+                                        const size_t exppathlen)
 {
-       printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
-               nfs_export_path, nfs_data.hostname);
-       printk(KERN_NOTICE "Root-NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-               nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
-       printk(KERN_NOTICE "Root-NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
-               nfs_data.acregmin, nfs_data.acregmax,
-               nfs_data.acdirmin, nfs_data.acdirmax);
-       printk(KERN_NOTICE "Root-NFS:     nfsd port = %d, mountd port = %d, flags = %08x\n",
-               nfs_port, mount_port, nfs_data.flags);
-}
-#endif
-
+       char *p;
 
-static int __init root_nfs_init(void)
-{
-#ifdef NFSROOT_DEBUG
-       nfs_debug |= NFSDBG_ROOT;
-#endif
+       /*
+        * Set the NFS remote path
+        */
+       p = strsep(&incoming, ",");
+       if (*p != '\0' && strcmp(p, "default") != 0)
+               if (root_nfs_copy(exppath, p, exppathlen))
+                       return -1;
 
        /*
-        * Decode the root directory path name and NFS options from
-        * the kernel command line. This has to go here in order to
-        * be able to use the client IP address for the remote root
-        * directory (necessary for pure RARP booting).
+        * @incoming now points to the rest of the string; if it
+        * contains something, append it to our root options buffer
         */
-       if (root_nfs_name(nfs_root_name) < 0 ||
-           root_nfs_addr() < 0)
-               return -1;
+       if (incoming != NULL && *incoming != '\0')
+               if (root_nfs_cat(nfs_root_options, incoming,
+                                               sizeof(nfs_root_options)))
+                       return -1;
 
-#ifdef NFSROOT_DEBUG
-       root_nfs_print();
-#endif
+       /*
+        * Possibly prepare for more options to be appended
+        */
+       if (nfs_root_options[0] != '\0' &&
+           nfs_root_options[strlen(nfs_root_options)] != ',')
+               if (root_nfs_cat(nfs_root_options, ",",
+                                               sizeof(nfs_root_options)))
+                       return -1;
 
        return 0;
 }
 
-
 /*
- *  Parse NFS server and directory information passed on the kernel
- *  command line.
+ *  Decode the export directory path name and NFS options from
+ *  the kernel command line.  This has to be done late in order to
+ *  use a dynamically acquired client IP address for the remote
+ *  root directory path.
+ *
+ *  Returns zero if successful; otherwise -1 is returned.
  */
-static int __init nfs_root_setup(char *line)
+static int __init root_nfs_data(char *cmdline)
 {
-       ROOT_DEV = Root_NFS;
-       if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
-               strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
-       } else {
-               int n = strlen(line) + sizeof(NFS_ROOT) - 1;
-               if (n >= sizeof(nfs_root_name))
-                       line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
-               sprintf(nfs_root_name, NFS_ROOT, line);
+       char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1];
+       int len, retval = -1;
+       char *tmp = NULL;
+       const size_t tmplen = sizeof(nfs_export_path);
+
+       tmp = kzalloc(tmplen, GFP_KERNEL);
+       if (tmp == NULL)
+               goto out_nomem;
+       strcpy(tmp, NFS_ROOT);
+
+       if (root_server_path[0] != '\0') {
+               dprintk("Root-NFS: DHCPv4 option 17: %s\n",
+                       root_server_path);
+               if (root_nfs_parse_options(root_server_path, tmp, tmplen))
+                       goto out_optionstoolong;
        }
-       root_server_addr = root_nfs_parse_addr(nfs_root_name);
-       return 1;
-}
 
-__setup("nfsroot=", nfs_root_setup);
-
-/***************************************************************************
-
-              Routines to actually mount the root directory
+       if (cmdline[0] != '\0') {
+               dprintk("Root-NFS: nfsroot=%s\n", cmdline);
+               if (root_nfs_parse_options(cmdline, tmp, tmplen))
+                       goto out_optionstoolong;
+       }
 
- ***************************************************************************/
+       /*
+        * Append mandatory options for nfsroot so they override
+        * what has come before
+        */
+       snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4",
+                       &servaddr);
+       if (root_nfs_cat(nfs_root_options, addr_option,
+                                               sizeof(nfs_root_options)))
+               goto out_optionstoolong;
 
-/*
- *  Construct sockaddr_in from address and port number.
- */
-static inline void
-set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
-{
-       sin->sin_family = AF_INET;
-       sin->sin_addr.s_addr = addr;
-       sin->sin_port = port;
-}
+       /*
+        * Set up nfs_root_device.  For NFS mounts, this looks like
+        *
+        *      server:/path
+        *
+        * At this point, utsname()->nodename contains our local
+        * IP address or hostname, set by ipconfig.  If "%s" exists
+        * in tmp, substitute the nodename, then shovel the whole
+        * mess into nfs_root_device.
+        */
+       len = snprintf(nfs_export_path, sizeof(nfs_export_path),
+                               tmp, utsname()->nodename);
+       if (len > (int)sizeof(nfs_export_path))
+               goto out_devnametoolong;
+       len = snprintf(nfs_root_device, sizeof(nfs_root_device),
+                               "%pI4:%s", &servaddr, nfs_export_path);
+       if (len > (int)sizeof(nfs_root_device))
+               goto out_devnametoolong;
 
-/*
- *  Query server portmapper for the port of a daemon program.
- */
-static int __init root_nfs_getport(int program, int version, int proto)
-{
-       struct sockaddr_in sin;
+       retval = 0;
 
-       printk(KERN_NOTICE "Looking up port of RPC %d/%d on %pI4\n",
-               program, version, &servaddr);
-       set_sockaddr(&sin, servaddr, 0);
-       return rpcb_getport_sync(&sin, program, version, proto);
+out:
+       kfree(tmp);
+       return retval;
+out_nomem:
+       printk(KERN_ERR "Root-NFS: could not allocate memory\n");
+       goto out;
+out_optionstoolong:
+       printk(KERN_ERR "Root-NFS: mount options string too long\n");
+       goto out;
+out_devnametoolong:
+       printk(KERN_ERR "Root-NFS: root device name too long.\n");
+       goto out;
 }
 
-
-/*
- *  Use portmapper to find mountd and nfsd port numbers if not overriden
- *  by the user. Use defaults if portmapper is not available.
- *  XXX: Is there any nfs server with no portmapper?
+/**
+ * nfs_root_data - Return prepared 'data' for NFSROOT mount
+ * @root_device: OUT: address of string containing NFSROOT device
+ * @root_data: OUT: address of string containing NFSROOT mount options
+ *
+ * Returns zero and sets @root_device and @root_data if successful,
+ * otherwise -1 is returned.
  */
-static int __init root_nfs_ports(void)
+int __init nfs_root_data(char **root_device, char **root_data)
 {
-       int port;
-       int nfsd_ver, mountd_ver;
-       int nfsd_port, mountd_port;
-       int proto;
-
-       if (nfs_data.flags & NFS_MOUNT_VER3) {
-               nfsd_ver = NFS3_VERSION;
-               mountd_ver = NFS_MNT3_VERSION;
-               nfsd_port = NFS_PORT;
-               mountd_port = NFS_MNT_PORT;
-       } else {
-               nfsd_ver = NFS2_VERSION;
-               mountd_ver = NFS_MNT_VERSION;
-               nfsd_port = NFS_PORT;
-               mountd_port = NFS_MNT_PORT;
-       }
-
-       proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
-
-       if (nfs_port < 0) {
-               if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) {
-                       printk(KERN_ERR "Root-NFS: Unable to get nfsd port "
-                                       "number from server, using default\n");
-                       port = nfsd_port;
-               }
-               nfs_port = port;
-               dprintk("Root-NFS: Portmapper on server returned %d "
-                       "as nfsd port\n", port);
+       servaddr = root_server_addr;
+       if (servaddr == htonl(INADDR_NONE)) {
+               printk(KERN_ERR "Root-NFS: no NFS server address\n");
+               return -1;
        }
 
-       if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
-               printk(KERN_ERR "Root-NFS: Unable to get mountd port "
-                               "number from server, using default\n");
-               port = mountd_port;
-       }
-       mount_port = port;
-       dprintk("Root-NFS: mountd port is %d\n", port);
+       if (root_nfs_data(nfs_root_parms) < 0)
+               return -1;
 
+       *root_device = nfs_root_device;
+       *root_data = nfs_root_options;
        return 0;
 }
-
-
-/*
- *  Get a file handle from the server for the directory which is to be
- *  mounted.
- */
-static int __init root_nfs_get_handle(void)
-{
-       struct sockaddr_in sin;
-       unsigned int auth_flav_len = 0;
-       struct nfs_mount_request request = {
-               .sap            = (struct sockaddr *)&sin,
-               .salen          = sizeof(sin),
-               .dirpath        = nfs_export_path,
-               .version        = (nfs_data.flags & NFS_MOUNT_VER3) ?
-                                       NFS_MNT3_VERSION : NFS_MNT_VERSION,
-               .protocol       = (nfs_data.flags & NFS_MOUNT_TCP) ?
-                                       XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
-               .auth_flav_len  = &auth_flav_len,
-       };
-       int status = -ENOMEM;
-
-       request.fh = nfs_alloc_fhandle();
-       if (!request.fh)
-               goto out;
-       set_sockaddr(&sin, servaddr, htons(mount_port));
-       status = nfs_mount(&request);
-       if (status < 0)
-               printk(KERN_ERR "Root-NFS: Server returned error %d "
-                               "while mounting %s\n", status, nfs_export_path);
-       else {
-               nfs_data.root.size = request.fh->size;
-               memcpy(&nfs_data.root.data, request.fh->data, request.fh->size);
-       }
-       nfs_free_fhandle(request.fh);
-out:
-       return status;
-}
-
-/*
- *  Get the NFS port numbers and file handle, and return the prepared 'data'
- *  argument for mount() if everything went OK. Return NULL otherwise.
- */
-void * __init nfs_root_data(void)
-{
-       if (root_nfs_init() < 0
-        || root_nfs_ports() < 0
-        || root_nfs_get_handle() < 0)
-               return NULL;
-       set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
-       return (void*)&nfs_data;
-}
index 611bec2..58e7f84 100644 (file)
@@ -258,7 +258,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-               int flags, struct nameidata *nd)
+               int flags, struct nfs_open_context *ctx)
 {
        struct nfs_createdata *data;
        struct rpc_message msg = {
@@ -365,17 +365,32 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void
+nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
+}
+
+static int
+nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                    struct inode *new_dir)
+{
+       if (nfs_async_handle_expired_key(task))
+               return 0;
+       nfs_mark_for_revalidate(old_dir);
+       nfs_mark_for_revalidate(new_dir);
+       return 1;
+}
+
 static int
 nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
                struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_renameargs   arg = {
-               .fromfh         = NFS_FH(old_dir),
-               .fromname       = old_name->name,
-               .fromlen        = old_name->len,
-               .tofh           = NFS_FH(new_dir),
-               .toname         = new_name->name,
-               .tolen          = new_name->len
+               .old_dir        = NFS_FH(old_dir),
+               .old_name       = old_name,
+               .new_dir        = NFS_FH(new_dir),
+               .new_name       = new_name,
        };
        struct rpc_message msg = {
                .rpc_proc       = &nfs_procedures[NFSPROC_RENAME],
@@ -519,14 +534,14 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
  */
 static int
 nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                u64 cookie, struct page *page, unsigned int count, int plus)
+                u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        struct nfs_readdirargs  arg = {
                .fh             = NFS_FH(dir),
                .cookie         = cookie,
                .count          = count,
-               .pages          = &page,
+               .pages          = pages,
        };
        struct rpc_message      msg = {
                .rpc_proc       = &nfs_procedures[NFSPROC_READDIR],
@@ -705,6 +720,8 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .unlink_setup   = nfs_proc_unlink_setup,
        .unlink_done    = nfs_proc_unlink_done,
        .rename         = nfs_proc_rename,
+       .rename_setup   = nfs_proc_rename_setup,
+       .rename_done    = nfs_proc_rename_done,
        .link           = nfs_proc_link,
        .symlink        = nfs_proc_symlink,
        .mkdir          = nfs_proc_mkdir,
index 87adc27..79859c8 100644 (file)
@@ -46,7 +46,6 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
                p->npages = pagecount;
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
                if (pagecount <= ARRAY_SIZE(p->page_array))
                        p->pagevec = p->page_array;
                else {
index f4cbf0c..3600ec7 100644 (file)
@@ -100,6 +100,7 @@ enum {
        Opt_addr, Opt_mountaddr, Opt_clientaddr,
        Opt_lookupcache,
        Opt_fscache_uniq,
+       Opt_local_lock,
 
        /* Special mount options */
        Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -171,6 +172,7 @@ static const match_table_t nfs_mount_option_tokens = {
 
        { Opt_lookupcache, "lookupcache=%s" },
        { Opt_fscache_uniq, "fsc=%s" },
+       { Opt_local_lock, "local_lock=%s" },
 
        { Opt_err, NULL }
 };
@@ -236,6 +238,22 @@ static match_table_t nfs_lookupcache_tokens = {
        { Opt_lookupcache_err, NULL }
 };
 
+enum {
+       Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_posix,
+       Opt_local_lock_none,
+
+       Opt_local_lock_err
+};
+
+static match_table_t nfs_local_lock_tokens = {
+       { Opt_local_lock_all, "all" },
+       { Opt_local_lock_flock, "flock" },
+       { Opt_local_lock_posix, "posix" },
+       { Opt_local_lock_none, "none" },
+
+       { Opt_local_lock_err, NULL }
+};
+
 
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
@@ -622,6 +640,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        const struct proc_nfs_info *nfs_infop;
        struct nfs_client *clp = nfss->nfs_client;
        u32 version = clp->rpc_ops->version;
+       int local_flock, local_fcntl;
 
        seq_printf(m, ",vers=%u", version);
        seq_printf(m, ",rsize=%u", nfss->rsize);
@@ -670,6 +689,18 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                else
                        seq_printf(m, ",lookupcache=pos");
        }
+
+       local_flock = nfss->flags & NFS_MOUNT_LOCAL_FLOCK;
+       local_fcntl = nfss->flags & NFS_MOUNT_LOCAL_FCNTL;
+
+       if (!local_flock && !local_fcntl)
+               seq_printf(m, ",local_lock=none");
+       else if (local_flock && local_fcntl)
+               seq_printf(m, ",local_lock=all");
+       else if (local_flock)
+               seq_printf(m, ",local_lock=flock");
+       else
+               seq_printf(m, ",local_lock=posix");
 }
 
 /*
@@ -1017,9 +1048,13 @@ static int nfs_parse_mount_options(char *raw,
                        break;
                case Opt_lock:
                        mnt->flags &= ~NFS_MOUNT_NONLM;
+                       mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+                                       NFS_MOUNT_LOCAL_FCNTL);
                        break;
                case Opt_nolock:
                        mnt->flags |= NFS_MOUNT_NONLM;
+                       mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+                                      NFS_MOUNT_LOCAL_FCNTL);
                        break;
                case Opt_v2:
                        mnt->flags &= ~NFS_MOUNT_VER3;
@@ -1420,6 +1455,34 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->fscache_uniq = string;
                        mnt->options |= NFS_OPTION_FSCACHE;
                        break;
+               case Opt_local_lock:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string, nfs_local_lock_tokens,
+                                       args);
+                       kfree(string);
+                       switch (token) {
+                       case Opt_local_lock_all:
+                               mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+                                              NFS_MOUNT_LOCAL_FCNTL);
+                               break;
+                       case Opt_local_lock_flock:
+                               mnt->flags |= NFS_MOUNT_LOCAL_FLOCK;
+                               break;
+                       case Opt_local_lock_posix:
+                               mnt->flags |= NFS_MOUNT_LOCAL_FCNTL;
+                               break;
+                       case Opt_local_lock_none:
+                               mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+                                               NFS_MOUNT_LOCAL_FCNTL);
+                               break;
+                       default:
+                               dfprintk(MOUNT, "NFS:   invalid "
+                                               "local_lock argument\n");
+                               return 0;
+                       };
+                       break;
 
                /*
                 * Special options
@@ -1825,6 +1888,12 @@ static int nfs_validate_mount_data(void *options,
                if (!args->nfs_server.hostname)
                        goto out_nomem;
 
+               if (!(data->flags & NFS_MOUNT_NONLM))
+                       args->flags &= ~(NFS_MOUNT_LOCAL_FLOCK|
+                                        NFS_MOUNT_LOCAL_FCNTL);
+               else
+                       args->flags |= (NFS_MOUNT_LOCAL_FLOCK|
+                                       NFS_MOUNT_LOCAL_FCNTL);
                /*
                 * The legacy version 6 binary mount data from userspace has a
                 * field used only to transport selinux information into the
@@ -2441,7 +2510,8 @@ static void nfs4_fill_super(struct super_block *sb)
 
 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
 {
-       args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3);
+       args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
+                        NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
 }
 
 static int nfs4_validate_text_mount_data(void *options,
index ad4d2e7..978aaeb 100644 (file)
@@ -32,6 +32,7 @@ static ctl_table nfs_cb_sysctls[] = {
                .extra1 = (int *)&nfs_set_port_min,
                .extra2 = (int *)&nfs_set_port_max,
        },
+#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
        {
                .procname = "idmap_cache_timeout",
                .data = &nfs_idmap_cache_timeout,
@@ -39,6 +40,7 @@ static ctl_table nfs_cb_sysctls[] = {
                .mode = 0644,
                .proc_handler = proc_dointvec_jiffies,
        },
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
 #endif
        {
                .procname       = "nfs_mountpoint_timeout",
index 2f84ada..9a16bad 100644 (file)
 #include <linux/nfs_fs.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/namei.h>
 
 #include "internal.h"
 #include "nfs4_fs.h"
+#include "iostat.h"
+#include "delegation.h"
 
 struct nfs_unlinkdata {
        struct hlist_node list;
@@ -244,7 +247,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
  * @dir: parent directory of dentry
  * @dentry: dentry to unlink
  */
-int
+static int
 nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct nfs_unlinkdata *data;
@@ -259,7 +262,6 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
                status = PTR_ERR(data->cred);
                goto out_free;
        }
-       data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        data->res.dir_attr = &data->dir_attr;
 
        status = -EBUSY;
@@ -303,3 +305,256 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
        if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
                nfs_free_unlinkdata(data);
 }
+
+/* Cancel a queued async unlink. Called when a sillyrename run fails. */
+static void
+nfs_cancel_async_unlink(struct dentry *dentry)
+{
+       spin_lock(&dentry->d_lock);
+       if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
+               struct nfs_unlinkdata *data = dentry->d_fsdata;
+
+               dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
+               spin_unlock(&dentry->d_lock);
+               nfs_free_unlinkdata(data);
+               return;
+       }
+       spin_unlock(&dentry->d_lock);
+}
+
+struct nfs_renamedata {
+       struct nfs_renameargs   args;
+       struct nfs_renameres    res;
+       struct rpc_cred         *cred;
+       struct inode            *old_dir;
+       struct dentry           *old_dentry;
+       struct nfs_fattr        old_fattr;
+       struct inode            *new_dir;
+       struct dentry           *new_dentry;
+       struct nfs_fattr        new_fattr;
+};
+
+/**
+ * nfs_async_rename_done - Sillyrename post-processing
+ * @task: rpc_task of the sillyrename
+ * @calldata: nfs_renamedata for the sillyrename
+ *
+ * Do the directory attribute updates and the d_move
+ */
+static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs_renamedata *data = calldata;
+       struct inode *old_dir = data->old_dir;
+       struct inode *new_dir = data->new_dir;
+
+       if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
+               nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client);
+               return;
+       }
+
+       if (task->tk_status != 0) {
+               nfs_cancel_async_unlink(data->old_dentry);
+               return;
+       }
+
+       nfs_set_verifier(data->old_dentry, nfs_save_change_attribute(old_dir));
+       d_move(data->old_dentry, data->new_dentry);
+}
+
+/**
+ * nfs_async_rename_release - Release the sillyrename data.
+ * @calldata: the struct nfs_renamedata to be released
+ */
+static void nfs_async_rename_release(void *calldata)
+{
+       struct nfs_renamedata   *data = calldata;
+       struct super_block *sb = data->old_dir->i_sb;
+
+       if (data->old_dentry->d_inode)
+               nfs_mark_for_revalidate(data->old_dentry->d_inode);
+
+       dput(data->old_dentry);
+       dput(data->new_dentry);
+       iput(data->old_dir);
+       iput(data->new_dir);
+       nfs_sb_deactive(sb);
+       put_rpccred(data->cred);
+       kfree(data);
+}
+
+#if defined(CONFIG_NFS_V4_1)
+static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
+{
+       struct nfs_renamedata *data = calldata;
+       struct nfs_server *server = NFS_SERVER(data->old_dir);
+
+       if (nfs4_setup_sequence(server, &data->args.seq_args,
+                               &data->res.seq_res, 1, task))
+               return;
+       rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+static const struct rpc_call_ops nfs_rename_ops = {
+       .rpc_call_done = nfs_async_rename_done,
+       .rpc_release = nfs_async_rename_release,
+#if defined(CONFIG_NFS_V4_1)
+       .rpc_call_prepare = nfs_rename_prepare,
+#endif /* CONFIG_NFS_V4_1 */
+};
+
+/**
+ * nfs_async_rename - perform an asynchronous rename operation
+ * @old_dir: directory that currently holds the dentry to be renamed
+ * @new_dir: target directory for the rename
+ * @old_dentry: original dentry to be renamed
+ * @new_dentry: dentry to which the old_dentry should be renamed
+ *
+ * It's expected that valid references to the dentries and inodes are held
+ */
+static struct rpc_task *
+nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
+                struct dentry *old_dentry, struct dentry *new_dentry)
+{
+       struct nfs_renamedata *data;
+       struct rpc_message msg = { };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_message = &msg,
+               .callback_ops = &nfs_rename_ops,
+               .workqueue = nfsiod_workqueue,
+               .rpc_client = NFS_CLIENT(old_dir),
+               .flags = RPC_TASK_ASYNC,
+       };
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return ERR_PTR(-ENOMEM);
+       task_setup_data.callback_data = data,
+
+       data->cred = rpc_lookup_cred();
+       if (IS_ERR(data->cred)) {
+               struct rpc_task *task = ERR_CAST(data->cred);
+               kfree(data);
+               return task;
+       }
+
+       msg.rpc_argp = &data->args;
+       msg.rpc_resp = &data->res;
+       msg.rpc_cred = data->cred;
+
+       /* set up nfs_renamedata */
+       data->old_dir = old_dir;
+       atomic_inc(&old_dir->i_count);
+       data->new_dir = new_dir;
+       atomic_inc(&new_dir->i_count);
+       data->old_dentry = dget(old_dentry);
+       data->new_dentry = dget(new_dentry);
+       nfs_fattr_init(&data->old_fattr);
+       nfs_fattr_init(&data->new_fattr);
+
+       /* set up nfs_renameargs */
+       data->args.old_dir = NFS_FH(old_dir);
+       data->args.old_name = &old_dentry->d_name;
+       data->args.new_dir = NFS_FH(new_dir);
+       data->args.new_name = &new_dentry->d_name;
+
+       /* set up nfs_renameres */
+       data->res.old_fattr = &data->old_fattr;
+       data->res.new_fattr = &data->new_fattr;
+
+       nfs_sb_active(old_dir->i_sb);
+
+       NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
+
+       return rpc_run_task(&task_setup_data);
+}
+
+/**
+ * nfs_sillyrename - Perform a silly-rename of a dentry
+ * @dir: inode of directory that contains dentry
+ * @dentry: dentry to be sillyrenamed
+ *
+ * NFSv2/3 is stateless and the server doesn't know when the client is
+ * holding a file open. To prevent application problems when a file is
+ * unlinked while it's still open, the client performs a "silly-rename".
+ * That is, it renames the file to a hidden file in the same directory,
+ * and only performs the unlink once the last reference to it is put.
+ *
+ * The final cleanup is done during dentry_iput.
+ */
+int
+nfs_sillyrename(struct inode *dir, struct dentry *dentry)
+{
+       static unsigned int sillycounter;
+       const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
+       const int      countersize = sizeof(sillycounter)*2;
+       const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
+       char           silly[slen+1];
+       struct dentry *sdentry;
+       struct rpc_task *task;
+       int            error = -EIO;
+
+       dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               atomic_read(&dentry->d_count));
+       nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
+
+       /*
+        * We don't allow a dentry to be silly-renamed twice.
+        */
+       error = -EBUSY;
+       if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
+               goto out;
+
+       sprintf(silly, ".nfs%*.*Lx",
+               fileidsize, fileidsize,
+               (unsigned long long)NFS_FILEID(dentry->d_inode));
+
+       /* Return delegation in anticipation of the rename */
+       nfs_inode_return_delegation(dentry->d_inode);
+
+       sdentry = NULL;
+       do {
+               char *suffix = silly + slen - countersize;
+
+               dput(sdentry);
+               sillycounter++;
+               sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
+
+               dfprintk(VFS, "NFS: trying to rename %s to %s\n",
+                               dentry->d_name.name, silly);
+
+               sdentry = lookup_one_len(silly, dentry->d_parent, slen);
+               /*
+                * N.B. Better to return EBUSY here ... it could be
+                * dangerous to delete the file while it's in use.
+                */
+               if (IS_ERR(sdentry))
+                       goto out;
+       } while (sdentry->d_inode != NULL); /* need negative lookup */
+
+       /* queue unlink first. Can't do this from rpc_release as it
+        * has to allocate memory
+        */
+       error = nfs_async_unlink(dir, dentry);
+       if (error)
+               goto out_dput;
+
+       /* run the rename task, undo unlink if it fails */
+       task = nfs_async_rename(dir, dir, dentry, sdentry);
+       if (IS_ERR(task)) {
+               error = -EBUSY;
+               nfs_cancel_async_unlink(dentry);
+               goto out_dput;
+       }
+
+       /* wait for the RPC task to complete, unless a SIGKILL intervenes */
+       error = rpc_wait_for_completion_task(task);
+       if (error == 0)
+               error = task->tk_status;
+       rpc_put_task(task);
+out_dput:
+       dput(sdentry);
+out:
+       return error;
+}
index 874972d..605e292 100644 (file)
@@ -55,7 +55,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
        if (p) {
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        }
        return p;
 }
@@ -75,7 +74,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
                p->npages = pagecount;
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
                if (pagecount <= ARRAY_SIZE(p->page_array))
                        p->pagevec = p->page_array;
                else {
@@ -1433,15 +1431,17 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
        int flags = FLUSH_SYNC;
        int ret = 0;
 
-       /* Don't commit yet if this is a non-blocking flush and there are
-        * lots of outstanding writes for this mapping.
-        */
-       if (wbc->sync_mode == WB_SYNC_NONE &&
-           nfsi->ncommit <= (nfsi->npages >> 1))
-               goto out_mark_dirty;
+       if (wbc->sync_mode == WB_SYNC_NONE) {
+               /* Don't commit yet if this is a non-blocking flush and there
+                * are a lot of outstanding writes for this mapping.
+                */
+               if (nfsi->ncommit <= (nfsi->npages >> 1))
+                       goto out_mark_dirty;
 
-       if (wbc->nonblocking || wbc->for_background)
+               /* don't wait for the COMMIT response */
                flags = 0;
+       }
+
        ret = nfs_commit_inode(inode, flags);
        if (ret >= 0) {
                if (wbc->sync_mode == WB_SYNC_NONE) {
index b81bfc0..0a8b0ad 100644 (file)
@@ -365,25 +365,17 @@ struct device_type part_type = {
 static void delete_partition_rcu_cb(struct rcu_head *head)
 {
        struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
-       struct gendisk *disk = part_to_disk(part);
-       struct request_queue *q = disk->queue;
-       unsigned long flags;
 
        part->start_sect = 0;
        part->nr_sects = 0;
        part_stat_set_all(part, 0);
        put_device(part_to_dev(part));
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       elv_quiesce_end(q);
-       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 void delete_partition(struct gendisk *disk, int partno)
 {
        struct disk_part_tbl *ptbl = disk->part_tbl;
        struct hd_struct *part;
-       struct request_queue *q = disk->queue;
 
        if (partno >= ptbl->len)
                return;
@@ -398,10 +390,6 @@ void delete_partition(struct gendisk *disk, int partno)
        kobject_put(part->holder_dir);
        device_del(part_to_dev(part));
 
-       spin_lock_irq(q->queue_lock);
-       elv_quiesce_start(q);
-       spin_unlock_irq(q->queue_lock);
-
        call_rcu(&part->rcu_head, delete_partition_rcu_cb);
 }
 
index f4d4120..6f3c6ae 100644 (file)
@@ -108,7 +108,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_CLEAR_DIRTY
-#define page_clear_dirty(page)         do { } while (0)
+#define page_clear_dirty(page, mapped) do { } while (0)
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_TEST_DIRTY
diff --git a/include/linux/bfin_mac.h b/include/linux/bfin_mac.h
new file mode 100644 (file)
index 0000000..904dec7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Blackfin On-Chip MAC Driver
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _LINUX_BFIN_MAC_H_
+#define _LINUX_BFIN_MAC_H_
+
+#include <linux/phy.h>
+
+struct bfin_phydev_platform_data {
+       unsigned short addr;
+       int irq;
+};
+
+struct bfin_mii_bus_platform_data {
+       int phydev_number;
+       struct bfin_phydev_platform_data *phydev_data;
+       const unsigned short *mac_peripherals;
+       int phy_mode;
+       unsigned int phy_mask;
+};
+
+#endif
index 009b80e..646b462 100644 (file)
@@ -115,7 +115,6 @@ struct request {
        void *elevator_private3;
 
        struct gendisk *rq_disk;
-       struct hd_struct *part;
        unsigned long start_time;
 #ifdef CONFIG_BLK_CGROUP
        unsigned long long start_time_ns;
index b3ef0c4..e35071b 100644 (file)
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/spinlock.h>
 #include <linux/coda.h>
 
 /*
  * coda fs inode data
+ * c_lock protects accesses to c_flags, c_mapcount, c_cached_epoch, c_uid and
+ * c_cached_perm.
+ * vfs_inode is set only when the inode is created and never changes.
+ * c_fid is set when the inode is created and should be considered immutable.
  */
 struct coda_inode_info {
-        struct CodaFid    c_fid;       /* Coda identifier */
-        u_short                   c_flags;     /* flags (see below) */
-       struct list_head   c_cilist;    /* list of all coda inodes */
+       struct CodaFid     c_fid;       /* Coda identifier */
+       u_short            c_flags;     /* flags (see below) */
        unsigned int       c_mapcount;  /* nr of times this inode is mapped */
        unsigned int       c_cached_epoch; /* epoch for cached permissions */
        vuid_t             c_uid;       /* fsuid for cached permissions */
-        unsigned int       c_cached_perm; /* cached access permissions */
+       unsigned int       c_cached_perm; /* cached access permissions */
+       spinlock_t         c_lock;
        struct inode       vfs_inode;
 };
 
index dcc228a..2e914d0 100644 (file)
@@ -89,7 +89,11 @@ static __inline__ char *coda_i2s(struct inode *inode)
 /* this will not zap the inode away */
 static __inline__ void coda_flag_inode(struct inode *inode, int flag)
 {
-       ITOC(inode)->c_flags |= flag;
+       struct coda_inode_info *cii = ITOC(inode);
+
+       spin_lock(&cii->c_lock);
+       cii->c_flags |= flag;
+       spin_unlock(&cii->c_lock);
 }              
 
 #endif
index 284b520..72f2d2f 100644 (file)
@@ -8,6 +8,7 @@
 
 #ifdef __KERNEL__
 #include <linux/backing-dev.h>
+#include <linux/mutex.h>
 
 struct kstatfs;
 
@@ -20,6 +21,7 @@ struct venus_comm {
        int                 vc_inuse;
        struct super_block *vc_sb;
        struct backing_dev_info bdi;
+       struct mutex        vc_mutex;
 };
 
 
@@ -63,7 +65,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
                 unsigned int cmd, struct PioctlData *data);
-int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
+int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out);
 int venus_fsync(struct super_block *sb, struct CodaFid *fid);
 int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
 
index 7c930db..5dd4285 100644 (file)
 #include <linux/if_ether.h>
 #include <linux/memory.h>
 
+struct mdio_platform_data {
+       unsigned long           bus_freq;
+};
+
 struct emac_platform_data {
        char mac_addr[ETH_ALEN];
        u32 ctrl_reg_offset;
        u32 ctrl_mod_reg_offset;
        u32 ctrl_ram_offset;
        u32 hw_ram_addr;
-       u32 mdio_reg_offset;
        u32 ctrl_ram_size;
-       u32 phy_mask;
-       u32 mdio_max_freq;
+
+       /*
+        * phy_id can be one of the following:
+        *   - NULL             : use the first phy on the bus,
+        *   - ""               : force to 100/full, no mdio control
+        *   - "<bus>:<addr>"   : use the specified bus and phy
+        */
+       const char *phy_id;
+
        u8 rmii_en;
        u8 version;
        void (*interrupt_enable) (void);
index 80a0ece..4fd978e 100644 (file)
@@ -122,8 +122,6 @@ extern void elv_completed_request(struct request_queue *, struct request *);
 extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
 extern void elv_put_request(struct request_queue *, struct request *);
 extern void elv_drain_elevator(struct request_queue *);
-extern void elv_quiesce_start(struct request_queue *);
-extern void elv_quiesce_end(struct request_queue *);
 
 /*
  * io scheduler registration
index 361d1cc..b65a6f4 100644 (file)
@@ -53,9 +53,7 @@ struct gameport {
 #define to_gameport_port(d)    container_of(d, struct gameport, dev)
 
 struct gameport_driver {
-
-       void *private;
-       char *description;
+       const char *description;
 
        int (*connect)(struct gameport *, struct gameport_driver *drv);
        int (*reconnect)(struct gameport *);
index 557c392..7a7b9c1 100644 (file)
@@ -140,7 +140,6 @@ struct disk_part_tbl {
        struct rcu_head rcu_head;
        int len;
        struct hd_struct __rcu *last_lookup;
-       struct gendisk *disk;
        struct hd_struct __rcu *part[];
 };
 
diff --git a/include/linux/gpio-fan.h b/include/linux/gpio-fan.h
new file mode 100644 (file)
index 0000000..0966591
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * include/linux/gpio-fan.h
+ *
+ * Platform data structure for GPIO fan driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_GPIO_FAN_H
+#define __LINUX_GPIO_FAN_H
+
+struct gpio_fan_alarm {
+       unsigned        gpio;
+       unsigned        active_low;
+};
+
+struct gpio_fan_speed {
+       int rpm;
+       int ctrl_val;
+};
+
+struct gpio_fan_platform_data {
+       int                     num_ctrl;
+       unsigned                *ctrl;  /* fan control GPIOs. */
+       struct gpio_fan_alarm   *alarm; /* fan alarm GPIO. */
+       /*
+        * Speed conversion array: rpm from/to GPIO bit field.
+        * This array _must_ be sorted in ascending rpm order.
+        */
+       int                     num_speed;
+       struct gpio_fan_speed   *speed;
+};
+
+#endif /* __LINUX_GPIO_FAN_H */
index 6de90bf..4793d8a 100644 (file)
@@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
 extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
-       unsigned int    audio_mclk;
+       unsigned int audio_mclk; /* not used, will be removed */
+       unsigned int digimic_delay; /* in ms */
        unsigned int ramp_delay_value;
+       unsigned int offset_cncl_path;
+       unsigned int check_defaults:1;
+       unsigned int reset_registers:1;
        unsigned int hs_extmute:1;
        void (*set_hs_extmute)(int mute);
 };
index d6ae176..51af441 100644 (file)
@@ -34,7 +34,7 @@ struct input_event {
  * Protocol version.
  */
 
-#define EV_VERSION             0x010000
+#define EV_VERSION             0x010001
 
 /*
  * IOCTLs (0x00 - 0x7f)
@@ -56,25 +56,50 @@ struct input_absinfo {
        __s32 resolution;
 };
 
+/**
+ * struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
+ * @scancode: scancode represented in machine-endian form.
+ * @len: length of the scancode that resides in @scancode buffer.
+ * @index: index in the keymap, may be used instead of scancode
+ * @flags: allows to specify how kernel should handle the request. For
+ *     example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
+ *     should perform lookup in keymap by @index instead of @scancode
+ * @keycode: key code assigned to this scancode
+ *
+ * The structure is used to retrieve and modify keymap data. Users have
+ * option of performing lookup either by @scancode itself or by @index
+ * in keymap entry. EVIOCGKEYCODE will also return scancode or index
+ * (depending on which element was used to perform lookup).
+ */
+struct input_keymap_entry {
+#define INPUT_KEYMAP_BY_INDEX  (1 << 0)
+       __u8  flags;
+       __u8  len;
+       __u16 index;
+       __u32 keycode;
+       __u8  scancode[32];
+};
+
 #define EVIOCGVERSION          _IOR('E', 0x01, int)                    /* get driver version */
 #define EVIOCGID               _IOR('E', 0x02, struct input_id)        /* get device ID */
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
-#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+
+#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
+#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
 #define EVIOCGUNIQ(len)                _IOC(_IOC_READ, 'E', 0x08, len)         /* get unique identifier */
 
-#define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global keystate */
+#define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global key state */
 #define EVIOCGLED(len)         _IOC(_IOC_READ, 'E', 0x19, len)         /* get all LEDs */
 #define EVIOCGSND(len)         _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
 #define EVIOCGSW(len)          _IOC(_IOC_READ, 'E', 0x1b, len)         /* get all switch states */
 
 #define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
-#define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)             /* get abs value/limits */
-#define EVIOCSABS(abs)         _IOW('E', 0xc0 + abs, struct input_absinfo)             /* set abs value/limits */
+#define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)     /* get abs value/limits */
+#define EVIOCSABS(abs)         _IOW('E', 0xc0 + abs, struct input_absinfo)     /* set abs value/limits */
 
 #define EVIOCSFF               _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))   /* send a force effect to a force feedback device */
 #define EVIOCRMFF              _IOW('E', 0x81, int)                    /* Erase a force effect */
@@ -1088,13 +1113,13 @@ struct input_mt_slot {
  * @keycodemax: size of keycode table
  * @keycodesize: size of elements in keycode table
  * @keycode: map of scancodes to keycodes for this device
+ * @getkeycode: optional legacy method to retrieve current keymap.
  * @setkeycode: optional method to alter current keymap, used to implement
  *     sparse keymaps. If not supplied default mechanism will be used.
  *     The method is being called while holding event_lock and thus must
  *     not sleep
- * @getkeycode: optional method to retrieve current keymap. If not supplied
- *     default mechanism will be used. The method is being called while
- *     holding event_lock and thus must not sleep
+ * @getkeycode_new: transition method
+ * @setkeycode_new: transition method
  * @ff: force feedback structure associated with the device if device
  *     supports force feedback effects
  * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1168,10 +1193,16 @@ struct input_dev {
        unsigned int keycodemax;
        unsigned int keycodesize;
        void *keycode;
+
        int (*setkeycode)(struct input_dev *dev,
                          unsigned int scancode, unsigned int keycode);
        int (*getkeycode)(struct input_dev *dev,
                          unsigned int scancode, unsigned int *keycode);
+       int (*setkeycode_new)(struct input_dev *dev,
+                             const struct input_keymap_entry *ke,
+                             unsigned int *old_keycode);
+       int (*getkeycode_new)(struct input_dev *dev,
+                             struct input_keymap_entry *ke);
 
        struct ff_device *ff;
 
@@ -1478,10 +1509,12 @@ INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
 INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
 INPUT_GENERATE_ABS_ACCESSORS(res, resolution)
 
-int input_get_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int *keycode);
+int input_scancode_to_scalar(const struct input_keymap_entry *ke,
+                            unsigned int *scancode);
+
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke);
 int input_set_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int keycode);
+                     const struct input_keymap_entry *ke);
 
 extern struct class input_class;
 
diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h
new file mode 100644 (file)
index 0000000..e470d38
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#ifndef _BU21013_H
+#define _BU21013_H
+
+/**
+ * struct bu21013_platform_device - Handle the platform data
+ * @cs_en:     pointer to the cs enable function
+ * @cs_dis:    pointer to the cs disable function
+ * @irq_read_val:    pointer to read the pen irq value function
+ * @x_max_res: xmax resolution
+ * @y_max_res: ymax resolution
+ * @touch_x_max: touch x max
+ * @touch_y_max: touch y max
+ * @cs_pin: chip select pin
+ * @irq: irq pin
+ * @ext_clk: external clock flag
+ * @x_flip: x flip flag
+ * @y_flip: y flip flag
+ * @wakeup: wakeup flag
+ *
+ * This is used to handle the platform data
+ */
+struct bu21013_platform_device {
+       int (*cs_en)(int reset_pin);
+       int (*cs_dis)(int reset_pin);
+       int (*irq_read_val)(void);
+       int x_max_res;
+       int y_max_res;
+       int touch_x_max;
+       int touch_y_max;
+       unsigned int cs_pin;
+       unsigned int irq;
+       bool ext_clk;
+       bool x_flip;
+       bool y_flip;
+       bool wakeup;
+};
+
+#endif
index 0e8a346..d4292c8 100644 (file)
@@ -1,6 +1,52 @@
 #ifndef __LIS3LV02D_H_
 #define __LIS3LV02D_H_
 
+/**
+ * struct lis3lv02d_platform_data - lis3 chip family platform data
+ * @click_flags:       Click detection unit configuration
+ * @click_thresh_x:    Click detection unit x axis threshold
+ * @click_thresh_y:    Click detection unit y axis threshold
+ * @click_thresh_z:    Click detection unit z axis threshold
+ * @click_time_limit:  Click detection unit time parameter
+ * @click_latency:     Click detection unit latency parameter
+ * @click_window:      Click detection unit window parameter
+ * @irq_cfg:           On chip irq source and type configuration (click /
+ *                     data available / wake up, open drain, polarity)
+ * @irq_flags1:                Additional irq triggering flags for irq channel 0
+ * @irq_flags2:                Additional irq triggering flags for irq channel 1
+ * @duration1:         Wake up unit 1 duration parameter
+ * @duration2:         Wake up unit 2 duration parameter
+ * @wakeup_flags:      Wake up unit 1 flags
+ * @wakeup_thresh:     Wake up unit 1 threshold value
+ * @wakeup_flags2:     Wake up unit 2 flags
+ * @wakeup_thresh2:    Wake up unit 2 threshold value
+ * @hipass_ctrl:       High pass filter control (enable / disable, cut off
+ *                     frequency)
+ * @axis_x:            Sensor orientation remapping for x-axis
+ * @axis_y:            Sensor orientation remapping for y-axis
+ * @axis_z:            Sensor orientation remapping for z-axis
+ * @driver_features:   Enable bits for different features. Disabled by default
+ * @default_rate:      Default sampling rate. 0 means reset default
+ * @setup_resources:   Interrupt line setup call back function
+ * @release_resources: Interrupt line release call back function
+ * @st_min_limits[3]:  Selftest acceptance minimum values
+ * @st_max_limits[3]:  Selftest acceptance maximum values
+ * @irq2:              Irq line 2 number
+ *
+ * Platform data is used to setup the sensor chip. Meaning of the different
+ * chip features can be found from the data sheet. It is publicly available
+ * at www.st.com web pages. Currently the platform data is used
+ * only for the 8 bit device. The 8 bit device has two wake up / free fall
+ * detection units and click detection unit. There are plenty of ways to
+ * configure the chip which makes is quite hard to explain deeper meaning of
+ * the fields here. Behaviour of the detection blocks varies heavily depending
+ * on the configuration. For example, interrupt detection block can use high
+ * pass filtered data which makes it react to the changes in the acceleration.
+ * Irq_flags can be used to enable interrupt detection on the both edges.
+ * With proper chip configuration this produces interrupt when some trigger
+ * starts and when it goes away.
+ */
+
 struct lis3lv02d_platform_data {
        /* please note: the 'click' feature is only supported for
         * LIS[32]02DL variants of the chip and will be ignored for
@@ -36,7 +82,10 @@ struct lis3lv02d_platform_data {
 #define LIS3_IRQ_OPEN_DRAIN    (1 << 6)
 #define LIS3_IRQ_ACTIVE_LOW    (1 << 7)
        unsigned char irq_cfg;
-
+       unsigned char irq_flags1; /* Additional irq edge / level flags */
+       unsigned char irq_flags2; /* Additional irq edge / level flags */
+       unsigned char duration1;
+       unsigned char duration2;
 #define LIS3_WAKEUP_X_LO       (1 << 0)
 #define LIS3_WAKEUP_X_HI       (1 << 1)
 #define LIS3_WAKEUP_Y_LO       (1 << 2)
@@ -64,6 +113,10 @@ struct lis3lv02d_platform_data {
        s8 axis_x;
        s8 axis_y;
        s8 axis_z;
+#define LIS3_USE_REGULATOR_CTRL 0x01
+#define LIS3_USE_BLOCK_READ    0x02
+       u16 driver_features;
+       int default_rate;
        int (*setup_resources)(void);
        int (*release_resources)(void);
        /* Limits for selftest are specified in chip data sheet */
index d0edf7d..a46e430 100644 (file)
@@ -360,10 +360,13 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
+extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
 extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
 extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
 extern u64 nfs_compat_user_ino64(u64 fileid);
 extern void nfs_fattr_init(struct nfs_fattr *fattr);
+extern unsigned long nfs_inc_attr_generation_counter(void);
 
 extern struct nfs_fattr *nfs_alloc_fattr(void);
 
@@ -379,9 +382,12 @@ static inline void nfs_free_fhandle(const struct nfs_fh *fh)
        kfree(fh);
 }
 
+/*
+ * linux/fs/nfs/nfsroot.c
+ */
+extern int  nfs_root_data(char **root_device, char **root_data); /*__init*/
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-extern unsigned long nfs_inc_attr_generation_counter(void);
 
 /*
  * linux/fs/nfs/file.c
@@ -479,10 +485,10 @@ extern void nfs_release_automount_timer(void);
 /*
  * linux/fs/nfs/unlink.c
  */
-extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
 extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
 extern void nfs_block_sillyrename(struct dentry *dentry);
 extern void nfs_unblock_sillyrename(struct dentry *dentry);
+extern int  nfs_sillyrename(struct inode *dir, struct dentry *dentry);
 
 /*
  * linux/fs/nfs/write.c
@@ -584,10 +590,6 @@ nfs_fileid_to_ino_t(u64 fileid)
        return ino;
 }
 
-/* NFS root */
-
-extern void * nfs_root_data(void);
-
 #define nfs_wait_event(clnt, wq, condition)                            \
 ({                                                                     \
        int __retval = wait_event_killable(wq, condition);              \
index c82ee7c..5eef862 100644 (file)
@@ -124,6 +124,7 @@ struct nfs_server {
 
        struct nfs_fsid         fsid;
        __u64                   maxfilesize;    /* maximum file size */
+       struct timespec         time_delta;     /* smallest time granularity */
        unsigned long           mount_time;     /* when this fs was mounted */
        dev_t                   s_dev;          /* superblock dev numbers */
 
index 91a1c24..e8352dc 100644 (file)
@@ -66,13 +66,40 @@ struct idmap_msg {
 /* Forward declaration to make this header independent of others */
 struct nfs_client;
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+int nfs_idmap_init(void);
+void nfs_idmap_quit(void);
+
+static inline int nfs_idmap_new(struct nfs_client *clp)
+{
+       return 0;
+}
+
+static inline void nfs_idmap_delete(struct nfs_client *clp)
+{
+}
+
+#else /* CONFIG_NFS_USE_NEW_IDMAPPER not set */
+
+static inline int nfs_idmap_init(void)
+{
+       return 0;
+}
+
+static inline void nfs_idmap_quit(void)
+{
+}
+
 int nfs_idmap_new(struct nfs_client *);
 void nfs_idmap_delete(struct nfs_client *);
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
+
 int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *);
 int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(struct nfs_client *, __u32, char *);
-int nfs_map_gid_to_group(struct nfs_client *, __u32, char *);
+int nfs_map_uid_to_name(struct nfs_client *, __u32, char *, size_t);
+int nfs_map_gid_to_group(struct nfs_client *, __u32, char *, size_t);
 
 extern unsigned int nfs_idmap_cache_timeout;
 #endif /* __KERNEL__ */
index 5d59ae8..576bddd 100644 (file)
@@ -71,4 +71,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_NORESVPORT           0x40000
 #define NFS_MOUNT_LEGACY_INTERFACE     0x80000
 
+#define NFS_MOUNT_LOCAL_FLOCK  0x100000
+#define NFS_MOUNT_LOCAL_FCNTL  0x200000
+
 #endif
index fc46192..da7a130 100644 (file)
@@ -112,6 +112,7 @@ struct nfs_fsinfo {
        __u32                   wtmult; /* writes should be multiple of this */
        __u32                   dtpref; /* pref. readdir transfer size */
        __u64                   maxfilesize;
+       struct timespec         time_delta; /* server time granularity */
        __u32                   lease_time; /* in seconds */
 };
 
@@ -170,7 +171,7 @@ struct nfs4_sequence_args {
 
 struct nfs4_sequence_res {
        struct nfs4_session     *sr_session;
-       u8                      sr_slotid;      /* slot used to send request */
+       struct nfs4_slot        *sr_slot;       /* slot used to send request */
        int                     sr_status;      /* sequence operation status */
        unsigned long           sr_renewal_time;
        u32                     sr_status_flags;
@@ -400,6 +401,27 @@ struct nfs_removeres {
 };
 
 /*
+ * Common arguments to the rename call
+ */
+struct nfs_renameargs {
+       const struct nfs_fh             *old_dir;
+       const struct nfs_fh             *new_dir;
+       const struct qstr               *old_name;
+       const struct qstr               *new_name;
+       const u32                       *bitmask;
+       struct nfs4_sequence_args       seq_args;
+};
+
+struct nfs_renameres {
+       const struct nfs_server         *server;
+       struct nfs4_change_info         old_cinfo;
+       struct nfs_fattr                *old_fattr;
+       struct nfs4_change_info         new_cinfo;
+       struct nfs_fattr                *new_fattr;
+       struct nfs4_sequence_res        seq_res;
+};
+
+/*
  * Argument struct for decode_entry function
  */
 struct nfs_entry {
@@ -434,15 +456,6 @@ struct nfs_createargs {
        struct iattr *          sattr;
 };
 
-struct nfs_renameargs {
-       struct nfs_fh *         fromfh;
-       const char *            fromname;
-       unsigned int            fromlen;
-       struct nfs_fh *         tofh;
-       const char *            toname;
-       unsigned int            tolen;
-};
-
 struct nfs_setattrargs {
        struct nfs_fh *                 fh;
        nfs4_stateid                    stateid;
@@ -586,15 +599,6 @@ struct nfs3_mknodargs {
        dev_t                   rdev;
 };
 
-struct nfs3_renameargs {
-       struct nfs_fh *         fromfh;
-       const char *            fromname;
-       unsigned int            fromlen;
-       struct nfs_fh *         tofh;
-       const char *            toname;
-       unsigned int            tolen;
-};
-
 struct nfs3_linkargs {
        struct nfs_fh *         fromfh;
        struct nfs_fh *         tofh;
@@ -629,11 +633,6 @@ struct nfs3_readlinkargs {
        struct page **          pages;
 };
 
-struct nfs3_renameres {
-       struct nfs_fattr *      fromattr;
-       struct nfs_fattr *      toattr;
-};
-
 struct nfs3_linkres {
        struct nfs_fattr *      dir_attr;
        struct nfs_fattr *      fattr;
@@ -780,6 +779,7 @@ struct nfs4_readdir_arg {
        struct page **                  pages;  /* zero-copy data */
        unsigned int                    pgbase; /* zero-copy data */
        const u32 *                     bitmask;
+       int                             plus;
        struct nfs4_sequence_args       seq_args;
 };
 
@@ -801,24 +801,6 @@ struct nfs4_readlink_res {
        struct nfs4_sequence_res        seq_res;
 };
 
-struct nfs4_rename_arg {
-       const struct nfs_fh *           old_dir;
-       const struct nfs_fh *           new_dir;
-       const struct qstr *             old_name;
-       const struct qstr *             new_name;
-       const u32 *                     bitmask;
-       struct nfs4_sequence_args       seq_args;
-};
-
-struct nfs4_rename_res {
-       const struct nfs_server *       server;
-       struct nfs4_change_info         old_cinfo;
-       struct nfs_fattr *              old_fattr;
-       struct nfs4_change_info         new_cinfo;
-       struct nfs_fattr *              new_fattr;
-       struct nfs4_sequence_res        seq_res;
-};
-
 #define NFS4_SETCLIENTID_NAMELEN       (127)
 struct nfs4_setclientid {
        const nfs4_verifier *           sc_verifier;
@@ -1032,19 +1014,21 @@ struct nfs_rpc_ops {
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);
        int     (*create)  (struct inode *, struct dentry *,
-                           struct iattr *, int, struct nameidata *);
+                           struct iattr *, int, struct nfs_open_context *);
        int     (*remove)  (struct inode *, struct qstr *);
        void    (*unlink_setup)  (struct rpc_message *, struct inode *dir);
        int     (*unlink_done) (struct rpc_task *, struct inode *);
        int     (*rename)  (struct inode *, struct qstr *,
                            struct inode *, struct qstr *);
+       void    (*rename_setup)  (struct rpc_message *msg, struct inode *dir);
+       int     (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
        int     (*link)    (struct inode *, struct inode *, struct qstr *);
        int     (*symlink) (struct inode *, struct dentry *, struct page *,
                            unsigned int, struct iattr *);
        int     (*mkdir)   (struct inode *, struct dentry *, struct iattr *);
        int     (*rmdir)   (struct inode *, struct qstr *);
        int     (*readdir) (struct dentry *, struct rpc_cred *,
-                           u64, struct page *, unsigned int, int);
+                           u64, struct page **, unsigned int, int);
        int     (*mknod)   (struct inode *, struct dentry *, struct iattr *,
                            dev_t);
        int     (*statfs)  (struct nfs_server *, struct nfs_fh *,
@@ -1054,7 +1038,7 @@ struct nfs_rpc_ops {
        int     (*pathconf) (struct nfs_server *, struct nfs_fh *,
                             struct nfs_pathconf *);
        int     (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
-       __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus);
+       __be32 *(*decode_dirent)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int plus);
        void    (*read_setup)   (struct nfs_read_data *, struct rpc_message *);
        int     (*read_done)  (struct rpc_task *, struct nfs_read_data *);
        void    (*write_setup)  (struct nfs_write_data *, struct rpc_message *);
@@ -1065,6 +1049,10 @@ struct nfs_rpc_ops {
        int     (*lock_check_bounds)(const struct file_lock *);
        void    (*clear_acl_cache)(struct inode *);
        void    (*close_context)(struct nfs_open_context *ctx, int);
+       struct inode * (*open_context) (struct inode *dir,
+                               struct nfs_open_context *ctx,
+                               int open_flags,
+                               struct iattr *iattr);
 };
 
 /*
index 835f85e..975d347 100644 (file)
@@ -27,20 +27,19 @@ static inline int of_driver_match_device(const struct device *dev,
 extern struct platform_device *of_dev_get(struct platform_device *dev);
 extern void of_dev_put(struct platform_device *dev);
 
+extern int of_device_add(struct platform_device *pdev);
 extern int of_device_register(struct platform_device *ofdev);
 extern void of_device_unregister(struct platform_device *ofdev);
-extern void of_release_dev(struct device *dev);
-
-static inline void of_device_free(struct platform_device *dev)
-{
-       of_release_dev(&dev->dev);
-}
 
 extern ssize_t of_device_get_modalias(struct device *dev,
                                        char *str, ssize_t len);
 
 extern int of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 
+static inline void of_device_node_put(struct device *dev)
+{
+       of_node_put(dev->of_node);
+}
 
 #else /* CONFIG_OF_DEVICE */
 
@@ -56,6 +55,8 @@ static inline int of_device_uevent(struct device *dev,
        return -ENODEV;
 }
 
+static inline void of_device_node_put(struct device *dev) { }
+
 #endif /* CONFIG_OF_DEVICE */
 
 #endif /* _LINUX_OF_DEVICE_H */
index 71e1a91..7bbf5b3 100644 (file)
@@ -72,7 +72,7 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
                                 unsigned long *size);
 extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern unsigned long of_get_flat_dt_root(void);
-extern void early_init_dt_scan_chosen_arch(unsigned long node);
+
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
                                     int depth, void *data);
 extern void early_init_dt_check_for_initrd(unsigned long node);
index 5929781..109e013 100644 (file)
@@ -5,6 +5,7 @@
 struct of_irq;
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
 
@@ -64,6 +65,9 @@ extern unsigned int irq_create_of_mapping(struct device_node *controller,
                                          unsigned int intsize);
 extern int of_irq_to_resource(struct device_node *dev, int index,
                              struct resource *r);
+extern int of_irq_count(struct device_node *dev);
+extern int of_irq_to_resource_table(struct device_node *dev,
+               struct resource *res, int nr_irqs);
 
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
diff --git a/include/linux/of_pdt.h b/include/linux/of_pdt.h
new file mode 100644 (file)
index 0000000..c65a18a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Definitions for building a device tree by calling into the
+ * Open Firmware PROM.
+ *
+ * Copyright (C) 2010  Andres Salomon <dilinger@queued.net>
+ *
+ * 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 _LINUX_OF_PDT_H
+#define _LINUX_OF_PDT_H
+
+/* overridable operations for calling into the PROM */
+struct of_pdt_ops {
+       /*
+        * buf should be 32 bytes; return 0 on success.
+        * If prev is NULL, the first property will be returned.
+        */
+       int (*nextprop)(phandle node, char *prev, char *buf);
+
+       /* for both functions, return proplen on success; -1 on error */
+       int (*getproplen)(phandle node, const char *prop);
+       int (*getproperty)(phandle node, const char *prop, char *buf,
+                       int bufsize);
+
+       /* phandles are 0 if no child or sibling exists */
+       phandle (*getchild)(phandle parent);
+       phandle (*getsibling)(phandle node);
+
+       /* return 0 on success; fill in 'len' with number of bytes in path */
+       int (*pkg2path)(phandle node, char *buf, const int buflen, int *len);
+};
+
+extern void *prom_early_alloc(unsigned long size);
+
+/* for building the device tree */
+extern void of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops);
+
+extern void (*of_pdt_build_more)(struct device_node *dp,
+               struct device_node ***nextp);
+
+#endif /* _LINUX_OF_PDT_H */
index 6fa3178..5f38c46 100644 (file)
@@ -310,7 +310,7 @@ static inline void SetPageUptodate(struct page *page)
 {
 #ifdef CONFIG_S390
        if (!test_and_set_bit(PG_uptodate, &page->flags))
-               page_clear_dirty(page);
+               page_clear_dirty(page, 0);
 #else
        /*
         * Memory barrier must be issued before setting the PG_uptodate bit,
index d278dd9..b4c3d1b 100644 (file)
 
 #define PCI_VENDOR_ID_SILAN            0x1904
 
+#define PCI_VENDOR_ID_RENESAS          0x1912
+#define PCI_DEVICE_ID_RENESAS_SH7781   0x0001
+#define PCI_DEVICE_ID_RENESAS_SH7780   0x0002
+#define PCI_DEVICE_ID_RENESAS_SH7763   0x0004
+#define PCI_DEVICE_ID_RENESAS_SH7785   0x0007
+#define PCI_DEVICE_ID_RENESAS_SH7786   0x0010
+
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
index 99e5994..212eb4c 100644 (file)
 /* High Speed UART for Medfield */
 #define PORT_MFD       95
 
+/* TI OMAP-UART */
+#define PORT_OMAP      96
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
index b555256..e26f478 100644 (file)
@@ -41,7 +41,9 @@ struct serio {
        int (*start)(struct serio *);
        void (*stop)(struct serio *);
 
-       struct serio *parent, *child;
+       struct serio *parent;
+       struct list_head child_node;    /* Entry in parent->children list */
+       struct list_head children;
        unsigned int depth;             /* level of nesting in serio hierarchy */
 
        struct serio_driver *drv;       /* accessed from interrupt, must be protected by serio->lock and serio->sem */
@@ -54,10 +56,9 @@ struct serio {
 #define to_serio_port(d)       container_of(d, struct serio, dev)
 
 struct serio_driver {
-       void *private;
-       char *description;
+       const char *description;
 
-       struct serio_device_id *id_table;
+       const struct serio_device_id *id_table;
        bool manual_bind;
 
        void (*write_wakeup)(struct serio *);
@@ -197,5 +198,6 @@ static inline void serio_continue_rx(struct serio *serio)
 #define SERIO_W8001    0x39
 #define SERIO_DYNAPRO  0x3a
 #define SERIO_HAMPSHIRE        0x3b
+#define SERIO_PS2MULT  0x3c
 
 #endif
index 875ce50..4dca992 100644 (file)
@@ -4,11 +4,20 @@
 #include <linux/list.h>
 #include <linux/seq_file.h>
 #include <linux/cpufreq.h>
+#include <linux/types.h>
+#include <linux/kref.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
 struct clk;
 
+struct clk_mapping {
+       phys_addr_t             phys;
+       void __iomem            *base;
+       unsigned long           len;
+       struct kref             ref;
+};
+
 struct clk_ops {
        void (*init)(struct clk *clk);
        int (*enable)(struct clk *clk);
@@ -21,9 +30,6 @@ struct clk_ops {
 
 struct clk {
        struct list_head        node;
-       const char              *name;
-       int                     id;
-
        struct clk              *parent;
        struct clk              **parent_table; /* list of parents to */
        unsigned short          parent_num;     /* choose between */
@@ -45,7 +51,9 @@ struct clk {
        unsigned long           arch_flags;
        void                    *priv;
        struct dentry           *dentry;
+       struct clk_mapping      *mapping;
        struct cpufreq_frequency_table *freq_table;
+       unsigned int            nr_freqs;
 };
 
 #define CLK_ENABLE_ON_INIT     (1 << 0)
@@ -111,6 +119,9 @@ int clk_rate_table_find(struct clk *clk,
                        struct cpufreq_frequency_table *freq_table,
                        unsigned long rate);
 
+long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
+                             unsigned int div_max, unsigned long rate);
+
 #define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags)       \
 {                                                                      \
        .parent         = _parent,                                      \
index 0d6cd38..b4f183a 100644 (file)
@@ -20,6 +20,12 @@ struct intc_group {
 
 #define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
 
+struct intc_subgroup {
+       unsigned long reg, reg_width;
+       intc_enum parent_id;
+       intc_enum enum_ids[32];
+};
+
 struct intc_mask_reg {
        unsigned long set_reg, clr_reg, reg_width;
        intc_enum enum_ids[32];
@@ -69,9 +75,12 @@ struct intc_hw_desc {
        unsigned int nr_sense_regs;
        struct intc_mask_reg *ack_regs;
        unsigned int nr_ack_regs;
+       struct intc_subgroup *subgroups;
+       unsigned int nr_subgroups;
 };
 
-#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+#define _INTC_ARRAY(a) a, a == NULL ? 0 : sizeof(a)/sizeof(*a)
+
 #define INTC_HW_DESC(vectors, groups, mask_regs,       \
                     prio_regs, sense_regs, ack_regs)   \
 {                                                      \
@@ -105,8 +114,11 @@ struct intc_desc symbol __initdata = {                                     \
                           prio_regs, sense_regs, ack_regs),            \
 }
 
-int __init register_intc_controller(struct intc_desc *desc);
+int register_intc_controller(struct intc_desc *desc);
+void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
 int intc_set_priority(unsigned int irq, unsigned int prio);
+int intc_irq_lookup(const char *chipname, intc_enum enum_id);
+void intc_finalize(void);
 
 #ifdef CONFIG_INTC_USERIMASK
 int register_intc_userimask(unsigned long addr);
index 07c08af..30cae70 100644 (file)
@@ -92,5 +92,6 @@ struct pinmux_info {
 };
 
 int register_pinmux(struct pinmux_info *pip);
+int unregister_pinmux(struct pinmux_info *pip);
 
 #endif /* __SH_PFC_H */
index 85f38a6..c83df09 100644 (file)
@@ -137,7 +137,6 @@ int         rpcb_register(u32, u32, int, unsigned short);
 int            rpcb_v4_register(const u32 program, const u32 version,
                                 const struct sockaddr *address,
                                 const char *netid);
-int            rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
 void           rpcb_getport_async(struct rpc_task *);
 
 void           rpc_call_start(struct rpc_task *);
index 35cf2e8..ab91d86 100644 (file)
@@ -108,6 +108,7 @@ void        xdr_encode_pages(struct xdr_buf *, struct page **, unsigned int,
                         unsigned int);
 void   xdr_inline_pages(struct xdr_buf *, unsigned int,
                         struct page **, unsigned int, unsigned int);
+void   xdr_terminate_string(struct xdr_buf *, const u32);
 
 static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
@@ -200,6 +201,7 @@ extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
                unsigned int base, unsigned int len);
 extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes);
 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
diff --git a/include/linux/wlp.h b/include/linux/wlp.h
deleted file mode 100644 (file)
index c76fe23..0000000
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * WiMedia Logical Link Control Protocol (WLP)
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Reinette Chatre <reinette.chatre@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * FIXME: docs
- *
- * - Does not (yet) include support for WLP control frames
- *   WLP Draft 0.99 [6.5].
- *
- *   A visual representation of the data structures.
- *
- *                              wssidB      wssidB
- *                               ^           ^
- *                               |           |
- *                              wssidA      wssidA
- *   wlp interface {             ^           ^
- *       ...                     |           |
- *       ...               ...  wssid      wssid ...
- *       wlp --- ...             |           |
- *   };          neighbors --> neighbA --> neighbB
- *               ...
- *               wss
- *               ...
- *               eda cache  --> neighborA --> neighborB --> neighborC ...
- */
-
-#ifndef __LINUX__WLP_H_
-#define __LINUX__WLP_H_
-
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/list.h>
-#include <linux/uwb.h>
-
-/**
- * WLP Protocol ID
- * WLP Draft 0.99 [6.2]
- *
- * The MUX header for all WLP frames
- */
-#define WLP_PROTOCOL_ID 0x0100
-
-/**
- * WLP Version
- * WLP version placed in the association frames (WLP 0.99 [6.6])
- */
-#define WLP_VERSION 0x10
-
-/**
- * Bytes needed to print UUID as string
- */
-#define WLP_WSS_UUID_STRSIZE 48
-
-/**
- * Bytes needed to print nonce as string
- */
-#define WLP_WSS_NONCE_STRSIZE 48
-
-
-/**
- * Size used for WLP name size
- *
- * The WSS name is set to 65 bytes, 1 byte larger than the maximum
- * allowed by the WLP spec. This is to have a null terminated string
- * for display to the user. A maximum of 64 bytes will still be used
- * when placing the WSS name field in association frames.
- */
-#define WLP_WSS_NAME_SIZE 65
-
-/**
- * Number of bytes added by WLP to data frame
- *
- * A data frame transmitted from a host will be placed in a Standard or
- * Abbreviated WLP frame. These have an extra 4 bytes of header (struct
- * wlp_frame_std_abbrv_hdr).
- * When the stack sends this data frame for transmission it needs to ensure
- * there is enough headroom for this header.
- */
-#define WLP_DATA_HLEN 4
-
-/**
- * State of device regarding WLP Service Set
- *
- * WLP_WSS_STATE_NONE: the host does not participate in any WSS
- * WLP_WSS_STATE_PART_ENROLLED: used as part of the enrollment sequence
- *                            ("Partial Enroll"). This state is used to
- *                            indicate the first part of enrollment that is
- *                            unsecure. If the WSS is unsecure then the
- *                            state will promptly go to WLP_WSS_STATE_ENROLLED,
- *                            if the WSS is not secure then the enrollment
- *                            procedure is a few more steps before we are
- *                            enrolled.
- * WLP_WSS_STATE_ENROLLED: the host is enrolled in a WSS
- * WLP_WSS_STATE_ACTIVE: WSS is activated
- * WLP_WSS_STATE_CONNECTED: host is connected to neighbor in WSS
- *
- */
-enum wlp_wss_state {
-       WLP_WSS_STATE_NONE = 0,
-       WLP_WSS_STATE_PART_ENROLLED,
-       WLP_WSS_STATE_ENROLLED,
-       WLP_WSS_STATE_ACTIVE,
-       WLP_WSS_STATE_CONNECTED,
-};
-
-/**
- * WSS Secure status
- * WLP 0.99 Table 6
- *
- * Set to one if the WSS is secure, zero if it is not secure
- */
-enum wlp_wss_sec_status {
-       WLP_WSS_UNSECURE = 0,
-       WLP_WSS_SECURE,
-};
-
-/**
- * WLP frame type
- * WLP Draft 0.99 [6.2 Table 1]
- */
-enum wlp_frame_type {
-       WLP_FRAME_STANDARD = 0,
-       WLP_FRAME_ABBREVIATED,
-       WLP_FRAME_CONTROL,
-       WLP_FRAME_ASSOCIATION,
-};
-
-/**
- * WLP Association Message Type
- * WLP Draft 0.99 [6.6.1.2 Table 8]
- */
-enum wlp_assoc_type {
-       WLP_ASSOC_D1 = 2,
-       WLP_ASSOC_D2 = 3,
-       WLP_ASSOC_M1 = 4,
-       WLP_ASSOC_M2 = 5,
-       WLP_ASSOC_M3 = 7,
-       WLP_ASSOC_M4 = 8,
-       WLP_ASSOC_M5 = 9,
-       WLP_ASSOC_M6 = 10,
-       WLP_ASSOC_M7 = 11,
-       WLP_ASSOC_M8 = 12,
-       WLP_ASSOC_F0 = 14,
-       WLP_ASSOC_E1 = 32,
-       WLP_ASSOC_E2 = 33,
-       WLP_ASSOC_C1 = 34,
-       WLP_ASSOC_C2 = 35,
-       WLP_ASSOC_C3 = 36,
-       WLP_ASSOC_C4 = 37,
-};
-
-/**
- * WLP Attribute Type
- * WLP Draft 0.99 [6.6.1 Table 6]
- */
-enum wlp_attr_type {
-       WLP_ATTR_AUTH           = 0x1005, /* Authenticator */
-       WLP_ATTR_DEV_NAME       = 0x1011, /* Device Name */
-       WLP_ATTR_DEV_PWD_ID     = 0x1012, /* Device Password ID */
-       WLP_ATTR_E_HASH1        = 0x1014, /* E-Hash1 */
-       WLP_ATTR_E_HASH2        = 0x1015, /* E-Hash2 */
-       WLP_ATTR_E_SNONCE1      = 0x1016, /* E-SNonce1 */
-       WLP_ATTR_E_SNONCE2      = 0x1017, /* E-SNonce2 */
-       WLP_ATTR_ENCR_SET       = 0x1018, /* Encrypted Settings */
-       WLP_ATTR_ENRL_NONCE     = 0x101A, /* Enrollee Nonce */
-       WLP_ATTR_KEYWRAP_AUTH   = 0x101E, /* Key Wrap Authenticator */
-       WLP_ATTR_MANUF          = 0x1021, /* Manufacturer */
-       WLP_ATTR_MSG_TYPE       = 0x1022, /* Message Type */
-       WLP_ATTR_MODEL_NAME     = 0x1023, /* Model Name */
-       WLP_ATTR_MODEL_NR       = 0x1024, /* Model Number */
-       WLP_ATTR_PUB_KEY        = 0x1032, /* Public Key */
-       WLP_ATTR_REG_NONCE      = 0x1039, /* Registrar Nonce */
-       WLP_ATTR_R_HASH1        = 0x103D, /* R-Hash1 */
-       WLP_ATTR_R_HASH2        = 0x103E, /* R-Hash2 */
-       WLP_ATTR_R_SNONCE1      = 0x103F, /* R-SNonce1 */
-       WLP_ATTR_R_SNONCE2      = 0x1040, /* R-SNonce2 */
-       WLP_ATTR_SERIAL         = 0x1042, /* Serial number */
-       WLP_ATTR_UUID_E         = 0x1047, /* UUID-E */
-       WLP_ATTR_UUID_R         = 0x1048, /* UUID-R */
-       WLP_ATTR_PRI_DEV_TYPE   = 0x1054, /* Primary Device Type */
-       WLP_ATTR_SEC_DEV_TYPE   = 0x1055, /* Secondary Device Type */
-       WLP_ATTR_PORT_DEV       = 0x1056, /* Portable Device */
-       WLP_ATTR_APP_EXT        = 0x1058, /* Application Extension */
-       WLP_ATTR_WLP_VER        = 0x2000, /* WLP Version */
-       WLP_ATTR_WSSID          = 0x2001, /* WSSID */
-       WLP_ATTR_WSS_NAME       = 0x2002, /* WSS Name */
-       WLP_ATTR_WSS_SEC_STAT   = 0x2003, /* WSS Secure Status */
-       WLP_ATTR_WSS_BCAST      = 0x2004, /* WSS Broadcast Address */
-       WLP_ATTR_WSS_M_KEY      = 0x2005, /* WSS Master Key */
-       WLP_ATTR_ACC_ENRL       = 0x2006, /* Accepting Enrollment */
-       WLP_ATTR_WSS_INFO       = 0x2007, /* WSS Information */
-       WLP_ATTR_WSS_SEL_MTHD   = 0x2008, /* WSS Selection Method */
-       WLP_ATTR_ASSC_MTHD_LIST = 0x2009, /* Association Methods List */
-       WLP_ATTR_SEL_ASSC_MTHD  = 0x200A, /* Selected Association Method */
-       WLP_ATTR_ENRL_HASH_COMM = 0x200B, /* Enrollee Hash Commitment */
-       WLP_ATTR_WSS_TAG        = 0x200C, /* WSS Tag */
-       WLP_ATTR_WSS_VIRT       = 0x200D, /* WSS Virtual EUI-48 */
-       WLP_ATTR_WLP_ASSC_ERR   = 0x200E, /* WLP Association Error */
-       WLP_ATTR_VNDR_EXT       = 0x200F, /* Vendor Extension */
-};
-
-/**
- * WLP Category ID of primary/secondary device
- * WLP Draft 0.99 [6.6.1.8 Table 12]
- */
-enum wlp_dev_category_id {
-       WLP_DEV_CAT_COMPUTER = 1,
-       WLP_DEV_CAT_INPUT,
-       WLP_DEV_CAT_PRINT_SCAN_FAX_COPIER,
-       WLP_DEV_CAT_CAMERA,
-       WLP_DEV_CAT_STORAGE,
-       WLP_DEV_CAT_INFRASTRUCTURE,
-       WLP_DEV_CAT_DISPLAY,
-       WLP_DEV_CAT_MULTIM,
-       WLP_DEV_CAT_GAMING,
-       WLP_DEV_CAT_TELEPHONE,
-       WLP_DEV_CAT_OTHER = 65535,
-};
-
-/**
- * WLP WSS selection method
- * WLP Draft 0.99 [6.6.1.6 Table 10]
- */
-enum wlp_wss_sel_mthd {
-       WLP_WSS_ENRL_SELECT = 1,        /* Enrollee selects */
-       WLP_WSS_REG_SELECT,             /* Registrar selects */
-};
-
-/**
- * WLP association error values
- * WLP Draft 0.99 [6.6.1.5 Table 9]
- */
-enum wlp_assc_error {
-       WLP_ASSOC_ERROR_NONE,
-       WLP_ASSOC_ERROR_AUTH,           /* Authenticator Failure */
-       WLP_ASSOC_ERROR_ROGUE,          /* Rogue activity suspected */
-       WLP_ASSOC_ERROR_BUSY,           /* Device busy */
-       WLP_ASSOC_ERROR_LOCK,           /* Setup Locked */
-       WLP_ASSOC_ERROR_NOT_READY,      /* Registrar not ready */
-       WLP_ASSOC_ERROR_INV,            /* Invalid WSS selection */
-       WLP_ASSOC_ERROR_MSG_TIME,       /* Message timeout */
-       WLP_ASSOC_ERROR_ENR_TIME,       /* Enrollment session timeout */
-       WLP_ASSOC_ERROR_PW,             /* Device password invalid */
-       WLP_ASSOC_ERROR_VER,            /* Unsupported version */
-       WLP_ASSOC_ERROR_INT,            /* Internal error */
-       WLP_ASSOC_ERROR_UNDEF,          /* Undefined error */
-       WLP_ASSOC_ERROR_NUM,            /* Numeric comparison failure */
-       WLP_ASSOC_ERROR_WAIT,           /* Waiting for user input */
-};
-
-/**
- * WLP Parameters
- * WLP 0.99 [7.7]
- */
-enum wlp_parameters {
-       WLP_PER_MSG_TIMEOUT = 15,       /* Seconds to wait for response to
-                                          association message. */
-};
-
-/**
- * WLP IE
- *
- * The WLP IE should be included in beacons by all devices.
- *
- * The driver can set only a few of the fields in this information element,
- * most fields are managed by the device self. When the driver needs to set
- * a field it will only provide values for the fields of interest, the rest
- * will be filled with zeroes. The fields of interest are:
- *
- * Element ID
- * Length
- * Capabilities (only to include WSSID Hash list length)
- * WSSID Hash List fields
- *
- * WLP 0.99 [6.7]
- *
- * Only the fields that will be used are detailed in this structure, rest
- * are not detailed or marked as "notused".
- */
-struct wlp_ie {
-       struct uwb_ie_hdr hdr;
-       __le16 capabilities;
-       __le16 cycle_param;
-       __le16 acw_anchor_addr;
-       u8 wssid_hash_list[];
-} __packed;
-
-static inline int wlp_ie_hash_length(struct wlp_ie *ie)
-{
-       return (le16_to_cpu(ie->capabilities) >> 12) & 0xf;
-}
-
-static inline void wlp_ie_set_hash_length(struct wlp_ie *ie, int hash_length)
-{
-       u16 caps = le16_to_cpu(ie->capabilities);
-       caps = (caps & ~(0xf << 12)) | (hash_length << 12);
-       ie->capabilities = cpu_to_le16(caps);
-}
-
-/**
- * WLP nonce
- * WLP Draft 0.99 [6.6.1 Table 6]
- *
- * A 128-bit random number often used (E-SNonce1, E-SNonce2, Enrollee
- * Nonce, Registrar Nonce, R-SNonce1, R-SNonce2). It is passed to HW so
- * it is packed.
- */
-struct wlp_nonce {
-       u8 data[16];
-} __packed;
-
-/**
- * WLP UUID
- * WLP Draft 0.99 [6.6.1 Table 6]
- *
- * Universally Unique Identifier (UUID) encoded as an octet string in the
- * order the octets are shown in string representation in RFC4122. A UUID
- * is often used (UUID-E, UUID-R, WSSID). It is passed to HW so it is packed.
- */
-struct wlp_uuid {
-       u8 data[16];
-} __packed;
-
-
-/**
- * Primary and secondary device type attributes
- * WLP Draft 0.99 [6.6.1.8]
- */
-struct wlp_dev_type {
-       enum wlp_dev_category_id category:16;
-       u8 OUI[3];
-       u8 OUIsubdiv;
-       __le16 subID;
-} __packed;
-
-/**
- * WLP frame header
- * WLP Draft 0.99 [6.2]
- */
-struct wlp_frame_hdr {
-       __le16 mux_hdr;                 /* WLP_PROTOCOL_ID */
-       enum wlp_frame_type type:8;
-} __packed;
-
-/**
- * WLP attribute field header
- * WLP Draft 0.99 [6.6.1]
- *
- * Header of each attribute found in an association frame
- */
-struct wlp_attr_hdr {
-       __le16 type;
-       __le16 length;
-} __packed;
-
-/**
- * Device information commonly used together
- *
- * Each of these device information elements has a specified range in which it
- * should fit (WLP 0.99 [Table 6]). This range provided in the spec does not
- * include the termination null '\0' character (when used in the
- * association protocol the attribute fields are accompanied
- * with a "length" field so the full range from the spec can be used for
- * the value). We thus allocate an extra byte to be able to store a string
- * of max length with a terminating '\0'.
- */
-struct wlp_device_info {
-       char name[33];
-       char model_name[33];
-       char manufacturer[65];
-       char model_nr[33];
-       char serial[33];
-       struct wlp_dev_type prim_dev_type;
-};
-
-/**
- * Macros for the WLP attributes
- *
- * There are quite a few attributes (total is 43). The attribute layout can be
- * in one of three categories: one value, an array, an enum forced to 8 bits.
- * These macros help with their definitions.
- */
-#define wlp_attr(type, name)                                           \
-struct wlp_attr_##name {                                               \
-       struct wlp_attr_hdr hdr;                                        \
-       type name;                                                      \
-} __packed;
-
-#define wlp_attr_array(type, name)                                     \
-struct wlp_attr_##name {                                               \
-       struct wlp_attr_hdr hdr;                                        \
-       type name[];                                                    \
-} __packed;
-
-/**
- * WLP association attribute fields
- * WLP Draft 0.99 [6.6.1 Table 6]
- *
- * Attributes appear in same order as the Table in the spec
- * FIXME Does not define all attributes yet
- */
-
-/* Device name: Friendly name of sending device */
-wlp_attr_array(u8, dev_name)
-
-/* Enrollee Nonce: Random number generated by enrollee for an enrollment
- * session */
-wlp_attr(struct wlp_nonce, enonce)
-
-/* Manufacturer name: Name of manufacturer of the sending device */
-wlp_attr_array(u8, manufacturer)
-
-/* WLP Message Type */
-wlp_attr(u8, msg_type)
-
-/* WLP Model name: Model name of sending device */
-wlp_attr_array(u8, model_name)
-
-/* WLP Model number: Model number of sending device */
-wlp_attr_array(u8, model_nr)
-
-/* Registrar Nonce: Random number generated by registrar for an enrollment
- * session */
-wlp_attr(struct wlp_nonce, rnonce)
-
-/* Serial number of device */
-wlp_attr_array(u8, serial)
-
-/* UUID of enrollee */
-wlp_attr(struct wlp_uuid, uuid_e)
-
-/* UUID of registrar */
-wlp_attr(struct wlp_uuid, uuid_r)
-
-/* WLP Primary device type */
-wlp_attr(struct wlp_dev_type, prim_dev_type)
-
-/* WLP Secondary device type */
-wlp_attr(struct wlp_dev_type, sec_dev_type)
-
-/* WLP protocol version */
-wlp_attr(u8, version)
-
-/* WLP service set identifier */
-wlp_attr(struct wlp_uuid, wssid)
-
-/* WLP WSS name */
-wlp_attr_array(u8, wss_name)
-
-/* WLP WSS Secure Status */
-wlp_attr(u8, wss_sec_status)
-
-/* WSS Broadcast Address */
-wlp_attr(struct uwb_mac_addr, wss_bcast)
-
-/* WLP Accepting Enrollment */
-wlp_attr(u8, accept_enrl)
-
-/**
- * WSS information attributes
- * WLP Draft 0.99 [6.6.3 Table 15]
- */
-struct wlp_wss_info {
-       struct wlp_attr_wssid wssid;
-       struct wlp_attr_wss_name name;
-       struct wlp_attr_accept_enrl accept;
-       struct wlp_attr_wss_sec_status sec_stat;
-       struct wlp_attr_wss_bcast bcast;
-} __packed;
-
-/* WLP WSS Information */
-wlp_attr_array(struct wlp_wss_info, wss_info)
-
-/* WLP WSS Selection method */
-wlp_attr(u8, wss_sel_mthd)
-
-/* WLP WSS tag */
-wlp_attr(u8, wss_tag)
-
-/* WSS Virtual Address */
-wlp_attr(struct uwb_mac_addr, wss_virt)
-
-/* WLP association error */
-wlp_attr(u8, wlp_assc_err)
-
-/**
- * WLP standard and abbreviated frames
- *
- * WLP Draft 0.99 [6.3] and [6.4]
- *
- * The difference between the WLP standard frame and the WLP
- * abbreviated frame is that the standard frame includes the src
- * and dest addresses from the Ethernet header, the abbreviated frame does
- * not.
- * The src/dest (as well as the type/length and client data) are already
- * defined as part of the Ethernet header, we do not do this here.
- * From this perspective the standard and abbreviated frames appear the
- * same - they will be treated differently though.
- *
- * The size of this header is also captured in WLP_DATA_HLEN to enable
- * interfaces to prepare their headroom.
- */
-struct wlp_frame_std_abbrv_hdr {
-       struct wlp_frame_hdr hdr;
-       u8 tag;
-} __packed;
-
-/**
- * WLP association frames
- *
- * WLP Draft 0.99 [6.6]
- */
-struct wlp_frame_assoc {
-       struct wlp_frame_hdr hdr;
-       enum wlp_assoc_type type:8;
-       struct wlp_attr_version version;
-       struct wlp_attr_msg_type msg_type;
-       u8 attr[];
-} __packed;
-
-/* Ethernet to dev address mapping */
-struct wlp_eda {
-       spinlock_t lock;
-       struct list_head cache; /* Eth<->Dev Addr cache */
-};
-
-/**
- * WSS information temporary storage
- *
- * This information is only stored temporarily during discovery. It should
- * not be stored unless the device is enrolled in the advertised WSS. This
- * is done mainly because we follow the letter of the spec in this regard.
- * See WLP 0.99 [7.2.3].
- * When the device does become enrolled in a WSS the WSS information will
- * be stored as part of the more comprehensive struct wlp_wss.
- */
-struct wlp_wss_tmp_info {
-       char name[WLP_WSS_NAME_SIZE];
-       u8 accept_enroll;
-       u8 sec_status;
-       struct uwb_mac_addr bcast;
-};
-
-struct wlp_wssid_e {
-       struct list_head node;
-       struct wlp_uuid wssid;
-       struct wlp_wss_tmp_info *info;
-};
-
-/**
- * A cache entry of WLP neighborhood
- *
- * @node: head of list is wlp->neighbors
- * @wssid: list of wssids of this neighbor, element is wlp_wssid_e
- * @info:  temporary storage for information learned during discovery. This
- *         storage is used together with the wssid_e temporary storage
- *         during discovery.
- */
-struct wlp_neighbor_e {
-       struct list_head node;
-       struct wlp_uuid uuid;
-       struct uwb_dev *uwb_dev;
-       struct list_head wssid; /* Elements are wlp_wssid_e */
-       struct wlp_device_info *info;
-};
-
-struct wlp;
-/**
- * Information for an association session in progress.
- *
- * @exp_message: The type of the expected message. Both this message and a
- *               F0 message (which can be sent in response to any
- *               association frame) will be accepted as a valid message for
- *               this session.
- * @cb:          The function that will be called upon receipt of this
- *               message.
- * @cb_priv:     Private data of callback
- * @data:        Data used in association process (always a sk_buff?)
- * @neighbor:    Address of neighbor with which association session is in
- *               progress.
- */
-struct wlp_session {
-       enum wlp_assoc_type exp_message;
-       void (*cb)(struct wlp *);
-       void *cb_priv;
-       void *data;
-       struct uwb_dev_addr neighbor_addr;
-};
-
-/**
- * WLP Service Set
- *
- * @mutex: used to protect entire WSS structure.
- *
- * @name: The WSS name is set to 65 bytes, 1 byte larger than the maximum
- *        allowed by the WLP spec. This is to have a null terminated string
- *        for display to the user. A maximum of 64 bytes will still be used
- *        when placing the WSS name field in association frames.
- *
- * @accept_enroll: Accepting enrollment: Set to one if registrar is
- *                 accepting enrollment in WSS, or zero otherwise.
- *
- * Global and local information for each WSS in which we are enrolled.
- * WLP 0.99 Section 7.2.1 and Section 7.2.2
- */
-struct wlp_wss {
-       struct mutex mutex;
-       struct kobject kobj;
-       /* Global properties. */
-       struct wlp_uuid wssid;
-       u8 hash;
-       char name[WLP_WSS_NAME_SIZE];
-       struct uwb_mac_addr bcast;
-       u8 secure_status:1;
-       u8 master_key[16];
-       /* Local properties. */
-       u8 tag;
-       struct uwb_mac_addr virtual_addr;
-       /* Extra */
-       u8 accept_enroll:1;
-       enum wlp_wss_state state;
-};
-
-/**
- * WLP main structure
- * @mutex: protect changes to WLP structure. We only allow changes to the
- *         uuid, so currently this mutex only protects this field.
- */
-struct wlp {
-       struct mutex mutex;
-       struct uwb_rc *rc;              /* UWB radio controller */
-       struct net_device *ndev;
-       struct uwb_pal pal;
-       struct wlp_eda eda;
-       struct wlp_uuid uuid;
-       struct wlp_session *session;
-       struct wlp_wss wss;
-       struct mutex nbmutex; /* Neighbor mutex protects neighbors list */
-       struct list_head neighbors; /* Elements are wlp_neighbor_e */
-       struct uwb_notifs_handler uwb_notifs_handler;
-       struct wlp_device_info *dev_info;
-       void (*fill_device_info)(struct wlp *wlp, struct wlp_device_info *info);
-       int (*xmit_frame)(struct wlp *, struct sk_buff *,
-                         struct uwb_dev_addr *);
-       void (*stop_queue)(struct wlp *);
-       void (*start_queue)(struct wlp *);
-};
-
-/* sysfs */
-
-
-struct wlp_wss_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct wlp_wss *wss, char *buf);
-       ssize_t (*store)(struct wlp_wss *wss, const char *buf, size_t count);
-};
-
-#define WSS_ATTR(_name, _mode, _show, _store) \
-static struct wlp_wss_attribute wss_attr_##_name = __ATTR(_name, _mode,        \
-                                                         _show, _store)
-
-extern int wlp_setup(struct wlp *, struct uwb_rc *, struct net_device *ndev);
-extern void wlp_remove(struct wlp *);
-extern ssize_t wlp_neighborhood_show(struct wlp *, char *);
-extern int wlp_wss_setup(struct net_device *, struct wlp_wss *);
-extern void wlp_wss_remove(struct wlp_wss *);
-extern ssize_t wlp_wss_activate_show(struct wlp_wss *, char *);
-extern ssize_t wlp_wss_activate_store(struct wlp_wss *, const char *, size_t);
-extern ssize_t wlp_eda_show(struct wlp *, char *);
-extern ssize_t wlp_eda_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_uuid_show(struct wlp *, char *);
-extern ssize_t wlp_uuid_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_name_show(struct wlp *, char *);
-extern ssize_t wlp_dev_name_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_manufacturer_show(struct wlp *, char *);
-extern ssize_t wlp_dev_manufacturer_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_model_name_show(struct wlp *, char *);
-extern ssize_t wlp_dev_model_name_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_model_nr_show(struct wlp *, char *);
-extern ssize_t wlp_dev_model_nr_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_serial_show(struct wlp *, char *);
-extern ssize_t wlp_dev_serial_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_prim_category_show(struct wlp *, char *);
-extern ssize_t wlp_dev_prim_category_store(struct wlp *, const char *,
-                                          size_t);
-extern ssize_t wlp_dev_prim_OUI_show(struct wlp *, char *);
-extern ssize_t wlp_dev_prim_OUI_store(struct wlp *, const char *, size_t);
-extern ssize_t wlp_dev_prim_OUI_sub_show(struct wlp *, char *);
-extern ssize_t wlp_dev_prim_OUI_sub_store(struct wlp *, const char *,
-                                         size_t);
-extern ssize_t wlp_dev_prim_subcat_show(struct wlp *, char *);
-extern ssize_t wlp_dev_prim_subcat_store(struct wlp *, const char *,
-                                        size_t);
-extern int wlp_receive_frame(struct device *, struct wlp *, struct sk_buff *,
-                            struct uwb_dev_addr *);
-extern int wlp_prepare_tx_frame(struct device *, struct wlp *,
-                              struct sk_buff *, struct uwb_dev_addr *);
-void wlp_reset_all(struct wlp *wlp);
-
-/**
- * Initialize WSS
- */
-static inline
-void wlp_wss_init(struct wlp_wss *wss)
-{
-       mutex_init(&wss->mutex);
-}
-
-static inline
-void wlp_init(struct wlp *wlp)
-{
-       INIT_LIST_HEAD(&wlp->neighbors);
-       mutex_init(&wlp->mutex);
-       mutex_init(&wlp->nbmutex);
-       wlp_wss_init(&wlp->wss);
-}
-
-
-#endif /* #ifndef __LINUX__WLP_H_ */
index a9c041d..9b201ec 100644 (file)
@@ -35,7 +35,7 @@ struct ir_scancode_table {
        unsigned int            len;    /* Used number of entries */
        unsigned int            alloc;  /* Size of *scan in bytes */
        u64                     ir_type;
-       char                    *name;
+       const char              *name;
        spinlock_t              lock;
 };
 
index df26ebb..1fa2407 100644 (file)
@@ -177,7 +177,7 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state);
 #define snd_power_lock(card)           do { (void)(card); } while (0)
 #define snd_power_unlock(card)         do { (void)(card); } while (0)
 static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
-#define snd_power_get_state(card)      SNDRV_CTL_POWER_D0
+#define snd_power_get_state(card)      ({ (void)(card); SNDRV_CTL_POWER_D0; })
 #define snd_power_change_state(card, state)    do { (void)(card); } while (0)
 
 #endif /* CONFIG_PM */
index 7dc97d1..4f865df 100644 (file)
 #define CCCA_CURRADDR_MASK     0x00ffffff      /* Current address of the selected channel              */
 #define CCCA_CURRADDR          0x18000008
 
+/* undefine CCR to avoid conflict with the definition for SH */
+#undef CCR
 #define CCR                    0x09            /* Cache control register                               */
 #define CCR_CACHEINVALIDSIZE   0x07190009
 #define CCR_CACHEINVALIDSIZE_MASK      0xfe000000      /* Number of invalid samples cache for this channel     */
index d90b9fa..c140fc7 100644 (file)
@@ -47,6 +47,9 @@ enum snd_jack_types {
        SND_JACK_BTN_0          = 0x4000,
        SND_JACK_BTN_1          = 0x2000,
        SND_JACK_BTN_2          = 0x1000,
+       SND_JACK_BTN_3          = 0x0800,
+       SND_JACK_BTN_4          = 0x0400,
+       SND_JACK_BTN_5          = 0x0200,
 };
 
 struct snd_jack {
@@ -55,7 +58,7 @@ struct snd_jack {
        int type;
        const char *id;
        char name[100];
-       unsigned int key[3];   /* Keep in sync with definitions above */
+       unsigned int key[6];   /* Keep in sync with definitions above */
        void *private_data;
        void (*private_free)(struct snd_jack *);
 };
diff --git a/include/sound/max98088.h b/include/sound/max98088.h
new file mode 100644 (file)
index 0000000..c3ba823
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Platform data for MAX98088
+ *
+ * Copyright 2010 Maxim Integrated Products
+ *
+ *  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 __SOUND_MAX98088_PDATA_H__
+#define __SOUND_MAX98088_PDATA_H__
+
+/* Equalizer filter response configuration */
+struct max98088_eq_cfg {
+       const char *name;
+       unsigned int rate;
+       u16 band1[5];
+       u16 band2[5];
+       u16 band3[5];
+       u16 band4[5];
+       u16 band5[5];
+};
+
+/* codec platform data */
+struct max98088_pdata {
+
+       /* Equalizers for DAI1 and DAI2 */
+       struct max98088_eq_cfg *eq_cfg;
+       unsigned int eq_cfgcnt;
+
+       /* Receiver output can be configured as power amplifier or LINE out */
+       /* Set receiver_mode to:
+        * 0 = amplifier output, or
+        * 1 = LINE level output
+        */
+       unsigned int receiver_mode:1;
+
+       /* Analog/digital microphone configuration:
+        * 0 = analog microphone input (normal setting)
+        * 1 = digital microphone input
+        */
+       unsigned int digmic_left_mode:1;
+       unsigned int digmic_right_mode:1;
+
+};
+
+#endif
index 85f1c6b..dfd9b76 100644 (file)
@@ -278,6 +278,7 @@ struct snd_pcm_runtime {
        snd_pcm_uframes_t hw_ptr_base;  /* Position at buffer restart */
        snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
        unsigned long hw_ptr_jiffies;   /* Time when hw_ptr is updated */
+       unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
        snd_pcm_sframes_t delay;        /* extra delay; typically FIFO size */
 
        /* -- HW params -- */
index 9d51d6f..fa60cbd 100644 (file)
@@ -114,7 +114,4 @@ struct sh_fsi_platform_info {
        int (*set_rate)(int is_porta, int rate); /* for master mode */
 };
 
-extern struct snd_soc_dai fsi_soc_dai[2];
-extern struct snd_soc_platform fsi_soc_platform;
-
 #endif /* __SOUND_FSI_H */
index 377693a..e7b6802 100644 (file)
@@ -91,15 +91,17 @@ struct snd_pcm_substream;
                                SNDRV_PCM_FMTBIT_S32_LE |\
                                SNDRV_PCM_FMTBIT_S32_BE)
 
-struct snd_soc_dai_ops;
+struct snd_soc_dai_driver;
 struct snd_soc_dai;
 struct snd_ac97_bus_ops;
 
 /* Digital Audio Interface registration */
-int snd_soc_register_dai(struct snd_soc_dai *dai);
-void snd_soc_unregister_dai(struct snd_soc_dai *dai);
-int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
-void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
+int snd_soc_register_dai(struct device *dev,
+               struct snd_soc_dai_driver *dai_drv);
+void snd_soc_unregister_dai(struct device *dev);
+int snd_soc_register_dais(struct device *dev,
+               struct snd_soc_dai_driver *dai_drv, size_t count);
+void snd_soc_unregister_dais(struct device *dev, size_t count);
 
 /* Digital Audio Interface clocking API.*/
 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
@@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
 /* Digital Audio Interface mute */
 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
- * structure for every DAI they have.
- *
- * This structure covers the clocking, formating and ALSA operations for each
- * interface.
- */
 struct snd_soc_dai_ops {
        /*
         * DAI clocking configuration, all optional.
@@ -191,24 +183,24 @@ struct snd_soc_dai_ops {
 };
 
 /*
- * Digital Audio Interface runtime data.
+ * Digital Audio Interface Driver.
  *
- * Holds runtime data for a DAI.
+ * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
+ * operations and capabilities. Codec and platform drivers will register this
+ * structure for every DAI they have.
+ *
+ * This structure covers the clocking, formating and ALSA operations for each
+ * interface.
  */
-struct snd_soc_dai {
+struct snd_soc_dai_driver {
        /* DAI description */
-       char *name;
+       const char *name;
        unsigned int id;
        int ac97_control;
 
-       struct device *dev;
-       void *ac97_pdata;       /* platform_data for the ac97 codec */
-
-       /* DAI callbacks */
-       int (*probe)(struct platform_device *pdev,
-                    struct snd_soc_dai *dai);
-       void (*remove)(struct platform_device *pdev,
-                      struct snd_soc_dai *dai);
+       /* DAI driver callbacks */
+       int (*probe)(struct snd_soc_dai *dai);
+       int (*remove)(struct snd_soc_dai *dai);
        int (*suspend)(struct snd_soc_dai *dai);
        int (*resume)(struct snd_soc_dai *dai);
 
@@ -219,26 +211,51 @@ struct snd_soc_dai {
        struct snd_soc_pcm_stream capture;
        struct snd_soc_pcm_stream playback;
        unsigned int symmetric_rates:1;
+};
+
+/*
+ * Digital Audio Interface runtime data.
+ *
+ * Holds runtime data for a DAI.
+ */
+struct snd_soc_dai {
+       const char *name;
+       int id;
+       struct device *dev;
+       void *ac97_pdata;       /* platform_data for the ac97 codec */
+
+       /* driver ops */
+       struct snd_soc_dai_driver *driver;
 
        /* DAI runtime info */
-       struct snd_soc_codec *codec;
+       unsigned int capture_active:1;          /* stream is in use */
+       unsigned int playback_active:1;         /* stream is in use */
+       unsigned int symmetric_rates:1;
+       struct snd_pcm_runtime *runtime;
        unsigned int active;
        unsigned char pop_wait:1;
+       unsigned char probed:1;
 
-       /* DAI private data */
-       void *private_data;
+       /* DAI DMA data */
+       void *playback_dma_data;
+       void *capture_dma_data;
 
-       /* parent platform */
-       struct snd_soc_platform *platform;
+       /* parent platform/codec */
+       union {
+               struct snd_soc_platform *platform;
+               struct snd_soc_codec *codec;
+       };
+       struct snd_soc_card *card;
 
        struct list_head list;
+       struct list_head card_list;
 };
 
 static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
                                             const struct snd_pcm_substream *ss)
 {
        return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
-               dai->playback.dma_data : dai->capture.dma_data;
+               dai->playback_dma_data : dai->capture_dma_data;
 }
 
 static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
@@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
                                            void *data)
 {
        if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dai->playback.dma_data = data;
+               dai->playback_dma_data = data;
        else
-               dai->capture.dma_data = data;
+               dai->capture_dma_data = data;
+}
+
+static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
+               void *data)
+{
+       dev_set_drvdata(dai->dev, data);
+}
+
+static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai)
+{
+       return dev_get_drvdata(dai->dev);
 }
 
 #endif
index c5d9987..8fd3b41 100644 (file)
 #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_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
+                             wevent, wflags)                           \
+{      .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
+       .reg = wreg, .shift = wshift, .invert = winvert, \
+       .event = wevent, .event_flags = wflags }
 #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_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
+                            wevent, wflags)                            \
+{      .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
+       .reg = wreg, .shift = wshift, .invert = winvert, \
+       .event = wevent, .event_flags = wflags }
 #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}
@@ -322,14 +332,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
 
 /* dapm path setup */
 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
-void snd_soc_dapm_free(struct snd_soc_device *socdev);
+void snd_soc_dapm_free(struct snd_soc_codec *codec);
 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
                            const struct snd_soc_dapm_route *route, int num);
 
 /* 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);
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
+       const char *stream, int event);
+void snd_soc_dapm_shutdown(struct snd_soc_card *card);
 
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h
deleted file mode 100644 (file)
index a064e19..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * OF helpers for ALSA SoC
- *
- * Copyright (C) 2008, Secret Lab Technologies Ltd.
- */
-
-#ifndef _INCLUDE_SOC_OF_H_
-#define _INCLUDE_SOC_OF_H_
-
-#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE)
-
-#include <linux/of.h>
-#include <sound/soc.h>
-
-int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
-                             void *codec_data, struct snd_soc_dai *dai,
-                             struct device_node *node);
-
-int of_snd_soc_register_platform(struct snd_soc_platform *platform,
-                                struct device_node *node,
-                                struct snd_soc_dai *cpu_dai);
-
-#endif
-
-#endif /* _INCLUDE_SOC_OF_H_ */
index 65e9d03..5c3bce8 100644 (file)
  * @OFF:     Power Off. No restrictions on transition times.
  */
 enum snd_soc_bias_level {
-       SND_SOC_BIAS_ON,
-       SND_SOC_BIAS_PREPARE,
-       SND_SOC_BIAS_STANDBY,
        SND_SOC_BIAS_OFF,
+       SND_SOC_BIAS_STANDBY,
+       SND_SOC_BIAS_PREPARE,
+       SND_SOC_BIAS_ON,
 };
 
 struct snd_jack;
@@ -228,13 +228,17 @@ struct snd_soc_ops;
 struct snd_soc_dai_mode;
 struct snd_soc_pcm_runtime;
 struct snd_soc_dai;
+struct snd_soc_dai_driver;
 struct snd_soc_platform;
 struct snd_soc_dai_link;
+struct snd_soc_platform_driver;
 struct snd_soc_codec;
+struct snd_soc_codec_driver;
 struct soc_enum;
 struct snd_soc_ac97_ops;
 struct snd_soc_jack;
 struct snd_soc_jack_pin;
+
 #ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio;
 #endif
@@ -249,19 +253,18 @@ enum snd_soc_control_type {
        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_register_platform(struct device *dev,
+               struct snd_soc_platform_driver *platform_drv);
+void snd_soc_unregister_platform(struct device *dev);
+int snd_soc_register_codec(struct device *dev,
+               struct snd_soc_codec_driver *codec_drv,
+               struct snd_soc_dai_driver *dai_drv, int num_dai);
+void snd_soc_unregister_codec(struct device *dev);
 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);
 
-/* pcm <-> DAI connect */
-void snd_soc_free_pcms(struct snd_soc_device *socdev);
-int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
-
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
 int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
        const struct snd_pcm_hardware *hw);
 
 /* Jack reporting */
-int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
+int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
                     struct snd_soc_jack *jack);
 void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
 int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
@@ -382,7 +385,7 @@ struct snd_soc_jack_gpio {
        int invert;
        int debounce_time;
        struct snd_soc_jack *jack;
-       struct work_struct work;
+       struct delayed_work work;
 
        int (*jack_status_check)(void);
 };
@@ -390,7 +393,7 @@ struct snd_soc_jack_gpio {
 
 struct snd_soc_jack {
        struct snd_jack *jack;
-       struct snd_soc_card *card;
+       struct snd_soc_codec *codec;
        struct list_head pins;
        int status;
        struct blocking_notifier_head notifier;
@@ -398,15 +401,13 @@ struct snd_soc_jack {
 
 /* SoC PCM stream information */
 struct snd_soc_pcm_stream {
-       char *stream_name;
+       const char *stream_name;
        u64 formats;                    /* SNDRV_PCM_FMTBIT_* */
        unsigned int rates;             /* SNDRV_PCM_RATE_* */
        unsigned int rate_min;          /* min rate */
        unsigned int rate_max;          /* max rate */
        unsigned int channels_min;      /* min channels */
        unsigned int channels_max;      /* max channels */
-       unsigned int active;            /* stream is in use */
-       void *dma_data;                 /* used by platform code */
 };
 
 /* SoC audio ops */
@@ -419,44 +420,36 @@ struct snd_soc_ops {
        int (*trigger)(struct snd_pcm_substream *, int);
 };
 
-/* SoC Audio Codec */
+/* SoC Audio Codec device */
 struct snd_soc_codec {
-       char *name;
-       struct module *owner;
-       struct mutex mutex;
+       const char *name;
+       int id;
        struct device *dev;
-       struct snd_soc_device *socdev;
+       struct snd_soc_codec_driver *driver;
 
+       struct mutex mutex;
+       struct snd_soc_card *card;
        struct list_head list;
-
-       /* callbacks */
-       int (*set_bias_level)(struct snd_soc_codec *,
-                             enum snd_soc_bias_level level);
+       struct list_head card_list;
+       int num_dai;
 
        /* runtime */
-       struct snd_card *card;
        struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
        unsigned int active;
-       unsigned int pcm_devs;
-       void *drvdata;
+       unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
+       unsigned int cache_only:1;  /* Suppress writes to hardware */
+       unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
+       unsigned int suspended:1; /* Codec is in suspend PM state */
+       unsigned int probed:1; /* Codec has been probed */
+       unsigned int ac97_registered:1; /* Codec has been AC97 registered */
+       unsigned int ac97_created:1; /* Codec has been created by SoC */
+       unsigned int sysfs_registered:1; /* codec has been sysfs registered */
 
        /* codec IO */
        void *control_data; /* codec control (i2c/3wire) data */
-       unsigned int (*read)(struct snd_soc_codec *, unsigned int);
-       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);
        void *reg_cache;
-       short reg_cache_size;
-       short reg_cache_step;
-
-       unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
-       unsigned int cache_only:1;  /* Suppress writes to hardware */
-       unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
 
        /* dapm */
        u32 pop_time;
@@ -466,10 +459,6 @@ struct snd_soc_codec {
        enum snd_soc_bias_level suspend_bias_level;
        struct delayed_work delayed_work;
 
-       /* codec DAI's */
-       struct snd_soc_dai *dai;
-       unsigned int num_dai;
-
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_codec_root;
        struct dentry *debugfs_reg;
@@ -478,23 +467,40 @@ struct snd_soc_codec {
 #endif
 };
 
-/* codec device */
-struct snd_soc_codec_device {
-       int (*probe)(struct platform_device *pdev);
-       int (*remove)(struct platform_device *pdev);
-       int (*suspend)(struct platform_device *pdev, pm_message_t state);
-       int (*resume)(struct platform_device *pdev);
+/* codec driver */
+struct snd_soc_codec_driver {
+
+       /* driver ops */
+       int (*probe)(struct snd_soc_codec *);
+       int (*remove)(struct snd_soc_codec *);
+       int (*suspend)(struct snd_soc_codec *,
+                       pm_message_t state);
+       int (*resume)(struct snd_soc_codec *);
+
+       /* codec IO */
+       unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+       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);
+       short reg_cache_size;
+       short reg_cache_step;
+       short reg_word_size;
+       const void *reg_cache_default;
+
+       /* codec bias level */
+       int (*set_bias_level)(struct snd_soc_codec *,
+                             enum snd_soc_bias_level level);
 };
 
 /* SoC platform interface */
-struct snd_soc_platform {
-       char *name;
-       struct list_head list;
+struct snd_soc_platform_driver {
 
-       int (*probe)(struct platform_device *pdev);
-       int (*remove)(struct platform_device *pdev);
-       int (*suspend)(struct snd_soc_dai_link *dai_link);
-       int (*resume)(struct snd_soc_dai_link *dai_link);
+       int (*probe)(struct snd_soc_platform *);
+       int (*remove)(struct snd_soc_platform *);
+       int (*suspend)(struct snd_soc_dai *dai);
+       int (*resume)(struct snd_soc_dai *dai);
 
        /* pcm creation and destruction */
        int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@@ -509,23 +515,31 @@ struct snd_soc_platform {
                struct snd_soc_dai *);
 
        /* platform stream ops */
-       struct snd_pcm_ops *pcm_ops;
+       struct snd_pcm_ops *ops;
 };
 
-/* SoC machine DAI configuration, glues a codec and cpu DAI together */
-struct snd_soc_dai_link  {
-       char *name;                     /* Codec name */
-       char *stream_name;              /* Stream name */
+struct snd_soc_platform {
+       const char *name;
+       int id;
+       struct device *dev;
+       struct snd_soc_platform_driver *driver;
 
-       /* DAI */
-       struct snd_soc_dai *codec_dai;
-       struct snd_soc_dai *cpu_dai;
+       unsigned int suspended:1; /* platform is suspended */
+       unsigned int probed:1;
 
-       /* machine stream operations */
-       struct snd_soc_ops *ops;
+       struct snd_soc_card *card;
+       struct list_head list;
+       struct list_head card_list;
+};
 
-       /* codec/machine specific init - e.g. add machine controls */
-       int (*init)(struct snd_soc_codec *codec);
+struct snd_soc_dai_link {
+       /* config - must be set by machine driver */
+       const char *name;                       /* Codec name */
+       const char *stream_name;                /* Stream name */
+       const char *codec_name;         /* for multi-codec */
+       const char *platform_name;      /* for multi-platform */
+       const char *cpu_dai_name;
+       const char *codec_dai_name;
 
        /* Keep DAI active over suspend */
        unsigned int ignore_suspend:1;
@@ -533,21 +547,24 @@ struct snd_soc_dai_link  {
        /* Symmetry requirements */
        unsigned int symmetric_rates:1;
 
-       /* Symmetry data - only valid if symmetry is being enforced */
-       unsigned int rate;
+       /* codec/machine specific init - e.g. add machine controls */
+       int (*init)(struct snd_soc_pcm_runtime *rtd);
 
-       /* DAI pcm */
-       struct snd_pcm *pcm;
+       /* machine stream operations */
+       struct snd_soc_ops *ops;
 };
 
 /* SoC card */
 struct snd_soc_card {
-       char *name;
+       const char *name;
        struct device *dev;
+       struct snd_card *snd_card;
+       struct module *owner;
 
        struct list_head list;
+       struct mutex mutex;
 
-       int instantiated;
+       bool instantiated;
 
        int (*probe)(struct platform_device *pdev);
        int (*remove)(struct platform_device *pdev);
@@ -568,28 +585,38 @@ struct snd_soc_card {
        /* CPU <--> Codec DAI links  */
        struct snd_soc_dai_link *dai_link;
        int num_links;
+       struct snd_soc_pcm_runtime *rtd;
+       int num_rtd;
 
-       struct snd_soc_device *socdev;
-
-       struct snd_soc_codec *codec;
-
-       struct snd_soc_platform *platform;
-       struct delayed_work delayed_work;
        struct work_struct deferred_resume_work;
+
+       /* lists of probed devices belonging to this card */
+       struct list_head codec_dev_list;
+       struct list_head platform_dev_list;
+       struct list_head dai_dev_list;
 };
 
-/* SoC Device - the audio subsystem */
-struct snd_soc_device {
-       struct device *dev;
+/* SoC machine DAI configuration, glues a codec and cpu DAI together */
+struct snd_soc_pcm_runtime  {
+       struct device dev;
        struct snd_soc_card *card;
-       struct snd_soc_codec_device *codec_dev;
-       void *codec_data;
-};
+       struct snd_soc_dai_link *dai_link;
+
+       unsigned int complete:1;
+       unsigned int dev_registered:1;
+
+       /* Symmetry data - only valid if symmetry is being enforced */
+       unsigned int rate;
+       long pmdown_time;
 
-/* runtime channel data */
-struct snd_soc_pcm_runtime {
-       struct snd_soc_dai_link *dai;
-       struct snd_soc_device *socdev;
+       /* runtime devices */
+       struct snd_pcm *pcm;
+       struct snd_soc_codec *codec;
+       struct snd_soc_platform *platform;
+       struct snd_soc_dai *codec_dai;
+       struct snd_soc_dai *cpu_dai;
+
+       struct delayed_work delayed_work;
 };
 
 /* mixer control */
@@ -615,24 +642,48 @@ struct soc_enum {
 static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,
                                        unsigned int reg)
 {
-       return codec->read(codec, reg);
+       return codec->driver->read(codec, reg);
 }
 
 static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
                                         unsigned int reg, unsigned int val)
 {
-       return codec->write(codec, reg, val);
+       return codec->driver->write(codec, reg, val);
 }
 
+/* device driver data */
+
 static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
-                                            void *data)
+               void *data)
 {
-       codec->drvdata = data;
+       dev_set_drvdata(codec->dev, data);
 }
 
 static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
 {
-       return codec->drvdata;
+       return dev_get_drvdata(codec->dev);
+}
+
+static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
+               void *data)
+{
+       dev_set_drvdata(platform->dev, data);
+}
+
+static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
+{
+       return dev_get_drvdata(platform->dev);
+}
+
+static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd,
+               void *data)
+{
+       dev_set_drvdata(&rtd->dev, data);
+}
+
+static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
+{
+       return dev_get_drvdata(&rtd->dev);
 }
 
 #include <sound/soc-dai.h>
index 9fd5b19..7067e2d 100644 (file)
 #define SNDRV_CTL_TLVT_DB_MINMAX 4     /* dB scale with min/max */
 #define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5        /* dB scale with min/max with mute */
 
+#define TLV_DB_SCALE_MASK      0xffff
+#define TLV_DB_SCALE_MUTE      0x10000
 #define TLV_DB_SCALE_ITEM(min, step, mute)                     \
        SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int),      \
-       (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0)
+       (min), ((step) & TLV_DB_SCALE_MASK) | ((mute) ? TLV_DB_SCALE_MUTE : 0)
 #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
        unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }
 
index b1a5f34..99e0308 100644 (file)
 #ifndef __TLV320AIC3x_H__
 #define __TLV320AIC3x_H__
 
+/* GPIO API */
+enum {
+       AIC3X_GPIO1_FUNC_DISABLED               = 0,
+       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC      = 1,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX              = 2,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2         = 3,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4         = 4,
+       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8         = 5,
+       AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ      = 6,
+       AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ          = 7,
+       AIC3X_GPIO1_FUNC_INPUT                  = 8,
+       AIC3X_GPIO1_FUNC_OUTPUT                 = 9,
+       AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK     = 10,
+       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK          = 11,
+       AIC3X_GPIO1_FUNC_BUTTON_IRQ             = 12,
+       AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ     = 13,
+       AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ   = 14,
+       AIC3X_GPIO1_FUNC_ALL_IRQ                = 16
+};
+
+enum {
+       AIC3X_GPIO2_FUNC_DISABLED               = 0,
+       AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ     = 2,
+       AIC3X_GPIO2_FUNC_INPUT                  = 3,
+       AIC3X_GPIO2_FUNC_OUTPUT                 = 4,
+       AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT      = 5,
+       AIC3X_GPIO2_FUNC_AUDIO_BITCLK           = 8,
+       AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
+       AIC3X_GPIO2_FUNC_ALL_IRQ                = 10,
+       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
+       AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
+       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ      = 13,
+       AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ          = 14,
+       AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ       = 15
+};
+
+struct aic3x_setup_data {
+       unsigned int gpio_func[2];
+};
+
 struct aic3x_pdata {
        int gpio_reset; /* < 0 if not used */
+       struct aic3x_setup_data *setup;
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
new file mode 100644 (file)
index 0000000..2b5306c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * wm8962.h  --  WM8962 Soc Audio driver platform data
+ *
+ * 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 _WM8962_PDATA_H
+#define _WM8962_PDATA_H
+
+#define WM8962_MAX_GPIO 6
+
+/* Use to set GPIO default values to zero */
+#define WM8962_GPIO_SET 0x10000
+
+struct wm8962_pdata {
+       int gpio_base;
+       u32 gpio_init[WM8962_MAX_GPIO];
+
+       /* Setup for microphone detection, raw value to be written to
+        * R48(0x30) - only microphone related bits will be updated.
+        * Detection may be enabled here for use with signals brought
+        * out on the GPIOs. */
+       u32 mic_cfg;
+
+       bool irq_active_low;
+
+       bool spk_mono;   /* Speaker outputs tied together as mono */
+};
+
+#endif
index 577cf18..1e1aa54 100644 (file)
 struct sh_mobile_lcdc_chan_cfg;
 struct device;
 
+/*
+ * flags format
+ *
+ * 0x0000000A
+ *
+ * A: Audio source select
+ */
+
+/* Audio source select */
+#define HDMI_SND_SRC_MASK      (0xF << 0)
+#define HDMI_SND_SRC_I2S       (0 << 0) /* default */
+#define HDMI_SND_SRC_SPDIF     (1 << 0)
+#define HDMI_SND_SRC_DSD       (2 << 0)
+#define HDMI_SND_SRC_HBR       (3 << 0)
+
 struct sh_mobile_hdmi_info {
        struct sh_mobile_lcdc_chan_cfg  *lcd_chan;
        struct device                   *lcd_dev;
+       unsigned int                     flags;
 };
 
 #endif
index 42db055..62a47ea 100644 (file)
@@ -361,13 +361,13 @@ out:
 #ifdef CONFIG_ROOT_NFS
 static int __init mount_nfs_root(void)
 {
-       void *data = nfs_root_data();
+       char *root_dev, *root_data;
 
-       create_dev("/dev/root", ROOT_DEV);
-       if (data &&
-           do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
-               return 1;
-       return 0;
+       if (nfs_root_data(&root_dev, &root_data) != 0)
+               return 0;
+       if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+               return 0;
+       return 1;
 }
 #endif
 
index 30acdb7..e5ff2cb 100644 (file)
@@ -2791,7 +2791,9 @@ static int alloc_cwqs(struct workqueue_struct *wq)
                }
        }
 
-       /* just in case, make sure it's actually aligned */
+       /* just in case, make sure it's actually aligned
+        * - this is affected by PERCPU() alignment in vmlinux.lds.S
+        */
        BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
        return wq->cpu_wq.v ? 0 : -ENOMEM;
 }
index 92e6757..5f17fad 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -745,7 +745,7 @@ int page_mkclean(struct page *page)
                if (mapping) {
                        ret = page_mkclean_file(mapping, page);
                        if (page_test_dirty(page)) {
-                               page_clear_dirty(page);
+                               page_clear_dirty(page, 1);
                                ret = 1;
                        }
                }
@@ -942,7 +942,7 @@ void page_remove_rmap(struct page *page)
         * containing the swap entry, but page not yet written to swap.
         */
        if ((!PageAnon(page) || PageSwapCache(page)) && page_test_dirty(page)) {
-               page_clear_dirty(page);
+               page_clear_dirty(page, 1);
                set_page_dirty(page);
        }
        /*
index 499c045..f7db676 100644 (file)
@@ -1798,7 +1798,8 @@ static void iucv_work_fn(struct work_struct *work)
  * Handles external interrupts coming in from CP.
  * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn().
  */
-static void iucv_external_interrupt(u16 code)
+static void iucv_external_interrupt(unsigned int ext_int_code,
+                                   unsigned int param32, unsigned long param64)
 {
        struct iucv_irq_data *p;
        struct iucv_irq_list *work;
index e9eaaf7..68192e5 100644 (file)
@@ -595,7 +595,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
 int
 rpcauth_refreshcred(struct rpc_task *task)
 {
-       struct rpc_cred *cred = task->tk_rqstp->rq_cred;
+       struct rpc_cred *cred;
        int err;
 
        cred = task->tk_rqstp->rq_cred;
index fa55490..cbc5b8c 100644 (file)
@@ -1675,7 +1675,7 @@ rpc_verify_header(struct rpc_task *task)
                        rpcauth_invalcred(task);
                        /* Ensure we obtain a new XID! */
                        xprt_release(task);
-                       task->tk_action = call_refresh;
+                       task->tk_action = call_reserve;
                        goto out_retry;
                case RPC_AUTH_BADCRED:
                case RPC_AUTH_BADVERF:
index dac219a..63ec116 100644 (file)
@@ -211,8 +211,9 @@ static int rpcb_create_local(void)
         */
        clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
        if (IS_ERR(clnt4)) {
-               dprintk("RPC:       failed to create local rpcbind v4 "
-                               "cleint (errno %ld).\n", PTR_ERR(clnt4));
+               dprintk("RPC:       failed to bind second program to "
+                               "rpcbind v4 client (errno %ld).\n",
+                               PTR_ERR(clnt4));
                clnt4 = NULL;
        }
 
@@ -475,57 +476,6 @@ int rpcb_v4_register(const u32 program, const u32 version,
        return -EAFNOSUPPORT;
 }
 
-/**
- * rpcb_getport_sync - obtain the port for an RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * Return value is the requested advertised port number,
- * or a negative errno value.
- *
- * Called from outside the RPC client in a synchronous task context.
- * Uses default timeout parameters specified by underlying transport.
- *
- * XXX: Needs to support IPv6
- */
-int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
-{
-       struct rpcbind_args map = {
-               .r_prog         = prog,
-               .r_vers         = vers,
-               .r_prot         = prot,
-               .r_port         = 0,
-       };
-       struct rpc_message msg = {
-               .rpc_proc       = &rpcb_procedures2[RPCBPROC_GETPORT],
-               .rpc_argp       = &map,
-               .rpc_resp       = &map,
-       };
-       struct rpc_clnt *rpcb_clnt;
-       int status;
-
-       dprintk("RPC:       %s(%pI4, %u, %u, %d)\n",
-               __func__, &sin->sin_addr.s_addr, prog, vers, prot);
-
-       rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
-                               sizeof(*sin), prot, RPCBVERS_2);
-       if (IS_ERR(rpcb_clnt))
-               return PTR_ERR(rpcb_clnt);
-
-       status = rpc_call_sync(rpcb_clnt, &msg, 0);
-       rpc_shutdown_client(rpcb_clnt);
-
-       if (status >= 0) {
-               if (map.r_port != 0)
-                       return map.r_port;
-               status = -EACCES;
-       }
-       return status;
-}
-EXPORT_SYMBOL_GPL(rpcb_getport_sync);
-
 static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
 {
        struct rpc_message msg = {
index aa5dbda..243fc09 100644 (file)
@@ -908,7 +908,7 @@ static int rpciod_start(void)
         * Create the rpciod thread and wait for it to start.
         */
        dprintk("RPC:       creating workqueue rpciod\n");
-       wq = create_workqueue("rpciod");
+       wq = alloc_workqueue("rpciod", WQ_RESCUER, 0);
        rpciod_workqueue = wq;
        return rpciod_workqueue != NULL;
 }
index a1f82a8..cd9e841 100644 (file)
@@ -111,6 +111,23 @@ xdr_decode_string_inplace(__be32 *p, char **sp,
 }
 EXPORT_SYMBOL_GPL(xdr_decode_string_inplace);
 
+/**
+ * xdr_terminate_string - '\0'-terminate a string residing in an xdr_buf
+ * @buf: XDR buffer where string resides
+ * @len: length of string, in bytes
+ *
+ */
+void
+xdr_terminate_string(struct xdr_buf *buf, const u32 len)
+{
+       char *kaddr;
+
+       kaddr = kmap_atomic(buf->pages[0], KM_USER0);
+       kaddr[buf->page_base + len] = '\0';
+       kunmap_atomic(kaddr, KM_USER0);
+}
+EXPORT_SYMBOL(xdr_terminate_string);
+
 void
 xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base,
                 unsigned int len)
@@ -395,24 +412,29 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len)
 {
        struct kvec *tail;
        size_t copy;
-       char *p;
        unsigned int pglen = buf->page_len;
+       unsigned int tailbuf_len;
 
        tail = buf->tail;
        BUG_ON (len > pglen);
 
+       tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
+
        /* Shift the tail first */
-       if (tail->iov_len != 0) {
-               p = (char *)tail->iov_base + len;
+       if (tailbuf_len != 0) {
+               unsigned int free_space = tailbuf_len - tail->iov_len;
+
+               if (len < free_space)
+                       free_space = len;
+               tail->iov_len += free_space;
+
+               copy = len;
                if (tail->iov_len > len) {
-                       copy = tail->iov_len - len;
-                       memmove(p, tail->iov_base, copy);
+                       char *p = (char *)tail->iov_base + len;
+                       memmove(p, tail->iov_base, tail->iov_len - len);
                } else
-                       buf->buflen -= len;
-               /* Copy from the inlined pages into the tail */
-               copy = len;
-               if (copy > tail->iov_len)
                        copy = tail->iov_len;
+               /* Copy from the inlined pages into the tail */
                _copy_from_pages((char *)tail->iov_base,
                                buf->pages, buf->page_base + pglen - len,
                                copy);
@@ -551,6 +573,27 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 EXPORT_SYMBOL_GPL(xdr_init_decode);
 
 /**
+ * xdr_inline_peek - Allow read-ahead in the XDR data stream
+ * @xdr: pointer to xdr_stream struct
+ * @nbytes: number of bytes of data to decode
+ *
+ * Check if the input buffer is long enough to enable us to decode
+ * 'nbytes' more bytes of data starting at the current position.
+ * If so return the current pointer without updating the current
+ * pointer position.
+ */
+__be32 * xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes)
+{
+       __be32 *p = xdr->p;
+       __be32 *q = p + XDR_QUADLEN(nbytes);
+
+       if (unlikely(q > xdr->end || q < p))
+               return NULL;
+       return p;
+}
+EXPORT_SYMBOL_GPL(xdr_inline_peek);
+
+/**
  * xdr_inline_decode - Retrieve non-page XDR data to decode
  * @xdr: pointer to xdr_stream struct
  * @nbytes: number of bytes of data to decode
index f7c3df8..57b792e 100644 (file)
@@ -604,11 +604,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
                return -EEXIST;
        }
        for (idx = 0; idx < snd_ecards_limit; idx++) {
-               if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1))
-                       goto __exist;
+               if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
+                       if (card == snd_cards[idx])
+                               goto __ok;
+                       else
+                               goto __exist;
+               }
        }
        strcpy(card->id, buf1);
        snd_info_card_id_change(card);
+__ok:
        mutex_unlock(&snd_card_mutex);
 
        return count;
index f50ebf2..822dd56 100644 (file)
@@ -77,7 +77,7 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
        struct snd_mixer_oss_file *fmixer;
 
        if (file->private_data) {
-               fmixer = (struct snd_mixer_oss_file *) file->private_data;
+               fmixer = file->private_data;
                module_put(fmixer->card->module);
                snd_card_file_remove(fmixer->card, file);
                kfree(fmixer);
@@ -368,7 +368,7 @@ static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int
 
 static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       return snd_mixer_oss_ioctl1((struct snd_mixer_oss_file *) file->private_data, cmd, arg);
+       return snd_mixer_oss_ioctl1(file->private_data, cmd, arg);
 }
 
 int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg)
@@ -582,7 +582,7 @@ static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer,
                                     struct snd_mixer_oss_slot *pslot,
                                     int *left, int *right)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        
        *left = *right = 100;
        if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
@@ -618,8 +618,10 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
        if (numid == ID_UNKNOWN)
                return;
        down_read(&card->controls_rwsem);
-       if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
+       if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
+               up_read(&card->controls_rwsem);
                return;
+       }
        uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
        uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL)
@@ -658,7 +660,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
                return;
        down_read(&card->controls_rwsem);
        if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
-               up_read(&fmixer->card->controls_rwsem);
+               up_read(&card->controls_rwsem);
                return;
        }
        uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
@@ -691,7 +693,7 @@ static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
                                     struct snd_mixer_oss_slot *pslot,
                                     int left, int right)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        
        if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
                snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
@@ -740,7 +742,7 @@ static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
                                        struct snd_mixer_oss_slot *pslot,
                                        int *active)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        int left, right;
        
        left = right = 1;
@@ -753,7 +755,7 @@ static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer,
                                           struct snd_mixer_oss_slot *pslot,
                                           int *active)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        int left, right;
        
        left = right = 1;
@@ -766,7 +768,7 @@ static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
                                        struct snd_mixer_oss_slot *pslot,
                                        int active)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        
        snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
        return 0;
@@ -776,7 +778,7 @@ static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer,
                                           struct snd_mixer_oss_slot *pslot,
                                           int active)
 {
-       struct slot *slot = (struct slot *)pslot->private_data;
+       struct slot *slot = pslot->private_data;
        
        snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
        return 0;
@@ -797,7 +799,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
        uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
-               goto __unlock;
+               goto __free_only;
        }
        down_read(&card->controls_rwsem);
        kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
@@ -813,7 +815,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
                if (!(mixer->mask_recsrc & (1 << idx)))
                        continue;
                pslot = &mixer->slots[idx];
-               slot = (struct slot *)pslot->private_data;
+               slot = pslot->private_data;
                if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
                        continue;
                if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
@@ -826,6 +828,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
        err = 0;
       __unlock:
        up_read(&card->controls_rwsem);
+      __free_only:
        kfree(uctl);
        kfree(uinfo);
        return err;
@@ -847,7 +850,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
        uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
        if (uinfo == NULL || uctl == NULL) {
                err = -ENOMEM;
-               goto __unlock;
+               goto __free_only;
        }
        down_read(&card->controls_rwsem);
        kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
@@ -861,7 +864,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
                if (!(mixer->mask_recsrc & (1 << idx)))
                        continue;
                pslot = &mixer->slots[idx];
-               slot = (struct slot *)pslot->private_data;
+               slot = pslot->private_data;
                if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
                        continue;
                if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
@@ -880,6 +883,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
        err = 0;
       __unlock:
        up_read(&card->controls_rwsem);
+      __free_only:
        kfree(uctl);
        kfree(uinfo);
        return err;
@@ -925,7 +929,7 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
 
 static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
 {
-       struct slot *p = (struct slot *)chn->private_data;
+       struct slot *p = chn->private_data;
        if (p) {
                if (p->allocated && p->assigned) {
                        kfree(p->assigned->name);
index ac242a3..6b4b128 100644 (file)
@@ -364,8 +364,7 @@ static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
 static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
                                             struct snd_info_buffer *buffer)
 {
-       snd_pcm_proc_info_read((struct snd_pcm_substream *)entry->private_data,
-                              buffer);
+       snd_pcm_proc_info_read(entry->private_data, buffer);
 }
 
 static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
index e23e0e7..a1707cc 100644 (file)
@@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
                /* delta = "expected next hw_ptr" for in_interrupt != 0 */
                delta = runtime->hw_ptr_interrupt + runtime->period_size;
                if (delta > new_hw_ptr) {
-                       hw_base += runtime->buffer_size;
-                       if (hw_base >= runtime->boundary)
-                               hw_base = 0;
-                       new_hw_ptr = hw_base + pos;
-                       goto __delta;
+                       /* check for double acknowledged interrupts */
+                       hdelta = jiffies - runtime->hw_ptr_jiffies;
+                       if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
+                               hw_base += runtime->buffer_size;
+                               if (hw_base >= runtime->boundary)
+                                       hw_base = 0;
+                               new_hw_ptr = hw_base + pos;
+                               goto __delta;
+                       }
                }
        }
        /* new_hw_ptr might be lower than old_hw_ptr in case when */
index d4eb2ef..8bc7cb3 100644 (file)
@@ -142,7 +142,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
 
 #ifdef RULES_DEBUG
 #define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
-char *snd_pcm_hw_param_names[] = {
+static const char * const snd_pcm_hw_param_names[] = {
        HW_PARAM(ACCESS),
        HW_PARAM(FORMAT),
        HW_PARAM(SUBFORMAT),
@@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_trigger_tstamp(substream);
        runtime->hw_ptr_jiffies = jiffies;
+       runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / 
+                                                           runtime->rate;
        runtime->status->state = state;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
            runtime->silence_size > 0)
index 480c386..c896116 100644 (file)
@@ -74,6 +74,25 @@ config SND_DUMMY
          To compile this driver as a module, choose M here: the module
          will be called snd-dummy.
 
+config SND_ALOOP
+        tristate "Generic loopback driver (PCM)"
+        select SND_PCM
+        help
+          Say 'Y' or 'M' to include support for the PCM loopback device.
+         This module returns played samples back to the user space using
+         the standard ALSA PCM device. The devices are routed 0->1 and
+          1->0, where first number is the playback PCM device and second
+         number is the capture device. Module creates two PCM devices and
+         configured number of substreams (see the pcm_substreams module
+          parameter).
+
+         The looback device allow time sychronization with an external
+         timing source using the time shift universal control (+-20%
+         of system time).
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-aloop.
+
 config SND_VIRMIDI
        tristate "Virtual MIDI soundcard"
        depends on SND_SEQUENCER
index d4a07f9..1a8440c 100644 (file)
@@ -4,6 +4,7 @@
 #
 
 snd-dummy-objs := dummy.o
+snd-aloop-objs := aloop.o
 snd-mtpav-objs := mtpav.o
 snd-mts64-objs := mts64.o
 snd-portman2x4-objs := portman2x4.o
@@ -13,6 +14,7 @@ snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
+obj-$(CONFIG_SND_ALOOP) += snd-aloop.o
 obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
 obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
 obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
new file mode 100644 (file)
index 0000000..12b44b0
--- /dev/null
@@ -0,0 +1,1258 @@
+/*
+ *  Loopback soundcard
+ *
+ *  Original code:
+ *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *
+ *  More accurate positioning and full-duplex support:
+ *  Copyright (c) Ahmet Ä°nan <ainan at mathematik.uni-freiburg.de>
+ *
+ *  Major (almost complete) rewrite:
+ *  Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *  A next major update in 2010 (separate timers for playback and capture):
+ *  Copyright (c) Jaroslav Kysela <perex@perex.cz>
+ *
+ *   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, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
+MODULE_DESCRIPTION("A loopback soundcard");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}");
+
+#define MAX_PCM_SUBSTREAMS     8
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
+static int pcm_notify[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for loopback soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for loopback soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable this loopback soundcard.");
+module_param_array(pcm_substreams, int, NULL, 0444);
+MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver.");
+module_param_array(pcm_notify, int, NULL, 0444);
+MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes.");
+
+#define NO_PITCH 100000
+
+struct loopback_pcm;
+
+struct loopback_cable {
+       spinlock_t lock;
+       struct loopback_pcm *streams[2];
+       struct snd_pcm_hardware hw;
+       /* flags */
+       unsigned int valid;
+       unsigned int running;
+       unsigned int pause;
+};
+
+struct loopback_setup {
+       unsigned int notify: 1;
+       unsigned int rate_shift;
+       unsigned int format;
+       unsigned int rate;
+       unsigned int channels;
+       struct snd_ctl_elem_id active_id;
+       struct snd_ctl_elem_id format_id;
+       struct snd_ctl_elem_id rate_id;
+       struct snd_ctl_elem_id channels_id;
+};
+
+struct loopback {
+       struct snd_card *card;
+       struct mutex cable_lock;
+       struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2];
+       struct snd_pcm *pcm[2];
+       struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2];
+};
+
+struct loopback_pcm {
+       struct loopback *loopback;
+       struct snd_pcm_substream *substream;
+       struct loopback_cable *cable;
+       unsigned int pcm_buffer_size;
+       unsigned int buf_pos;   /* position in buffer */
+       unsigned int silent_size;
+       /* PCM parameters */
+       unsigned int pcm_period_size;
+       unsigned int pcm_bps;           /* bytes per second */
+       unsigned int pcm_salign;        /* bytes per sample * channels */
+       unsigned int pcm_rate_shift;    /* rate shift value */
+       /* flags */
+       unsigned int period_update_pending :1;
+       /* timer stuff */
+       unsigned int irq_pos;           /* fractional IRQ position */
+       unsigned int period_size_frac;
+       unsigned long last_jiffies;
+       struct timer_list timer;
+};
+
+static struct platform_device *devices[SNDRV_CARDS];
+
+static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x)
+{
+       if (dpcm->pcm_rate_shift == NO_PITCH) {
+               x /= HZ;
+       } else {
+               x = div_u64(NO_PITCH * (unsigned long long)x,
+                           HZ * (unsigned long long)dpcm->pcm_rate_shift);
+       }
+       return x - (x % dpcm->pcm_salign);
+}
+
+static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x)
+{
+       if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */
+               return x * HZ;
+       } else {
+               x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ,
+                           NO_PITCH);
+       }
+       return x;
+}
+
+static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm)
+{
+       int device = dpcm->substream->pstr->pcm->device;
+       
+       if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               device ^= 1;
+       return &dpcm->loopback->setup[dpcm->substream->number][device];
+}
+
+static inline unsigned int get_notify(struct loopback_pcm *dpcm)
+{
+       return get_setup(dpcm)->notify;
+}
+
+static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
+{
+       return get_setup(dpcm)->rate_shift;
+}
+
+static void loopback_timer_start(struct loopback_pcm *dpcm)
+{
+       unsigned long tick;
+       unsigned int rate_shift = get_rate_shift(dpcm);
+
+       if (rate_shift != dpcm->pcm_rate_shift) {
+               dpcm->pcm_rate_shift = rate_shift;
+               dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
+       }
+       if (dpcm->period_size_frac <= dpcm->irq_pos) {
+               dpcm->irq_pos %= dpcm->period_size_frac;
+               dpcm->period_update_pending = 1;
+       }
+       tick = dpcm->period_size_frac - dpcm->irq_pos;
+       tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
+       dpcm->timer.expires = jiffies + tick;
+       add_timer(&dpcm->timer);
+}
+
+static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
+{
+       del_timer(&dpcm->timer);
+       dpcm->timer.expires = 0;
+}
+
+#define CABLE_VALID_PLAYBACK   (1 << SNDRV_PCM_STREAM_PLAYBACK)
+#define CABLE_VALID_CAPTURE    (1 << SNDRV_PCM_STREAM_CAPTURE)
+#define CABLE_VALID_BOTH       (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
+
+static int loopback_check_format(struct loopback_cable *cable, int stream)
+{
+       struct snd_pcm_runtime *runtime, *cruntime;
+       struct loopback_setup *setup;
+       struct snd_card *card;
+       int check;
+
+       if (cable->valid != CABLE_VALID_BOTH) {
+               if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       goto __notify;
+               return 0;
+       }
+       runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
+                                                       substream->runtime;
+       cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
+                                                       substream->runtime;
+       check = runtime->format != cruntime->format ||
+               runtime->rate != cruntime->rate ||
+               runtime->channels != cruntime->channels;
+       if (!check)
+               return 0;
+       if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+               return -EIO;
+       } else {
+               snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
+                                       substream, SNDRV_PCM_STATE_DRAINING);
+             __notify:
+               runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
+                                                       substream->runtime;
+               setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
+               card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
+               if (setup->format != runtime->format) {
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                                       &setup->format_id);
+                       setup->format = runtime->format;
+               }
+               if (setup->rate != runtime->rate) {
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                                       &setup->rate_id);
+                       setup->rate = runtime->rate;
+               }
+               if (setup->channels != runtime->channels) {
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                                       &setup->channels_id);
+                       setup->channels = runtime->channels;
+               }
+       }
+       return 0;
+}
+
+static void loopback_active_notify(struct loopback_pcm *dpcm)
+{
+       snd_ctl_notify(dpcm->loopback->card,
+                      SNDRV_CTL_EVENT_MASK_VALUE,
+                      &get_setup(dpcm)->active_id);
+}
+
+static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback_pcm *dpcm = runtime->private_data;
+       struct loopback_cable *cable = dpcm->cable;
+       int err, stream = 1 << substream->stream;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               err = loopback_check_format(cable, substream->stream);
+               if (err < 0)
+                       return err;
+               dpcm->last_jiffies = jiffies;
+               dpcm->pcm_rate_shift = 0;
+               spin_lock(&cable->lock);        
+               cable->running |= stream;
+               cable->pause &= ~stream;
+               spin_unlock(&cable->lock);
+               loopback_timer_start(dpcm);
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       loopback_active_notify(dpcm);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               spin_lock(&cable->lock);        
+               cable->running &= ~stream;
+               cable->pause &= ~stream;
+               spin_unlock(&cable->lock);
+               loopback_timer_stop(dpcm);
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       loopback_active_notify(dpcm);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               spin_lock(&cable->lock);        
+               cable->pause |= stream;
+               spin_unlock(&cable->lock);
+               loopback_timer_stop(dpcm);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               spin_lock(&cable->lock);
+               dpcm->last_jiffies = jiffies;
+               cable->pause &= ~stream;
+               spin_unlock(&cable->lock);
+               loopback_timer_start(dpcm);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void params_change_substream(struct loopback_pcm *dpcm,
+                                   struct snd_pcm_runtime *runtime)
+{
+       struct snd_pcm_runtime *dst_runtime;
+
+       if (dpcm == NULL || dpcm->substream == NULL)
+               return;
+       dst_runtime = dpcm->substream->runtime;
+       if (dst_runtime == NULL)
+               return;
+       dst_runtime->hw = dpcm->cable->hw;
+}
+
+static void params_change(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback_pcm *dpcm = runtime->private_data;
+       struct loopback_cable *cable = dpcm->cable;
+
+       cable->hw.formats = (1ULL << runtime->format);
+       cable->hw.rate_min = runtime->rate;
+       cable->hw.rate_max = runtime->rate;
+       cable->hw.channels_min = runtime->channels;
+       cable->hw.channels_max = runtime->channels;
+       params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
+                               runtime);
+       params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE],
+                               runtime);
+}
+
+static int loopback_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback_pcm *dpcm = runtime->private_data;
+       struct loopback_cable *cable = dpcm->cable;
+       int bps, salign;
+
+       salign = (snd_pcm_format_width(runtime->format) *
+                                               runtime->channels) / 8;
+       bps = salign * runtime->rate;
+       if (bps <= 0 || salign <= 0)
+               return -EINVAL;
+
+       dpcm->buf_pos = 0;
+       dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+               /* clear capture buffer */
+               dpcm->silent_size = dpcm->pcm_buffer_size;
+               snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
+                                          runtime->buffer_size * runtime->channels);
+       }
+
+       dpcm->irq_pos = 0;
+       dpcm->period_update_pending = 0;
+       dpcm->pcm_bps = bps;
+       dpcm->pcm_salign = salign;
+       dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);
+
+       mutex_lock(&dpcm->loopback->cable_lock);
+       if (!(cable->valid & ~(1 << substream->stream)) ||
+            (get_setup(dpcm)->notify &&
+            substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
+               params_change(substream);
+       cable->valid |= 1 << substream->stream;
+       mutex_unlock(&dpcm->loopback->cable_lock);
+
+       return 0;
+}
+
+static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
+{
+       struct snd_pcm_runtime *runtime = dpcm->substream->runtime;
+       char *dst = runtime->dma_area;
+       unsigned int dst_off = dpcm->buf_pos;
+
+       if (dpcm->silent_size >= dpcm->pcm_buffer_size)
+               return;
+       if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size)
+               bytes = dpcm->pcm_buffer_size - dpcm->silent_size;
+
+       for (;;) {
+               unsigned int size = bytes;
+               if (dst_off + size > dpcm->pcm_buffer_size)
+                       size = dpcm->pcm_buffer_size - dst_off;
+               snd_pcm_format_set_silence(runtime->format, dst + dst_off,
+                                          bytes_to_frames(runtime, size) *
+                                               runtime->channels);
+               dpcm->silent_size += size;
+               bytes -= size;
+               if (!bytes)
+                       break;
+               dst_off = 0;
+       }
+}
+
+static void copy_play_buf(struct loopback_pcm *play,
+                         struct loopback_pcm *capt,
+                         unsigned int bytes)
+{
+       struct snd_pcm_runtime *runtime = play->substream->runtime;
+       char *src = runtime->dma_area;
+       char *dst = capt->substream->runtime->dma_area;
+       unsigned int src_off = play->buf_pos;
+       unsigned int dst_off = capt->buf_pos;
+       unsigned int clear_bytes = 0;
+
+       /* check if playback is draining, trim the capture copy size
+        * when our pointer is at the end of playback ring buffer */
+       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
+           snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { 
+               snd_pcm_uframes_t appl_ptr, appl_ptr1, diff;
+               appl_ptr = appl_ptr1 = runtime->control->appl_ptr;
+               appl_ptr1 -= appl_ptr1 % runtime->buffer_size;
+               appl_ptr1 += play->buf_pos / play->pcm_salign;
+               if (appl_ptr < appl_ptr1)
+                       appl_ptr1 -= runtime->buffer_size;
+               diff = (appl_ptr - appl_ptr1) * play->pcm_salign;
+               if (diff < bytes) {
+                       clear_bytes = bytes - diff;
+                       bytes = diff;
+               }
+       }
+
+       for (;;) {
+               unsigned int size = bytes;
+               if (src_off + size > play->pcm_buffer_size)
+                       size = play->pcm_buffer_size - src_off;
+               if (dst_off + size > capt->pcm_buffer_size)
+                       size = capt->pcm_buffer_size - dst_off;
+               memcpy(dst + dst_off, src + src_off, size);
+               capt->silent_size = 0;
+               bytes -= size;
+               if (!bytes)
+                       break;
+               src_off = (src_off + size) % play->pcm_buffer_size;
+               dst_off = (dst_off + size) % capt->pcm_buffer_size;
+       }
+
+       if (clear_bytes > 0) {
+               clear_capture_buf(capt, clear_bytes);
+               capt->silent_size = 0;
+       }
+}
+
+#define BYTEPOS_UPDATE_POSONLY 0
+#define BYTEPOS_UPDATE_CLEAR   1
+#define BYTEPOS_UPDATE_COPY    2
+
+static void loopback_bytepos_update(struct loopback_pcm *dpcm,
+                                   unsigned int delta,
+                                   unsigned int cmd)
+{
+       unsigned int count;
+       unsigned long last_pos;
+
+       last_pos = byte_pos(dpcm, dpcm->irq_pos);
+       dpcm->irq_pos += delta * dpcm->pcm_bps;
+       count = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
+       if (!count)
+               return;
+       if (cmd == BYTEPOS_UPDATE_CLEAR)
+               clear_capture_buf(dpcm, count);
+       else if (cmd == BYTEPOS_UPDATE_COPY)
+               copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
+                             dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE],
+                             count);
+       dpcm->buf_pos += count;
+       dpcm->buf_pos %= dpcm->pcm_buffer_size;
+       if (dpcm->irq_pos >= dpcm->period_size_frac) {
+               dpcm->irq_pos %= dpcm->period_size_frac;
+               dpcm->period_update_pending = 1;
+       }
+}
+
+static unsigned int loopback_pos_update(struct loopback_cable *cable)
+{
+       struct loopback_pcm *dpcm_play =
+                       cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
+       struct loopback_pcm *dpcm_capt =
+                       cable->streams[SNDRV_PCM_STREAM_CAPTURE];
+       unsigned long delta_play = 0, delta_capt = 0;
+       unsigned int running;
+
+       spin_lock(&cable->lock);        
+       running = cable->running ^ cable->pause;
+       if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
+               delta_play = jiffies - dpcm_play->last_jiffies;
+               dpcm_play->last_jiffies += delta_play;
+       }
+
+       if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
+               delta_capt = jiffies - dpcm_capt->last_jiffies;
+               dpcm_capt->last_jiffies += delta_capt;
+       }
+
+       if (delta_play == 0 && delta_capt == 0) {
+               spin_unlock(&cable->lock);
+               return running;
+       }
+               
+       if (delta_play > delta_capt) {
+               loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
+                                       BYTEPOS_UPDATE_POSONLY);
+               delta_play = delta_capt;
+       } else if (delta_play < delta_capt) {
+               loopback_bytepos_update(dpcm_capt, delta_capt - delta_play,
+                                       BYTEPOS_UPDATE_CLEAR);
+               delta_capt = delta_play;
+       }
+
+       if (delta_play == 0 && delta_capt == 0) {
+               spin_unlock(&cable->lock);
+               return running;
+       }
+       /* note delta_capt == delta_play at this moment */
+       loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
+       loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
+       spin_unlock(&cable->lock);
+       return running;
+}
+
+static void loopback_timer_function(unsigned long data)
+{
+       struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
+       unsigned int running;
+
+       running = loopback_pos_update(dpcm->cable);
+       if (running & (1 << dpcm->substream->stream)) {
+               loopback_timer_start(dpcm);
+               if (dpcm->period_update_pending) {
+                       dpcm->period_update_pending = 0;
+                       snd_pcm_period_elapsed(dpcm->substream);
+               }
+       }
+}
+
+static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback_pcm *dpcm = runtime->private_data;
+
+       loopback_pos_update(dpcm->cable);
+       return bytes_to_frames(runtime, dpcm->buf_pos);
+}
+
+static struct snd_pcm_hardware loopback_pcm_hardware =
+{
+       .info =         (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
+                        SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
+       .formats =      (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+                        SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
+                        SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE),
+       .rates =        SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+       .rate_min =             8000,
+       .rate_max =             192000,
+       .channels_min =         1,
+       .channels_max =         32,
+       .buffer_bytes_max =     2 * 1024 * 1024,
+       .period_bytes_min =     64,
+       /* note check overflow in frac_pos() using pcm_rate_shift before
+          changing period_bytes_max value */
+       .period_bytes_max =     1024 * 1024,
+       .periods_min =          1,
+       .periods_max =          1024,
+       .fifo_size =            0,
+};
+
+static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
+{
+       struct loopback_pcm *dpcm = runtime->private_data;
+       kfree(dpcm);
+}
+
+static int loopback_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+}
+
+static int loopback_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback_pcm *dpcm = runtime->private_data;
+       struct loopback_cable *cable = dpcm->cable;
+
+       mutex_lock(&dpcm->loopback->cable_lock);
+       cable->valid &= ~(1 << substream->stream);
+       mutex_unlock(&dpcm->loopback->cable_lock);
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static unsigned int get_cable_index(struct snd_pcm_substream *substream)
+{
+       if (!substream->pcm->device)
+               return substream->stream;
+       else
+               return !substream->stream;
+}
+
+static int rule_format(struct snd_pcm_hw_params *params,
+                      struct snd_pcm_hw_rule *rule)
+{
+
+       struct snd_pcm_hardware *hw = rule->private;
+       struct snd_mask *maskp = hw_param_mask(params, rule->var);
+
+       maskp->bits[0] &= (u_int32_t)hw->formats;
+       maskp->bits[1] &= (u_int32_t)(hw->formats >> 32);
+       memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
+       if (! maskp->bits[0] && ! maskp->bits[1])
+               return -EINVAL;
+       return 0;
+}
+
+static int rule_rate(struct snd_pcm_hw_params *params,
+                    struct snd_pcm_hw_rule *rule)
+{
+       struct snd_pcm_hardware *hw = rule->private;
+       struct snd_interval t;
+
+        t.min = hw->rate_min;
+        t.max = hw->rate_max;
+        t.openmin = t.openmax = 0;
+        t.integer = 0;
+       return snd_interval_refine(hw_param_interval(params, rule->var), &t);
+}
+
+static int rule_channels(struct snd_pcm_hw_params *params,
+                        struct snd_pcm_hw_rule *rule)
+{
+       struct snd_pcm_hardware *hw = rule->private;
+       struct snd_interval t;
+
+        t.min = hw->channels_min;
+        t.max = hw->channels_max;
+        t.openmin = t.openmax = 0;
+        t.integer = 0;
+       return snd_interval_refine(hw_param_interval(params, rule->var), &t);
+}
+
+static int loopback_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct loopback *loopback = substream->private_data;
+       struct loopback_pcm *dpcm;
+       struct loopback_cable *cable;
+       int err = 0;
+       int dev = get_cable_index(substream);
+
+       mutex_lock(&loopback->cable_lock);
+       dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
+       if (!dpcm) {
+               err = -ENOMEM;
+               goto unlock;
+       }
+       dpcm->loopback = loopback;
+       dpcm->substream = substream;
+       setup_timer(&dpcm->timer, loopback_timer_function,
+                   (unsigned long)dpcm);
+
+       cable = loopback->cables[substream->number][dev];
+       if (!cable) {
+               cable = kzalloc(sizeof(*cable), GFP_KERNEL);
+               if (!cable) {
+                       kfree(dpcm);
+                       err = -ENOMEM;
+                       goto unlock;
+               }
+               spin_lock_init(&cable->lock);
+               cable->hw = loopback_pcm_hardware;
+               loopback->cables[substream->number][dev] = cable;
+       }
+       dpcm->cable = cable;
+       cable->streams[substream->stream] = dpcm;
+
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+       /* use dynamic rules based on actual runtime->hw values */
+       /* note that the default rules created in the PCM midlevel code */
+       /* are cached -> they do not reflect the actual state */
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_FORMAT,
+                                 rule_format, &runtime->hw,
+                                 SNDRV_PCM_HW_PARAM_FORMAT, -1);
+       if (err < 0)
+               goto unlock;
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_RATE,
+                                 rule_rate, &runtime->hw,
+                                 SNDRV_PCM_HW_PARAM_RATE, -1);
+       if (err < 0)
+               goto unlock;
+       err = snd_pcm_hw_rule_add(runtime, 0,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS,
+                                 rule_channels, &runtime->hw,
+                                 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+       if (err < 0)
+               goto unlock;
+
+       runtime->private_data = dpcm;
+       runtime->private_free = loopback_runtime_free;
+       if (get_notify(dpcm))
+               runtime->hw = loopback_pcm_hardware;
+       else
+               runtime->hw = cable->hw;
+ unlock:
+       mutex_unlock(&loopback->cable_lock);
+       return err;
+}
+
+static int loopback_close(struct snd_pcm_substream *substream)
+{
+       struct loopback *loopback = substream->private_data;
+       struct loopback_pcm *dpcm = substream->runtime->private_data;
+       struct loopback_cable *cable;
+       int dev = get_cable_index(substream);
+
+       loopback_timer_stop(dpcm);
+       mutex_lock(&loopback->cable_lock);
+       cable = loopback->cables[substream->number][dev];
+       if (cable->streams[!substream->stream]) {
+               /* other stream is still alive */
+               cable->streams[substream->stream] = NULL;
+       } else {
+               /* free the cable */
+               loopback->cables[substream->number][dev] = NULL;
+               kfree(cable);
+       }
+       mutex_unlock(&loopback->cable_lock);
+       return 0;
+}
+
+static struct snd_pcm_ops loopback_playback_ops = {
+       .open =         loopback_open,
+       .close =        loopback_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    loopback_hw_params,
+       .hw_free =      loopback_hw_free,
+       .prepare =      loopback_prepare,
+       .trigger =      loopback_trigger,
+       .pointer =      loopback_pointer,
+};
+
+static struct snd_pcm_ops loopback_capture_ops = {
+       .open =         loopback_open,
+       .close =        loopback_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    loopback_hw_params,
+       .hw_free =      loopback_hw_free,
+       .prepare =      loopback_prepare,
+       .trigger =      loopback_trigger,
+       .pointer =      loopback_pointer,
+};
+
+static int __devinit loopback_pcm_new(struct loopback *loopback,
+                                     int device, int substreams)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       err = snd_pcm_new(loopback->card, "Loopback PCM", device,
+                         substreams, substreams, &pcm);
+       if (err < 0)
+               return err;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops);
+
+       pcm->private_data = loopback;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, "Loopback PCM");
+
+       loopback->pcm[device] = pcm;
+
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                       snd_dma_continuous_data(GFP_KERNEL),
+                       0, 2 * 1024 * 1024);
+       return 0;
+}
+
+static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol,   
+                                   struct snd_ctl_elem_info *uinfo) 
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 80000;
+       uinfo->value.integer.max = 120000;
+       uinfo->value.integer.step = 1;
+       return 0;
+}                                  
+
+static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       
+       ucontrol->value.integer.value[0] =
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].rate_shift;
+       return 0;
+}
+
+static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int change = 0;
+
+       val = ucontrol->value.integer.value[0];
+       if (val < 80000)
+               val = 80000;
+       if (val > 120000)
+               val = 120000;   
+       mutex_lock(&loopback->cable_lock);
+       if (val != loopback->setup[kcontrol->id.subdevice]
+                                 [kcontrol->id.device].rate_shift) {
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].rate_shift = val;
+               change = 1;
+       }
+       mutex_unlock(&loopback->cable_lock);
+       return change;
+}
+
+static int loopback_notify_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       
+       ucontrol->value.integer.value[0] =
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].notify;
+       return 0;
+}
+
+static int loopback_notify_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       unsigned int val;
+       int change = 0;
+
+       val = ucontrol->value.integer.value[0] ? 1 : 0;
+       if (val != loopback->setup[kcontrol->id.subdevice]
+                               [kcontrol->id.device].notify) {
+               loopback->setup[kcontrol->id.subdevice]
+                       [kcontrol->id.device].notify = val;
+               change = 1;
+       }
+       return change;
+}
+
+static int loopback_active_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       struct loopback_cable *cable = loopback->cables
+                       [kcontrol->id.subdevice][kcontrol->id.device ^ 1];
+       unsigned int val = 0;
+
+       if (cable != NULL)
+               val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
+                                                                       1 : 0;
+       ucontrol->value.integer.value[0] = val;
+       return 0;
+}
+
+static int loopback_format_info(struct snd_kcontrol *kcontrol,   
+                               struct snd_ctl_elem_info *uinfo) 
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST;
+       uinfo->value.integer.step = 1;
+       return 0;
+}                                  
+
+static int loopback_format_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       
+       ucontrol->value.integer.value[0] =
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].format;
+       return 0;
+}
+
+static int loopback_rate_info(struct snd_kcontrol *kcontrol,   
+                             struct snd_ctl_elem_info *uinfo) 
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 192000;
+       uinfo->value.integer.step = 1;
+       return 0;
+}                                  
+
+static int loopback_rate_get(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       
+       ucontrol->value.integer.value[0] =
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].rate;
+       return 0;
+}
+
+static int loopback_channels_info(struct snd_kcontrol *kcontrol,   
+                                 struct snd_ctl_elem_info *uinfo) 
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = 1;
+       uinfo->value.integer.max = 1024;
+       uinfo->value.integer.step = 1;
+       return 0;
+}                                  
+
+static int loopback_channels_get(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct loopback *loopback = snd_kcontrol_chip(kcontrol);
+       
+       ucontrol->value.integer.value[0] =
+               loopback->setup[kcontrol->id.subdevice]
+                              [kcontrol->id.device].channels;
+       return 0;
+}
+
+static struct snd_kcontrol_new loopback_controls[]  __devinitdata = {
+{
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Rate Shift 100000",
+       .info =         loopback_rate_shift_info,
+       .get =          loopback_rate_shift_get,
+       .put =          loopback_rate_shift_put,
+},
+{
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Notify",
+       .info =         snd_ctl_boolean_mono_info,
+       .get =          loopback_notify_get,
+       .put =          loopback_notify_put,
+},
+#define ACTIVE_IDX 2
+{
+       .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Slave Active",
+       .info =         snd_ctl_boolean_mono_info,
+       .get =          loopback_active_get,
+},
+#define FORMAT_IDX 3
+{
+       .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Slave Format",
+       .info =         loopback_format_info,
+       .get =          loopback_format_get
+},
+#define RATE_IDX 4
+{
+       .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Slave Rate",
+       .info =         loopback_rate_info,
+       .get =          loopback_rate_get
+},
+#define CHANNELS_IDX 5
+{
+       .access =       SNDRV_CTL_ELEM_ACCESS_READ,
+       .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+       .name =         "PCM Slave Channels",
+       .info =         loopback_channels_info,
+       .get =          loopback_channels_get
+}
+};
+
+static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
+{
+       struct snd_card *card = loopback->card;
+       struct snd_pcm *pcm;
+       struct snd_kcontrol *kctl;
+       struct loopback_setup *setup;
+       int err, dev, substr, substr_count, idx;
+
+       strcpy(card->mixername, "Loopback Mixer");
+       for (dev = 0; dev < 2; dev++) {
+               pcm = loopback->pcm[dev];
+               substr_count =
+                   pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count;
+               for (substr = 0; substr < substr_count; substr++) {
+                       setup = &loopback->setup[substr][dev];
+                       setup->notify = notify;
+                       setup->rate_shift = NO_PITCH;
+                       setup->format = SNDRV_PCM_FORMAT_S16_LE;
+                       setup->rate = 48000;
+                       setup->channels = 2;
+                       for (idx = 0; idx < ARRAY_SIZE(loopback_controls);
+                                                                       idx++) {
+                               kctl = snd_ctl_new1(&loopback_controls[idx],
+                                                   loopback);
+                               if (!kctl)
+                                       return -ENOMEM;
+                               kctl->id.device = dev;
+                               kctl->id.subdevice = substr;
+                               switch (idx) {
+                               case ACTIVE_IDX:
+                                       setup->active_id = kctl->id;
+                                       break;
+                               case FORMAT_IDX:
+                                       setup->format_id = kctl->id;
+                                       break;
+                               case RATE_IDX:
+                                       setup->rate_id = kctl->id;
+                                       break;
+                               case CHANNELS_IDX:
+                                       setup->channels_id = kctl->id;
+                                       break;
+                               default:
+                                       break;
+                               }
+                               err = snd_ctl_add(card, kctl);
+                               if (err < 0)
+                                       return err;
+                       }
+               }
+       }
+       return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static void print_dpcm_info(struct snd_info_buffer *buffer,
+                           struct loopback_pcm *dpcm,
+                           const char *id)
+{
+       snd_iprintf(buffer, "  %s\n", id);
+       if (dpcm == NULL) {
+               snd_iprintf(buffer, "    inactive\n");
+               return;
+       }
+       snd_iprintf(buffer, "    buffer_size:\t%u\n", dpcm->pcm_buffer_size);
+       snd_iprintf(buffer, "    buffer_pos:\t\t%u\n", dpcm->buf_pos);
+       snd_iprintf(buffer, "    silent_size:\t%u\n", dpcm->silent_size);
+       snd_iprintf(buffer, "    period_size:\t%u\n", dpcm->pcm_period_size);
+       snd_iprintf(buffer, "    bytes_per_sec:\t%u\n", dpcm->pcm_bps);
+       snd_iprintf(buffer, "    sample_align:\t%u\n", dpcm->pcm_salign);
+       snd_iprintf(buffer, "    rate_shift:\t\t%u\n", dpcm->pcm_rate_shift);
+       snd_iprintf(buffer, "    update_pending:\t%u\n",
+                                               dpcm->period_update_pending);
+       snd_iprintf(buffer, "    irq_pos:\t\t%u\n", dpcm->irq_pos);
+       snd_iprintf(buffer, "    period_frac:\t%u\n", dpcm->period_size_frac);
+       snd_iprintf(buffer, "    last_jiffies:\t%lu (%lu)\n",
+                                       dpcm->last_jiffies, jiffies);
+       snd_iprintf(buffer, "    timer_expires:\t%lu\n", dpcm->timer.expires);
+}
+
+static void print_substream_info(struct snd_info_buffer *buffer,
+                                struct loopback *loopback,
+                                int sub,
+                                int num)
+{
+       struct loopback_cable *cable = loopback->cables[sub][num];
+
+       snd_iprintf(buffer, "Cable %i substream %i:\n", num, sub);
+       if (cable == NULL) {
+               snd_iprintf(buffer, "  inactive\n");
+               return;
+       }
+       snd_iprintf(buffer, "  valid: %u\n", cable->valid);
+       snd_iprintf(buffer, "  running: %u\n", cable->running);
+       snd_iprintf(buffer, "  pause: %u\n", cable->pause);
+       print_dpcm_info(buffer, cable->streams[0], "Playback");
+       print_dpcm_info(buffer, cable->streams[1], "Capture");
+}
+
+static void print_cable_info(struct snd_info_entry *entry,
+                            struct snd_info_buffer *buffer)
+{
+       struct loopback *loopback = entry->private_data;
+       int sub, num;
+
+       mutex_lock(&loopback->cable_lock);
+       num = entry->name[strlen(entry->name)-1];
+       num = num == '0' ? 0 : 1;
+       for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++)
+               print_substream_info(buffer, loopback, sub, num);
+       mutex_unlock(&loopback->cable_lock);
+}
+
+static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
+{
+       char name[32];
+       struct snd_info_entry *entry;
+       int err;
+
+       snprintf(name, sizeof(name), "cable#%d", cidx);
+       err = snd_card_proc_new(loopback->card, name, &entry);
+       if (err < 0)
+               return err;
+
+       snd_info_set_text_ops(entry, loopback, print_cable_info);
+       return 0;
+}
+
+#else /* !CONFIG_PROC_FS */
+
+#define loopback_proc_new(loopback, cidx) do { } while (0)
+
+#endif
+
+static int __devinit loopback_probe(struct platform_device *devptr)
+{
+       struct snd_card *card;
+       struct loopback *loopback;
+       int dev = devptr->id;
+       int err;
+
+       err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                             sizeof(struct loopback), &card);
+       if (err < 0)
+               return err;
+       loopback = card->private_data;
+
+       if (pcm_substreams[dev] < 1)
+               pcm_substreams[dev] = 1;
+       if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
+               pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
+       
+       loopback->card = card;
+       mutex_init(&loopback->cable_lock);
+
+       err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
+       if (err < 0)
+               goto __nodev;
+       err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
+       if (err < 0)
+               goto __nodev;
+       err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
+       if (err < 0)
+               goto __nodev;
+       loopback_proc_new(loopback, 0);
+       loopback_proc_new(loopback, 1);
+       strcpy(card->driver, "Loopback");
+       strcpy(card->shortname, "Loopback");
+       sprintf(card->longname, "Loopback %i", dev + 1);
+       err = snd_card_register(card);
+       if (!err) {
+               platform_set_drvdata(devptr, card);
+               return 0;
+       }
+      __nodev:
+       snd_card_free(card);
+       return err;
+}
+
+static int __devexit loopback_remove(struct platform_device *devptr)
+{
+       snd_card_free(platform_get_drvdata(devptr));
+       platform_set_drvdata(devptr, NULL);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int loopback_suspend(struct platform_device *pdev,
+                               pm_message_t state)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+       struct loopback *loopback = card->private_data;
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+       snd_pcm_suspend_all(loopback->pcm[0]);
+       snd_pcm_suspend_all(loopback->pcm[1]);
+       return 0;
+}
+       
+static int loopback_resume(struct platform_device *pdev)
+{
+       struct snd_card *card = platform_get_drvdata(pdev);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+#endif
+
+#define SND_LOOPBACK_DRIVER    "snd_aloop"
+
+static struct platform_driver loopback_driver = {
+       .probe          = loopback_probe,
+       .remove         = __devexit_p(loopback_remove),
+#ifdef CONFIG_PM
+       .suspend        = loopback_suspend,
+       .resume         = loopback_resume,
+#endif
+       .driver         = {
+               .name   = SND_LOOPBACK_DRIVER
+       },
+};
+
+static void loopback_unregister_all(void)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(devices); ++i)
+               platform_device_unregister(devices[i]);
+       platform_driver_unregister(&loopback_driver);
+}
+
+static int __init alsa_card_loopback_init(void)
+{
+       int i, err, cards;
+
+       err = platform_driver_register(&loopback_driver);
+       if (err < 0)
+               return err;
+
+
+       cards = 0;
+       for (i = 0; i < SNDRV_CARDS; i++) {
+               struct platform_device *device;
+               if (!enable[i])
+                       continue;
+               device = platform_device_register_simple(SND_LOOPBACK_DRIVER,
+                                                        i, NULL, 0);
+               if (IS_ERR(device))
+                       continue;
+               if (!platform_get_drvdata(device)) {
+                       platform_device_unregister(device);
+                       continue;
+               }
+               devices[i] = device;
+               cards++;
+       }
+       if (!cards) {
+#ifdef MODULE
+               printk(KERN_ERR "aloop: No loopback enabled\n");
+#endif
+               loopback_unregister_all();
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit alsa_card_loopback_exit(void)
+{
+       loopback_unregister_all();
+}
+
+module_init(alsa_card_loopback_init)
+module_exit(alsa_card_loopback_exit)
index 0e631c3..f4cd493 100644 (file)
@@ -94,7 +94,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
                              sizeof(struct snd_card_virmidi), &card);
        if (err < 0)
                return err;
-       vmidi = (struct snd_card_virmidi *)card->private_data;
+       vmidi = card->private_data;
        vmidi->card = card;
 
        if (midi_devs[dev] > MAX_MIDI_DEVICES) {
index 42d7844..57ccba8 100644 (file)
@@ -878,7 +878,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
 static void proc_regs_read(struct snd_info_entry *entry,
                struct snd_info_buffer *buffer)
 {
-       struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data;
+       struct snd_akm4xxx *ak = entry->private_data;
        int reg, val, chip;
        for (chip = 0; chip < ak->num_chips; chip++) {
                for (reg = 0; reg < ak->total_regs; reg++) {
index c6990c6..52064cf 100644 (file)
@@ -77,6 +77,32 @@ config SND_ALS100
          To compile this driver as a module, choose M here: the module
          will be called snd-als100.
 
+config SND_AZT1605
+       tristate "Aztech AZT1605 Driver"
+       depends on SND
+       select SND_WSS_LIB
+       select SND_MPU401_UART
+       select SND_OPL3_LIB
+       help
+         Say Y here to include support for Aztech Sound Galaxy cards
+         based on the AZT1605 chipset.
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-azt1605.
+
+config SND_AZT2316
+       tristate "Aztech AZT2316 Driver"
+       depends on SND
+       select SND_WSS_LIB
+       select SND_MPU401_UART
+       select SND_OPL3_LIB
+       help
+         Say Y here to include support for Aztech Sound Galaxy cards
+         based on the AZT2316 chipset.
+
+         To compile this driver as a module, choose M here: the module
+         will be called snd-azt2316.
+
 config SND_AZT2320
        tristate "Aztech Systems AZT2320"
        depends on PNP
@@ -351,16 +377,6 @@ config SND_SB16_CSP
          coprocessor can do variable tasks like various compression and
          decompression algorithms.
 
-config SND_SGALAXY
-       tristate "Aztech Sound Galaxy"
-       select SND_WSS_LIB
-       help
-         Say Y here to include support for Aztech Sound Galaxy
-         soundcards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called snd-sgalaxy.
-
 config SND_SSCAPE
        tristate "Ensoniq SoundScape driver"
        select SND_MPU401_UART
index c73d30c..8d781e4 100644 (file)
@@ -10,7 +10,6 @@ snd-cmi8330-objs := cmi8330.o
 snd-es18xx-objs := es18xx.o
 snd-opl3sa2-objs := opl3sa2.o
 snd-sc6000-objs := sc6000.o
-snd-sgalaxy-objs := sgalaxy.o
 snd-sscape-objs := sscape.o
 
 # Toplevel Module Dependency
@@ -21,8 +20,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
 obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
 obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
 obj-$(CONFIG_SND_SC6000) += snd-sc6000.o
-obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
 obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
 
-obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \
+obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \
                     sb/ wavefront/ wss/
index bbcbf92..3cb75bc 100644 (file)
@@ -162,7 +162,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
                                sizeof(struct snd_card_ad1816a), &card);
        if (error < 0)
                return error;
-       acard = (struct snd_card_ad1816a *)card->private_data;
+       acard = card->private_data;
 
        if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) {
                snd_card_free(card);
index f7aa637..aac8dc1 100644 (file)
@@ -188,7 +188,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
                                sizeof(struct snd_card_azt2320), &card);
        if (error < 0)
                return error;
-       acard = (struct snd_card_azt2320 *)card->private_data;
+       acard = card->private_data;
 
        if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
                snd_card_free(card);
diff --git a/sound/isa/galaxy/Makefile b/sound/isa/galaxy/Makefile
new file mode 100644 (file)
index 0000000..e307066
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for ALSA
+# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
+#
+
+snd-azt1605-objs := azt1605.o
+snd-azt2316-objs := azt2316.o
+
+obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o
+obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o
diff --git a/sound/isa/galaxy/azt1605.c b/sound/isa/galaxy/azt1605.c
new file mode 100644 (file)
index 0000000..9a97643
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Aztech AZT1605 Driver
+ * Copyright (C) 2007,2010  Rene Herman
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define AZT1605
+
+#define CRD_NAME "Aztech AZT1605"
+#define DRV_NAME "AZT1605"
+#define DEV_NAME "azt1605"
+
+#define GALAXY_DSP_MAJOR               2
+#define GALAXY_DSP_MINOR               1
+
+#define GALAXY_CONFIG_SIZE             3
+
+/*
+ * 24-bit config register
+ */
+
+#define GALAXY_CONFIG_SBA_220          (0 << 0)
+#define GALAXY_CONFIG_SBA_240          (1 << 0)
+#define GALAXY_CONFIG_SBA_260          (2 << 0)
+#define GALAXY_CONFIG_SBA_280          (3 << 0)
+#define GALAXY_CONFIG_SBA_MASK         GALAXY_CONFIG_SBA_280
+
+#define GALAXY_CONFIG_MPUA_300         (0 << 2)
+#define GALAXY_CONFIG_MPUA_330         (1 << 2)
+
+#define GALAXY_CONFIG_MPU_ENABLE       (1 << 3)
+
+#define GALAXY_CONFIG_GAME_ENABLE      (1 << 4)
+
+#define GALAXY_CONFIG_CD_PANASONIC     (1 << 5)
+#define GALAXY_CONFIG_CD_MITSUMI       (1 << 6)
+#define GALAXY_CONFIG_CD_MASK          (\
+       GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI)
+
+#define GALAXY_CONFIG_UNUSED           (1 << 7)
+#define GALAXY_CONFIG_UNUSED_MASK      GALAXY_CONFIG_UNUSED
+
+#define GALAXY_CONFIG_SBIRQ_2          (1 << 8)
+#define GALAXY_CONFIG_SBIRQ_3          (1 << 9)
+#define GALAXY_CONFIG_SBIRQ_5          (1 << 10)
+#define GALAXY_CONFIG_SBIRQ_7          (1 << 11)
+
+#define GALAXY_CONFIG_MPUIRQ_2         (1 << 12)
+#define GALAXY_CONFIG_MPUIRQ_3         (1 << 13)
+#define GALAXY_CONFIG_MPUIRQ_5         (1 << 14)
+#define GALAXY_CONFIG_MPUIRQ_7         (1 << 15)
+
+#define GALAXY_CONFIG_WSSA_530         (0 << 16)
+#define GALAXY_CONFIG_WSSA_604         (1 << 16)
+#define GALAXY_CONFIG_WSSA_E80         (2 << 16)
+#define GALAXY_CONFIG_WSSA_F40         (3 << 16)
+
+#define GALAXY_CONFIG_WSS_ENABLE       (1 << 18)
+
+#define GALAXY_CONFIG_CDIRQ_11         (1 << 19)
+#define GALAXY_CONFIG_CDIRQ_12         (1 << 20)
+#define GALAXY_CONFIG_CDIRQ_15         (1 << 21)
+#define GALAXY_CONFIG_CDIRQ_MASK       (\
+       GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\
+       GALAXY_CONFIG_CDIRQ_15)
+
+#define GALAXY_CONFIG_CDDMA_DISABLE    (0 << 22)
+#define GALAXY_CONFIG_CDDMA_0          (1 << 22)
+#define GALAXY_CONFIG_CDDMA_1          (2 << 22)
+#define GALAXY_CONFIG_CDDMA_3          (3 << 22)
+#define GALAXY_CONFIG_CDDMA_MASK       GALAXY_CONFIG_CDDMA_3
+
+#define GALAXY_CONFIG_MASK             (\
+       GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\
+       GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\
+       GALAXY_CONFIG_CDDMA_MASK)
+
+#include "galaxy.c"
diff --git a/sound/isa/galaxy/azt2316.c b/sound/isa/galaxy/azt2316.c
new file mode 100644 (file)
index 0000000..1894411
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Aztech AZT2316 Driver
+ * Copyright (C) 2007,2010  Rene Herman
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#define AZT2316
+
+#define CRD_NAME "Aztech AZT2316"
+#define DRV_NAME "AZT2316"
+#define DEV_NAME "azt2316"
+
+#define GALAXY_DSP_MAJOR               3
+#define GALAXY_DSP_MINOR               1
+
+#define GALAXY_CONFIG_SIZE             4
+
+/*
+ * 32-bit config register
+ */
+
+#define GALAXY_CONFIG_SBA_220          (0 << 0)
+#define GALAXY_CONFIG_SBA_240          (1 << 0)
+#define GALAXY_CONFIG_SBA_260          (2 << 0)
+#define GALAXY_CONFIG_SBA_280          (3 << 0)
+#define GALAXY_CONFIG_SBA_MASK         GALAXY_CONFIG_SBA_280
+
+#define GALAXY_CONFIG_SBIRQ_2          (1 << 2)
+#define GALAXY_CONFIG_SBIRQ_5          (1 << 3)
+#define GALAXY_CONFIG_SBIRQ_7          (1 << 4)
+#define GALAXY_CONFIG_SBIRQ_10         (1 << 5)
+
+#define GALAXY_CONFIG_SBDMA_DISABLE    (0 << 6)
+#define GALAXY_CONFIG_SBDMA_0          (1 << 6)
+#define GALAXY_CONFIG_SBDMA_1          (2 << 6)
+#define GALAXY_CONFIG_SBDMA_3          (3 << 6)
+
+#define GALAXY_CONFIG_WSSA_530         (0 << 8)
+#define GALAXY_CONFIG_WSSA_604         (1 << 8)
+#define GALAXY_CONFIG_WSSA_E80         (2 << 8)
+#define GALAXY_CONFIG_WSSA_F40         (3 << 8)
+
+#define GALAXY_CONFIG_WSS_ENABLE       (1 << 10)
+
+#define GALAXY_CONFIG_GAME_ENABLE      (1 << 11)
+
+#define GALAXY_CONFIG_MPUA_300         (0 << 12)
+#define GALAXY_CONFIG_MPUA_330         (1 << 12)
+
+#define GALAXY_CONFIG_MPU_ENABLE       (1 << 13)
+
+#define GALAXY_CONFIG_CDA_310          (0 << 14)
+#define GALAXY_CONFIG_CDA_320          (1 << 14)
+#define GALAXY_CONFIG_CDA_340          (2 << 14)
+#define GALAXY_CONFIG_CDA_350          (3 << 14)
+#define GALAXY_CONFIG_CDA_MASK         GALAXY_CONFIG_CDA_350
+
+#define GALAXY_CONFIG_CD_DISABLE       (0 << 16)
+#define GALAXY_CONFIG_CD_PANASONIC     (1 << 16)
+#define GALAXY_CONFIG_CD_SONY          (2 << 16)
+#define GALAXY_CONFIG_CD_MITSUMI       (3 << 16)
+#define GALAXY_CONFIG_CD_AZTECH                (4 << 16)
+#define GALAXY_CONFIG_CD_UNUSED_5      (5 << 16)
+#define GALAXY_CONFIG_CD_UNUSED_6      (6 << 16)
+#define GALAXY_CONFIG_CD_UNUSED_7      (7 << 16)
+#define GALAXY_CONFIG_CD_MASK          GALAXY_CONFIG_CD_UNUSED_7
+
+#define GALAXY_CONFIG_CDDMA8_DISABLE   (0 << 20)
+#define GALAXY_CONFIG_CDDMA8_0         (1 << 20)
+#define GALAXY_CONFIG_CDDMA8_1         (2 << 20)
+#define GALAXY_CONFIG_CDDMA8_3         (3 << 20)
+#define GALAXY_CONFIG_CDDMA8_MASK      GALAXY_CONFIG_CDDMA8_3
+
+#define GALAXY_CONFIG_CDDMA16_DISABLE  (0 << 22)
+#define GALAXY_CONFIG_CDDMA16_5                (1 << 22)
+#define GALAXY_CONFIG_CDDMA16_6                (2 << 22)
+#define GALAXY_CONFIG_CDDMA16_7                (3 << 22)
+#define GALAXY_CONFIG_CDDMA16_MASK     GALAXY_CONFIG_CDDMA16_7
+
+#define GALAXY_CONFIG_MPUIRQ_2         (1 << 24)
+#define GALAXY_CONFIG_MPUIRQ_5         (1 << 25)
+#define GALAXY_CONFIG_MPUIRQ_7         (1 << 26)
+#define GALAXY_CONFIG_MPUIRQ_10                (1 << 27)
+
+#define GALAXY_CONFIG_CDIRQ_5          (1 << 28)
+#define GALAXY_CONFIG_CDIRQ_11         (1 << 29)
+#define GALAXY_CONFIG_CDIRQ_12         (1 << 30)
+#define GALAXY_CONFIG_CDIRQ_15         (1 << 31)
+#define GALAXY_CONFIG_CDIRQ_MASK       (\
+       GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\
+       GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15)
+
+#define GALAXY_CONFIG_MASK             (\
+       GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\
+       GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\
+       GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK)
+
+#include "galaxy.c"
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
new file mode 100644 (file)
index 0000000..ee54df0
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * Aztech AZT1605/AZT2316 Driver
+ * Copyright (C) 2007,2010  Rene Herman
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/isa.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/wss.h>
+#include <sound/mpu401.h>
+#include <sound/opl3.h>
+
+MODULE_DESCRIPTION(CRD_NAME);
+MODULE_AUTHOR("Rene Herman");
+MODULE_LICENSE("GPL");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
+
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+
+module_param_array(port, long, NULL, 0444);
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
+module_param_array(wss_port, long, NULL, 0444);
+MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
+module_param_array(mpu_port, long, NULL, 0444);
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
+module_param_array(fm_port, long, NULL, 0444);
+MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
+module_param_array(irq, int, NULL, 0444);
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
+module_param_array(mpu_irq, int, NULL, 0444);
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
+module_param_array(dma1, int, NULL, 0444);
+MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
+module_param_array(dma2, int, NULL, 0444);
+MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
+
+/*
+ * Generic SB DSP support routines
+ */
+
+#define DSP_PORT_RESET         0x6
+#define DSP_PORT_READ          0xa
+#define DSP_PORT_COMMAND       0xc
+#define DSP_PORT_STATUS                0xc
+#define DSP_PORT_DATA_AVAIL    0xe
+
+#define DSP_SIGNATURE          0xaa
+
+#define DSP_COMMAND_GET_VERSION        0xe1
+
+static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
+{
+       int loops = 1000;
+
+       while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) {
+               if (!loops--)
+                       return -EIO;
+               cpu_relax();
+       }
+       *val = ioread8(port + DSP_PORT_READ);
+       return 0;
+}
+
+static int __devinit dsp_reset(void __iomem *port)
+{
+       u8 val;
+
+       iowrite8(1, port + DSP_PORT_RESET);
+       udelay(10);
+       iowrite8(0, port + DSP_PORT_RESET);
+
+       if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int __devinit dsp_command(void __iomem *port, u8 cmd)
+{
+       int loops = 1000;
+
+       while (ioread8(port + DSP_PORT_STATUS) & 0x80) {
+               if (!loops--)
+                       return -EIO;
+               cpu_relax();
+       }
+       iowrite8(cmd, port + DSP_PORT_COMMAND);
+       return 0;
+}
+
+static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
+{
+       int err;
+
+       err = dsp_command(port, DSP_COMMAND_GET_VERSION);
+       if (err < 0)
+               return err;
+
+       err = dsp_get_byte(port, major);
+       if (err < 0)
+               return err;
+
+       err = dsp_get_byte(port, minor);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+/*
+ * Generic WSS support routines
+ */
+
+#define WSS_CONFIG_DMA_0       (1 << 0)
+#define WSS_CONFIG_DMA_1       (2 << 0)
+#define WSS_CONFIG_DMA_3       (3 << 0)
+#define WSS_CONFIG_DUPLEX      (1 << 2)
+#define WSS_CONFIG_IRQ_7       (1 << 3)
+#define WSS_CONFIG_IRQ_9       (2 << 3)
+#define WSS_CONFIG_IRQ_10      (3 << 3)
+#define WSS_CONFIG_IRQ_11      (4 << 3)
+
+#define WSS_PORT_CONFIG                0
+#define WSS_PORT_SIGNATURE     3
+
+#define WSS_SIGNATURE          4
+
+static int __devinit wss_detect(void __iomem *wss_port)
+{
+       if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
+               return -ENODEV;
+
+       return 0;
+}
+
+static void wss_set_config(void __iomem *wss_port, u8 wss_config)
+{
+       iowrite8(wss_config, wss_port + WSS_PORT_CONFIG);
+}
+
+/*
+ * Aztech Sound Galaxy specifics
+ */
+
+#define GALAXY_PORT_CONFIG     1024
+#define CONFIG_PORT_SET                4
+
+#define DSP_COMMAND_GALAXY_8   8
+#define GALAXY_COMMAND_GET_TYPE        5
+
+#define DSP_COMMAND_GALAXY_9   9
+#define GALAXY_COMMAND_WSSMODE 0
+#define GALAXY_COMMAND_SB8MODE 1
+
+#define GALAXY_MODE_WSS                GALAXY_COMMAND_WSSMODE
+#define GALAXY_MODE_SB8                GALAXY_COMMAND_SB8MODE
+
+struct snd_galaxy {
+       void __iomem *port;
+       void __iomem *config_port;
+       void __iomem *wss_port;
+       u32 config;
+       struct resource *res_port;
+       struct resource *res_config_port;
+       struct resource *res_wss_port;
+};
+
+static u32 config[SNDRV_CARDS];
+static u8 wss_config[SNDRV_CARDS];
+
+static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
+{
+       if (!enable[n])
+               return 0;
+
+       switch (port[n]) {
+       case SNDRV_AUTO_PORT:
+               dev_err(dev, "please specify port\n");
+               return 0;
+       case 0x220:
+               config[n] |= GALAXY_CONFIG_SBA_220;
+               break;
+       case 0x240:
+               config[n] |= GALAXY_CONFIG_SBA_240;
+               break;
+       case 0x260:
+               config[n] |= GALAXY_CONFIG_SBA_260;
+               break;
+       case 0x280:
+               config[n] |= GALAXY_CONFIG_SBA_280;
+               break;
+       default:
+               dev_err(dev, "invalid port %#lx\n", port[n]);
+               return 0;
+       }
+
+       switch (wss_port[n]) {
+       case SNDRV_AUTO_PORT:
+               dev_err(dev,  "please specify wss_port\n");
+               return 0;
+       case 0x530:
+               config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530;
+               break;
+       case 0x604:
+               config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604;
+               break;
+       case 0xe80:
+               config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80;
+               break;
+       case 0xf40:
+               config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40;
+               break;
+       default:
+               dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]);
+               return 0;
+       }
+
+       switch (irq[n]) {
+       case SNDRV_AUTO_IRQ:
+               dev_err(dev,  "please specify irq\n");
+               return 0;
+       case 7:
+               wss_config[n] |= WSS_CONFIG_IRQ_7;
+               break;
+       case 2:
+               irq[n] = 9;
+       case 9:
+               wss_config[n] |= WSS_CONFIG_IRQ_9;
+               break;
+       case 10:
+               wss_config[n] |= WSS_CONFIG_IRQ_10;
+               break;
+       case 11:
+               wss_config[n] |= WSS_CONFIG_IRQ_11;
+               break;
+       default:
+               dev_err(dev, "invalid IRQ %d\n", irq[n]);
+               return 0;
+       }
+
+       switch (dma1[n]) {
+       case SNDRV_AUTO_DMA:
+               dev_err(dev,  "please specify dma1\n");
+               return 0;
+       case 0:
+               wss_config[n] |= WSS_CONFIG_DMA_0;
+               break;
+       case 1:
+               wss_config[n] |= WSS_CONFIG_DMA_1;
+               break;
+       case 3:
+               wss_config[n] |= WSS_CONFIG_DMA_3;
+               break;
+       default:
+               dev_err(dev, "invalid playback DMA %d\n", dma1[n]);
+               return 0;
+       }
+
+       if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) {
+               dma2[n] = -1;
+               goto mpu;
+       }
+
+       wss_config[n] |= WSS_CONFIG_DUPLEX;
+       switch (dma2[n]) {
+       case 0:
+               break;
+       case 1:
+               if (dma1[n] == 0)
+                       break;
+       default:
+               dev_err(dev, "invalid capture DMA %d\n", dma2[n]);
+               return 0;
+       }
+
+mpu:
+       switch (mpu_port[n]) {
+       case SNDRV_AUTO_PORT:
+               dev_warn(dev, "mpu_port not specified; not using MPU-401\n");
+               mpu_port[n] = -1;
+               goto fm;
+       case 0x300:
+               config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300;
+               break;
+       case 0x330:
+               config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330;
+               break;
+       default:
+               dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]);
+               return 0;
+       }
+
+       switch (mpu_irq[n]) {
+       case SNDRV_AUTO_IRQ:
+               dev_warn(dev, "mpu_irq not specified: using polling mode\n");
+               mpu_irq[n] = -1;
+               break;
+       case 2:
+               mpu_irq[n] = 9;
+       case 9:
+               config[n] |= GALAXY_CONFIG_MPUIRQ_2;
+               break;
+#ifdef AZT1605
+       case 3:
+               config[n] |= GALAXY_CONFIG_MPUIRQ_3;
+               break;
+#endif
+       case 5:
+               config[n] |= GALAXY_CONFIG_MPUIRQ_5;
+               break;
+       case 7:
+               config[n] |= GALAXY_CONFIG_MPUIRQ_7;
+               break;
+#ifdef AZT2316
+       case 10:
+               config[n] |= GALAXY_CONFIG_MPUIRQ_10;
+               break;
+#endif
+       default:
+               dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]);
+               return 0;
+       }
+
+       if (mpu_irq[n] == irq[n]) {
+               dev_err(dev, "cannot share IRQ between WSS and MPU-401\n");
+               return 0;
+       }
+
+fm:
+       switch (fm_port[n]) {
+       case SNDRV_AUTO_PORT:
+               dev_warn(dev, "fm_port not specified: not using OPL3\n");
+               fm_port[n] = -1;
+               break;
+       case 0x388:
+               break;
+       default:
+               dev_err(dev, "illegal FM port %#lx\n", fm_port[n]);
+               return 0;
+       }
+
+       config[n] |= GALAXY_CONFIG_GAME_ENABLE;
+       return 1;
+}
+
+static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
+{
+       u8 major;
+       u8 minor;
+       int err;
+
+       err = dsp_reset(galaxy->port);
+       if (err < 0)
+               return err;
+
+       err = dsp_get_version(galaxy->port, &major, &minor);
+       if (err < 0)
+               return err;
+
+       if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR)
+               return -ENODEV;
+
+       err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8);
+       if (err < 0)
+               return err;
+
+       err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE);
+       if (err < 0)
+               return err;
+
+       err = dsp_get_byte(galaxy->port, type);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
+{
+       int err;
+
+       err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9);
+       if (err < 0)
+               return err;
+
+       err = dsp_command(galaxy->port, mode);
+       if (err < 0)
+               return err;
+
+#ifdef AZT1605
+       /*
+        * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
+        */
+       err = dsp_reset(galaxy->port);
+       if (err < 0)
+               return err;
+#endif
+
+       return 0;
+}
+
+static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
+{
+       u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET);
+       int i;
+
+       iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET);
+       for (i = 0; i < GALAXY_CONFIG_SIZE; i++) {
+               iowrite8(config, galaxy->config_port + i);
+               config >>= 8;
+       }
+       iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET);
+       msleep(10);
+}
+
+static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
+{
+       int i;
+
+       for (i = GALAXY_CONFIG_SIZE; i; i--) {
+               u8 tmp = ioread8(galaxy->config_port + i - 1);
+               galaxy->config = (galaxy->config << 8) | tmp;
+       }
+       config |= galaxy->config & GALAXY_CONFIG_MASK;
+       galaxy_set_config(galaxy, config);
+}
+
+static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
+{
+       int err;
+
+       err = wss_detect(galaxy->wss_port);
+       if (err < 0)
+               return err;
+
+       wss_set_config(galaxy->wss_port, wss_config);
+
+       err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static void snd_galaxy_free(struct snd_card *card)
+{
+       struct snd_galaxy *galaxy = card->private_data;
+
+       if (galaxy->wss_port) {
+               wss_set_config(galaxy->wss_port, 0);
+               ioport_unmap(galaxy->wss_port);
+               release_and_free_resource(galaxy->res_wss_port);
+       }
+       if (galaxy->config_port) {
+               galaxy_set_config(galaxy, galaxy->config);
+               ioport_unmap(galaxy->config_port);
+               release_and_free_resource(galaxy->res_config_port);
+       }
+       if (galaxy->port) {
+               ioport_unmap(galaxy->port);
+               release_and_free_resource(galaxy->res_port);
+       }
+}
+
+static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
+{
+       struct snd_galaxy *galaxy;
+       struct snd_wss *chip;
+       struct snd_card *card;
+       u8 type;
+       int err;
+
+       err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy,
+                             &card);
+       if (err < 0)
+               return err;
+
+       snd_card_set_dev(card, dev);
+
+       card->private_free = snd_galaxy_free;
+       galaxy = card->private_data;
+
+       galaxy->res_port = request_region(port[n], 16, DRV_NAME);
+       if (!galaxy->res_port) {
+               dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
+                       port[n] + 15);
+               err = -EBUSY;
+               goto error;
+       }
+       galaxy->port = ioport_map(port[n], 16);
+
+       err = galaxy_init(galaxy, &type);
+       if (err < 0) {
+               dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
+               goto error;
+       }
+       dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
+
+       galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
+                                                16, DRV_NAME);
+       if (!galaxy->res_config_port) {
+               dev_err(dev, "could not grab ports %#lx-%#lx\n",
+                       port[n] + GALAXY_PORT_CONFIG,
+                       port[n] + GALAXY_PORT_CONFIG + 15);
+               err = -EBUSY;
+               goto error;
+       }
+       galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
+
+       galaxy_config(galaxy, config[n]);
+
+       galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
+       if (!galaxy->res_wss_port)  {
+               dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
+                       wss_port[n] + 3);
+               err = -EBUSY;
+               goto error;
+       }
+       galaxy->wss_port = ioport_map(wss_port[n], 4);
+
+       err = galaxy_wss_config(galaxy, wss_config[n]);
+       if (err < 0) {
+               dev_err(dev, "could not configure WSS\n");
+               goto error;
+       }
+
+       strcpy(card->driver, DRV_NAME);
+       strcpy(card->shortname, DRV_NAME);
+       sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d",
+               card->shortname, port[n], wss_port[n], irq[n], dma1[n],
+               dma2[n]);
+
+       err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
+                            dma2[n], WSS_HW_DETECT, 0, &chip);
+       if (err < 0)
+               goto error;
+
+       err = snd_wss_pcm(chip, 0, NULL);
+       if (err < 0)
+               goto error;
+
+       err = snd_wss_mixer(chip);
+       if (err < 0)
+               goto error;
+
+       err = snd_wss_timer(chip, 0, NULL);
+       if (err < 0)
+               goto error;
+
+       if (mpu_port[n] >= 0) {
+               err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
+                                         mpu_port[n], 0, mpu_irq[n],
+                                         IRQF_DISABLED, NULL);
+               if (err < 0)
+                       goto error;
+       }
+
+       if (fm_port[n] >= 0) {
+               struct snd_opl3 *opl3;
+
+               err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
+                                     OPL3_HW_AUTO, 0, &opl3);
+               if (err < 0) {
+                       dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
+                       goto error;
+               }
+               err = snd_opl3_timer_new(opl3, 1, 2);
+               if (err < 0)
+                       goto error;
+
+               err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+               if (err < 0)
+                       goto error;
+       }
+
+       err = snd_card_register(card);
+       if (err < 0)
+               goto error;
+
+       dev_set_drvdata(dev, card);
+       return 0;
+
+error:
+       snd_card_free(card);
+       return err;
+}
+
+static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
+{
+       snd_card_free(dev_get_drvdata(dev));
+       dev_set_drvdata(dev, NULL);
+       return 0;
+}
+
+static struct isa_driver snd_galaxy_driver = {
+       .match          = snd_galaxy_match,
+       .probe          = snd_galaxy_probe,
+       .remove         = __devexit_p(snd_galaxy_remove),
+
+       .driver         = {
+               .name   = DEV_NAME
+       }
+};
+
+static int __init alsa_card_galaxy_init(void)
+{
+       return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS);
+}
+
+static void __exit alsa_card_galaxy_exit(void)
+{
+       isa_unregister_driver(&snd_galaxy_driver);
+}
+
+module_init(alsa_card_galaxy_init);
+module_exit(alsa_card_galaxy_exit);
index f26eac8..3e4a58b 100644 (file)
@@ -191,7 +191,7 @@ static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
 
 static void snd_gusmax_free(struct snd_card *card)
 {
-       struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data;
+       struct snd_gusmax *maxcard = card->private_data;
        
        if (maxcard == NULL)
                return;
@@ -219,7 +219,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
        if (err < 0)
                return err;
        card->private_free = snd_gusmax_free;
-       maxcard = (struct snd_gusmax *)card->private_data;
+       maxcard = card->private_data;
        maxcard->card = card;
        maxcard->irq = -1;
        
index 81284a8..2259e3f 100644 (file)
@@ -72,7 +72,7 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
 
 static void snd_sb8_free(struct snd_card *card)
 {
-       struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data;
+       struct snd_sb8 *acard = card->private_data;
 
        if (acard == NULL)
                return;
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
deleted file mode 100644 (file)
index 6fe27b9..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- *  Driver for Aztech Sound Galaxy cards
- *  Copyright (c) by Christopher Butler <chrisb@sandy.force9.co.uk.
- *
- *  I don't have documentation for this card, I based this driver on the
- *  driver for OSS/Free included in the kernel source (drivers/sound/sgalaxy.c)
- *
- *   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, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/isa.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <asm/dma.h>
-#include <sound/core.h>
-#include <sound/sb.h>
-#include <sound/wss.h>
-#include <sound/control.h>
-#define SNDRV_LEGACY_FIND_FREE_IRQ
-#define SNDRV_LEGACY_FIND_FREE_DMA
-#include <sound/initval.h>
-
-MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
-MODULE_DESCRIPTION("Aztech Sound Galaxy");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
-static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;  /* 0x220,0x240 */
-static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
-static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;       /* 7,9,10,11 */
-static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;      /* 0,1,3 */
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
-module_param_array(sbport, long, NULL, 0444);
-MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
-module_param_array(wssport, long, NULL, 0444);
-MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
-module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
-module_param_array(dma1, int, NULL, 0444);
-MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
-
-#define SGALAXY_AUXC_LEFT 18
-#define SGALAXY_AUXC_RIGHT 19
-
-#define PFX    "sgalaxy: "
-
-/*
-
- */
-
-#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
-
-/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
-/* short time we actually need it.. */
-
-static int snd_sgalaxy_sbdsp_reset(unsigned long port)
-{
-       int i;
-
-       outb(1, SBP1(port, RESET));
-       udelay(10);
-       outb(0, SBP1(port, RESET));
-       udelay(30);
-       for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++);
-       if (inb(SBP1(port, READ)) != 0xaa) {
-               snd_printd("sb_reset: failed at 0x%lx!!!\n", port);
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
-                                              unsigned char val)
-{
-       int i;
-               
-       for (i = 10000; i; i--)
-               if ((inb(SBP1(port, STATUS)) & 0x80) == 0) {
-                       outb(val, SBP1(port, COMMAND));
-                       return 1;
-               }
-
-       return 0;
-}
-
-static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
-{
-       return IRQ_NONE;
-}
-
-static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
-{
-       static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 
-                                      0x10, 0x18, 0x20, -1, -1, -1, -1};
-       static int dma_bits[] = {1, 2, 0, 3};
-       int tmp, tmp1;
-
-       if ((tmp = inb(port + 3)) == 0xff)
-       {
-               snd_printdd("I/O address dead (0x%lx)\n", port);
-               return 0;
-       }
-#if 0
-       snd_printdd("WSS signature = 0x%x\n", tmp);
-#endif
-
-        if ((tmp & 0x3f) != 0x04 &&
-            (tmp & 0x3f) != 0x0f &&
-            (tmp & 0x3f) != 0x00) {
-               snd_printdd("No WSS signature detected on port 0x%lx\n",
-                           port + 3);
-               return 0;
-       }
-
-#if 0
-       snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
-#endif
-
-        /* initialize IRQ for WSS codec */
-        tmp = interrupt_bits[irq % 16];
-        if (tmp < 0)
-                return -EINVAL;
-
-       if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) {
-               snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq);
-               return -EIO;
-       }
-
-        outb(tmp | 0x40, port);
-        tmp1 = dma_bits[dma % 4];
-        outb(tmp | tmp1, port);
-
-       free_irq(irq, NULL);
-
-       return 0;
-}
-
-static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
-{
-#if 0
-       snd_printdd(PFX "switching to WSS mode\n");
-#endif
-
-       /* switch to WSS mode */
-       snd_sgalaxy_sbdsp_reset(sbport[dev]);
-
-       snd_sgalaxy_sbdsp_command(sbport[dev], 9);
-       snd_sgalaxy_sbdsp_command(sbport[dev], 0);
-
-       udelay(400);
-       return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
-}
-
-static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
-WSS_DOUBLE("Aux Playback Switch", 0,
-               SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
-WSS_DOUBLE("Aux Playback Volume", 0,
-               SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
-};
-
-static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
-{
-       struct snd_card *card = chip->card;
-       struct snd_ctl_elem_id id1, id2;
-       unsigned int idx;
-       int err;
-
-       memset(&id1, 0, sizeof(id1));
-       memset(&id2, 0, sizeof(id2));
-       id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       /* reassign AUX0 to LINE */
-       strcpy(id1.name, "Aux Playback Switch");
-       strcpy(id2.name, "Line Playback Switch");
-       if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-               return err;
-       strcpy(id1.name, "Aux Playback Volume");
-       strcpy(id2.name, "Line Playback Volume");
-       if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-               return err;
-       /* reassign AUX1 to FM */
-       strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
-       strcpy(id2.name, "FM Playback Switch");
-       if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-               return err;
-       strcpy(id1.name, "Aux Playback Volume");
-       strcpy(id2.name, "FM Playback Volume");
-       if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-               return err;
-       /* build AUX2 input */
-       for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
-               err = snd_ctl_add(card,
-                               snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
-               if (err < 0)
-                       return err;
-       }
-       return 0;
-}
-
-static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
-{
-       if (!enable[dev])
-               return 0;
-       if (sbport[dev] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR PFX "specify SB port\n");
-               return 0;
-       }
-       if (wssport[dev] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR PFX "specify WSS port\n");
-               return 0;
-       }
-       return 1;
-}
-
-static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
-{
-       static int possible_irqs[] = {7, 9, 10, 11, -1};
-       static int possible_dmas[] = {1, 3, 0, -1};
-       int err, xirq, xdma1;
-       struct snd_card *card;
-       struct snd_wss *chip;
-
-       err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
-       if (err < 0)
-               return err;
-
-       xirq = irq[dev];
-       if (xirq == SNDRV_AUTO_IRQ) {
-               if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-                       snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-                       err = -EBUSY;
-                       goto _err;
-               }
-       }
-       xdma1 = dma1[dev];
-        if (xdma1 == SNDRV_AUTO_DMA) {
-               if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-                       snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
-                       err = -EBUSY;
-                       goto _err;
-               }
-       }
-
-       if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
-               goto _err;
-
-       err = snd_wss_create(card, wssport[dev] + 4, -1,
-                            xirq, xdma1, -1,
-                            WSS_HW_DETECT, 0, &chip);
-       if (err < 0)
-               goto _err;
-       card->private_data = chip;
-
-       err = snd_wss_pcm(chip, 0, NULL);
-       if (err < 0) {
-               snd_printdd(PFX "error creating new WSS PCM device\n");
-               goto _err;
-       }
-       err = snd_wss_mixer(chip);
-       if (err < 0) {
-               snd_printdd(PFX "error creating new WSS mixer\n");
-               goto _err;
-       }
-       if ((err = snd_sgalaxy_mixer(chip)) < 0) {
-               snd_printdd(PFX "the mixer rewrite failed\n");
-               goto _err;
-       }
-
-       strcpy(card->driver, "Sound Galaxy");
-       strcpy(card->shortname, "Sound Galaxy");
-       sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
-               wssport[dev], xirq, xdma1);
-
-       snd_card_set_dev(card, devptr);
-
-       if ((err = snd_card_register(card)) < 0)
-               goto _err;
-
-       dev_set_drvdata(devptr, card);
-       return 0;
-
- _err:
-       snd_card_free(card);
-       return err;
-}
-
-static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
-{
-       snd_card_free(dev_get_drvdata(devptr));
-       dev_set_drvdata(devptr, NULL);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
-                              pm_message_t state)
-{
-       struct snd_card *card = dev_get_drvdata(pdev);
-       struct snd_wss *chip = card->private_data;
-
-       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       chip->suspend(chip);
-       return 0;
-}
-
-static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
-{
-       struct snd_card *card = dev_get_drvdata(pdev);
-       struct snd_wss *chip = card->private_data;
-
-       chip->resume(chip);
-       snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
-       snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
-
-       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-       return 0;
-}
-#endif
-
-#define DEV_NAME "sgalaxy"
-
-static struct isa_driver snd_sgalaxy_driver = {
-       .match          = snd_sgalaxy_match,
-       .probe          = snd_sgalaxy_probe,
-       .remove         = __devexit_p(snd_sgalaxy_remove),
-#ifdef CONFIG_PM
-       .suspend        = snd_sgalaxy_suspend,
-       .resume         = snd_sgalaxy_resume,
-#endif
-       .driver         = {
-               .name   = DEV_NAME
-       },
-};
-
-static int __init alsa_card_sgalaxy_init(void)
-{
-       return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
-}
-
-static void __exit alsa_card_sgalaxy_exit(void)
-{
-       isa_unregister_driver(&snd_sgalaxy_driver);
-}
-
-module_init(alsa_card_sgalaxy_init)
-module_exit(alsa_card_sgalaxy_exit)
index a513651..76c0902 100644 (file)
@@ -545,11 +545,3 @@ config SOUND_KAHLUA
 
 endif  # SOUND_OSS
 
-config SOUND_SH_DAC_AUDIO
-       tristate "SuperH DAC audio support"
-       depends on CPU_SH3 && HIGH_RES_TIMERS
-
-config SOUND_SH_DAC_AUDIO_CHANNEL
-       int "DAC channel"
-       default "1"
-       depends on SOUND_SH_DAC_AUDIO
index 567b8a7..96f14dc 100644 (file)
@@ -9,7 +9,6 @@ obj-$(CONFIG_SOUND_OSS)         += sound.o
 
 # Please leave it as is, cause the link order is significant !
 
-obj-$(CONFIG_SOUND_SH_DAC_AUDIO)       += sh_dac_audio.o
 obj-$(CONFIG_SOUND_AEDSP16)    += aedsp16.o
 obj-$(CONFIG_SOUND_PSS)                += pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)       += trix.o ad1848.o sb_lib.o uart401.o
index c6f2621..a8f626d 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/sound.h>
 #include <linux/slab.h>
 #include <linux/soundcard.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -77,6 +76,7 @@
 /* Boot options
  * 0 = no VRA, 1 = use VRA if codec supports it
  */
+static DEFINE_MUTEX(au1550_ac97_mutex);
 static int      vra = 1;
 module_param(vra, bool, 0);
 MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
@@ -171,7 +171,7 @@ au1550_delay(int msec)
 static u16
 rdcodec(struct ac97_codec *codec, u8 addr)
 {
-       struct au1550_state *s = (struct au1550_state *)codec->private_data;
+       struct au1550_state *s = codec->private_data;
        unsigned long   flags;
        u32             cmd, val;
        u16             data;
@@ -239,7 +239,7 @@ rdcodec(struct ac97_codec *codec, u8 addr)
 static void
 wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
 {
-       struct au1550_state *s = (struct au1550_state *)codec->private_data;
+       struct au1550_state *s = codec->private_data;
        unsigned long   flags;
        u32             cmd, val;
        int             i;
@@ -798,9 +798,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
 static int
 au1550_open_mixdev(struct inode *inode, struct file *file)
 {
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
        file->private_data = &au1550_state;
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
        return 0;
 }
 
@@ -820,13 +820,13 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
 static long
 au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        struct ac97_codec *codec = s->codec;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
        ret = mixdev_ioctl(codec, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
 
        return ret;
 }
@@ -1031,7 +1031,7 @@ copy_dmabuf_user(struct dmabuf *db, char* userbuf, int count, int to_user)
 static ssize_t
 au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        struct dmabuf  *db = &s->dma_adc;
        DECLARE_WAITQUEUE(wait, current);
        ssize_t         ret;
@@ -1111,7 +1111,7 @@ out2:
 static ssize_t
 au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        struct dmabuf  *db = &s->dma_dac;
        DECLARE_WAITQUEUE(wait, current);
        ssize_t         ret = 0;
@@ -1211,7 +1211,7 @@ out2:
 static unsigned int
 au1550_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        unsigned long   flags;
        unsigned int    mask = 0;
 
@@ -1250,12 +1250,12 @@ au1550_poll(struct file *file, struct poll_table_struct *wait)
 static int
 au1550_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        struct dmabuf  *db;
        unsigned long   size;
        int ret = 0;
 
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
        mutex_lock(&s->sem);
        if (vma->vm_flags & VM_WRITE)
                db = &s->dma_dac;
@@ -1283,7 +1283,7 @@ au1550_mmap(struct file *file, struct vm_area_struct *vma)
        db->mapped = 1;
 out:
        mutex_unlock(&s->sem);
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
        return ret;
 }
 
@@ -1342,7 +1342,7 @@ dma_count_done(struct dmabuf *db)
 static int
 au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
        unsigned long   flags;
        audio_buf_info  abinfo;
        count_info      cinfo;
@@ -1781,9 +1781,9 @@ au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
        ret = au1550_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
 
        return ret;
 }
@@ -1804,7 +1804,7 @@ au1550_open(struct inode *inode, struct file *file)
 #endif
 
        file->private_data = s;
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
        /* wait for device to become free */
        mutex_lock(&s->open_mutex);
        while (s->open_mode & file->f_mode) {
@@ -1861,21 +1861,21 @@ au1550_open(struct inode *inode, struct file *file)
 out:
        mutex_unlock(&s->open_mutex);
 out2:
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
        return ret;
 }
 
 static int
 au1550_release(struct inode *inode, struct file *file)
 {
-       struct au1550_state *s = (struct au1550_state *)file->private_data;
+       struct au1550_state *s = file->private_data;
 
-       lock_kernel();
+       mutex_lock(&au1550_ac97_mutex);
 
        if (file->f_mode & FMODE_WRITE) {
-               unlock_kernel();
+               mutex_unlock(&au1550_ac97_mutex);
                drain_dac(s, file->f_flags & O_NONBLOCK);
-               lock_kernel();
+               mutex_lock(&au1550_ac97_mutex);
        }
 
        mutex_lock(&s->open_mutex);
@@ -1892,7 +1892,7 @@ au1550_release(struct inode *inode, struct file *file)
        s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
        mutex_unlock(&s->open_mutex);
        wake_up(&s->open_wait);
-       unlock_kernel();
+       mutex_unlock(&au1550_ac97_mutex);
        return 0;
 }
 
index 6ecd41a..87e2c72 100644 (file)
 #include <linux/init.h>
 #include <linux/soundcard.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 
      *  Declarations
      */
 
+static DEFINE_MUTEX(dmasound_core_mutex);
 int dmasound_catchRadius = 0;
 module_param(dmasound_catchRadius, int, 0);
 
@@ -323,22 +324,22 @@ static struct {
 
 static int mixer_open(struct inode *inode, struct file *file)
 {
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        if (!try_module_get(dmasound.mach.owner)) {
-               unlock_kernel();
+               mutex_unlock(&dmasound_core_mutex);
                return -ENODEV;
        }
        mixer.busy = 1;
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return 0;
 }
 
 static int mixer_release(struct inode *inode, struct file *file)
 {
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        mixer.busy = 0;
        module_put(dmasound.mach.owner);
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return 0;
 }
 
@@ -370,9 +371,9 @@ static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        ret = mixer_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
 
        return ret;
 }
@@ -752,9 +753,9 @@ static int sq_open(struct inode *inode, struct file *file)
 {
        int rc;
 
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        if (!try_module_get(dmasound.mach.owner)) {
-               unlock_kernel();
+               mutex_unlock(&dmasound_core_mutex);
                return -ENODEV;
        }
 
@@ -799,11 +800,11 @@ static int sq_open(struct inode *inode, struct file *file)
                sound_set_format(AFMT_MU_LAW);
        }
 #endif
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return 0;
  out:
        module_put(dmasound.mach.owner);
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return rc;
 }
 
@@ -869,7 +870,7 @@ static int sq_release(struct inode *inode, struct file *file)
 {
        int rc = 0;
 
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
 
        if (file->f_mode & FMODE_WRITE) {
                if (write_sq.busy)
@@ -900,7 +901,7 @@ static int sq_release(struct inode *inode, struct file *file)
        write_sq_wake_up(file); /* checks f_mode */
 #endif /* blocking open() */
 
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
 
        return rc;
 }
@@ -1141,9 +1142,9 @@ static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        ret = sq_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
 
        return ret;
 }
@@ -1257,7 +1258,7 @@ static int state_open(struct inode *inode, struct file *file)
        int len = 0;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        ret = -EBUSY;
        if (state.busy)
                goto out;
@@ -1329,16 +1330,16 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
        state.len = len;
        ret = 0;
 out:
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return ret;
 }
 
 static int state_release(struct inode *inode, struct file *file)
 {
-       lock_kernel();
+       mutex_lock(&dmasound_core_mutex);
        state.busy = 0;
        module_put(dmasound.mach.owner);
-       unlock_kernel();
+       mutex_unlock(&dmasound_core_mutex);
        return 0;
 }
 
index ca942f7..7b5c77b 100644 (file)
@@ -39,7 +39,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/gfp.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -79,6 +79,7 @@
                                         dev.rec_sample_rate /          \
                                         dev.rec_channels)
 
+static DEFINE_MUTEX(msnd_pinnacle_mutex);
 static multisound_dev_t                        dev;
 
 #ifndef HAVE_DSPCODEH
@@ -651,12 +652,12 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        ret = -EINVAL;
 
-       lock_kernel();
+       mutex_lock(&msnd_pinnacle_mutex);
        if (minor == dev.dsp_minor)
                ret = dsp_ioctl(file, cmd, arg);
        else if (minor == dev.mixer_minor)
                ret = mixer_ioctl(cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&msnd_pinnacle_mutex);
 
        return ret;
 }
@@ -761,7 +762,7 @@ static int dev_open(struct inode *inode, struct file *file)
        int minor = iminor(inode);
        int err = 0;
 
-       lock_kernel();
+       mutex_lock(&msnd_pinnacle_mutex);
        if (minor == dev.dsp_minor) {
                if ((file->f_mode & FMODE_WRITE &&
                     test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
@@ -791,7 +792,7 @@ static int dev_open(struct inode *inode, struct file *file)
        } else
                err = -EINVAL;
 out:
-       unlock_kernel();
+       mutex_unlock(&msnd_pinnacle_mutex);
        return err;
 }
 
@@ -800,14 +801,14 @@ static int dev_release(struct inode *inode, struct file *file)
        int minor = iminor(inode);
        int err = 0;
 
-       lock_kernel();
+       mutex_lock(&msnd_pinnacle_mutex);
        if (minor == dev.dsp_minor)
                err = dsp_release(file);
        else if (minor == dev.mixer_minor) {
                /* nothing */
        } else
                err = -EINVAL;
-       unlock_kernel();
+       mutex_unlock(&msnd_pinnacle_mutex);
        return err;
 }
 
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
deleted file mode 100644 (file)
index 479e302..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * sound/oss/sh_dac_audio.c
- *
- * SH DAC based sound :(
- *
- *  Copyright (C) 2004,2005  Andriy Skulysh
- *
- * 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 <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/linkage.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/sound.h>
-#include <linux/smp_lock.h>
-#include <linux/soundcard.h>
-#include <linux/interrupt.h>
-#include <linux/hrtimer.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/clock.h>
-#include <cpu/dac.h>
-#include <asm/machvec.h>
-#include <mach/hp6xx.h>
-#include <asm/hd64461.h>
-
-#define MODNAME "sh_dac_audio"
-
-#define BUFFER_SIZE 48000
-
-static int rate;
-static int empty;
-static char *data_buffer, *buffer_begin, *buffer_end;
-static int in_use, device_major;
-static struct hrtimer hrtimer;
-static ktime_t wakeups_per_second;
-
-static void dac_audio_start_timer(void)
-{
-       hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
-}
-
-static void dac_audio_stop_timer(void)
-{
-       hrtimer_cancel(&hrtimer);
-}
-
-static void dac_audio_reset(void)
-{
-       dac_audio_stop_timer();
-       buffer_begin = buffer_end = data_buffer;
-       empty = 1;
-}
-
-static void dac_audio_sync(void)
-{
-       while (!empty)
-               schedule();
-}
-
-static void dac_audio_start(void)
-{
-       if (mach_is_hp6xx()) {
-               u16 v = __raw_readw(HD64461_GPADR);
-               v &= ~HD64461_GPADR_SPEAKER;
-               __raw_writew(v, HD64461_GPADR);
-       }
-
-       sh_dac_enable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
-}
-static void dac_audio_stop(void)
-{
-       dac_audio_stop_timer();
-
-       if (mach_is_hp6xx()) {
-               u16 v = __raw_readw(HD64461_GPADR);
-               v |= HD64461_GPADR_SPEAKER;
-               __raw_writew(v, HD64461_GPADR);
-       }
-
-       sh_dac_output(0, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
-       sh_dac_disable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
-}
-
-static void dac_audio_set_rate(void)
-{
-       wakeups_per_second = ktime_set(0, 1000000000 / rate);
-}
-
-static int dac_audio_ioctl(struct file *file,
-                          unsigned int cmd, unsigned long arg)
-{
-       int val;
-
-       switch (cmd) {
-       case OSS_GETVERSION:
-               return put_user(SOUND_VERSION, (int *)arg);
-
-       case SNDCTL_DSP_SYNC:
-               dac_audio_sync();
-               return 0;
-
-       case SNDCTL_DSP_RESET:
-               dac_audio_reset();
-               return 0;
-
-       case SNDCTL_DSP_GETFMTS:
-               return put_user(AFMT_U8, (int *)arg);
-
-       case SNDCTL_DSP_SETFMT:
-               return put_user(AFMT_U8, (int *)arg);
-
-       case SNDCTL_DSP_NONBLOCK:
-               spin_lock(&file->f_lock);
-               file->f_flags |= O_NONBLOCK;
-               spin_unlock(&file->f_lock);
-               return 0;
-
-       case SNDCTL_DSP_GETCAPS:
-               return 0;
-
-       case SOUND_PCM_WRITE_RATE:
-               val = *(int *)arg;
-               if (val > 0) {
-                       rate = val;
-                       dac_audio_set_rate();
-               }
-               return put_user(rate, (int *)arg);
-
-       case SNDCTL_DSP_STEREO:
-               return put_user(0, (int *)arg);
-
-       case SOUND_PCM_WRITE_CHANNELS:
-               return put_user(1, (int *)arg);
-
-       case SNDCTL_DSP_SETDUPLEX:
-               return -EINVAL;
-
-       case SNDCTL_DSP_PROFILE:
-               return -EINVAL;
-
-       case SNDCTL_DSP_GETBLKSIZE:
-               return put_user(BUFFER_SIZE, (int *)arg);
-
-       case SNDCTL_DSP_SETFRAGMENT:
-               return 0;
-
-       default:
-               printk(KERN_ERR "sh_dac_audio: unimplemented ioctl=0x%x\n",
-                      cmd);
-               return -EINVAL;
-       }
-       return -EINVAL;
-}
-
-static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
-{
-       int ret;
-
-       lock_kernel();
-       ret = dac_audio_ioctl(file, cmd, arg);
-       unlock_kernel();
-
-       return ret;
-}
-
-static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
-                              loff_t * ppos)
-{
-       int free;
-       int nbytes;
-
-       if (!count) {
-               dac_audio_sync();
-               return 0;
-       }
-
-       free = buffer_begin - buffer_end;
-
-       if (free < 0)
-               free += BUFFER_SIZE;
-       if ((free == 0) && (empty))
-               free = BUFFER_SIZE;
-       if (count > free)
-               count = free;
-       if (buffer_begin > buffer_end) {
-               if (copy_from_user((void *)buffer_end, buf, count))
-                       return -EFAULT;
-
-               buffer_end += count;
-       } else {
-               nbytes = data_buffer + BUFFER_SIZE - buffer_end;
-               if (nbytes > count) {
-                       if (copy_from_user((void *)buffer_end, buf, count))
-                               return -EFAULT;
-                       buffer_end += count;
-               } else {
-                       if (copy_from_user((void *)buffer_end, buf, nbytes))
-                               return -EFAULT;
-                       if (copy_from_user
-                           ((void *)data_buffer, buf + nbytes, count - nbytes))
-                               return -EFAULT;
-                       buffer_end = data_buffer + count - nbytes;
-               }
-       }
-
-       if (empty) {
-               empty = 0;
-               dac_audio_start_timer();
-       }
-
-       return count;
-}
-
-static ssize_t dac_audio_read(struct file *file, char *buf, size_t count,
-                             loff_t * ppos)
-{
-       return -EINVAL;
-}
-
-static int dac_audio_open(struct inode *inode, struct file *file)
-{
-       if (file->f_mode & FMODE_READ)
-               return -ENODEV;
-
-       lock_kernel();
-       if (in_use) {
-               unlock_kernel();
-               return -EBUSY;
-       }
-
-       in_use = 1;
-
-       dac_audio_start();
-       unlock_kernel();
-       return 0;
-}
-
-static int dac_audio_release(struct inode *inode, struct file *file)
-{
-       dac_audio_sync();
-       dac_audio_stop();
-       in_use = 0;
-
-       return 0;
-}
-
-const struct file_operations dac_audio_fops = {
-      .read =          dac_audio_read,
-      .write =         dac_audio_write,
-      .unlocked_ioctl =        dac_audio_unlocked_ioctl,
-      .open =          dac_audio_open,
-      .release =       dac_audio_release,
-};
-
-static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
-{
-       if (!empty) {
-               sh_dac_output(*buffer_begin, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
-               buffer_begin++;
-
-               if (buffer_begin == data_buffer + BUFFER_SIZE)
-                       buffer_begin = data_buffer;
-               if (buffer_begin == buffer_end)
-                       empty = 1;
-       }
-
-       if (!empty)
-               hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
-
-       return HRTIMER_NORESTART;
-}
-
-static int __init dac_audio_init(void)
-{
-       if ((device_major = register_sound_dsp(&dac_audio_fops, -1)) < 0) {
-               printk(KERN_ERR "Cannot register dsp device");
-               return device_major;
-       }
-
-       in_use = 0;
-
-       data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
-       if (data_buffer == NULL)
-               return -ENOMEM;
-
-       dac_audio_reset();
-       rate = 8000;
-       dac_audio_set_rate();
-
-       /* Today: High Resolution Timer driven DAC playback.
-        * The timer callback gets called once per sample. Ouch.
-        *
-        * Future: A much better approach would be to use the
-        * SH7720 CMT+DMAC+DAC hardware combination like this:
-        * - Program sample rate using CMT0 or CMT1
-        * - Program DMAC to use CMT for timing and output to DAC
-        * - Play sound using DMAC, let CPU sleep.
-        * - While at it, rewrite this driver to use ALSA.
-        */
-
-       hrtimer_init(&hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hrtimer.function = sh_dac_audio_timer;
-
-       return 0;
-}
-
-static void __exit dac_audio_exit(void)
-{
-       unregister_sound_dsp(device_major);
-       kfree((void *)data_buffer);
-}
-
-module_init(dac_audio_init);
-module_exit(dac_audio_exit);
-
-MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
-MODULE_DESCRIPTION("SH DAC sound driver");
-MODULE_LICENSE("GPL");
index 07f803e..46c0d03 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/major.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/device.h>
@@ -56,6 +56,7 @@
  * Table for permanently allocated memory (used when unloading the module)
  */
 void *          sound_mem_blocks[MAX_MEM_BLOCKS];
+static DEFINE_MUTEX(soundcard_mutex);
 int             sound_nblocks = 0;
 
 /* Persistent DMA buffers */
@@ -151,7 +152,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
         *      big one anyway, we might as well bandage here..
         */
         
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        
        DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count));
        switch (dev & 0x0f) {
@@ -169,7 +170,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
        case SND_DEV_MIDIN:
                ret = MIDIbuf_read(dev, file, buf, count);
        }
-       unlock_kernel();
+       mutex_unlock(&soundcard_mutex);
        return ret;
 }
 
@@ -178,7 +179,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
        int dev = iminor(file->f_path.dentry->d_inode);
        int ret = -EINVAL;
        
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count));
        switch (dev & 0x0f) {
        case SND_DEV_SEQ:
@@ -196,7 +197,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
                ret =  MIDIbuf_write(dev, file, buf, count);
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&soundcard_mutex);
        return ret;
 }
 
@@ -210,7 +211,7 @@ static int sound_open(struct inode *inode, struct file *file)
                printk(KERN_ERR "Invalid minor device %d\n", dev);
                return -ENXIO;
        }
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        switch (dev & 0x0f) {
        case SND_DEV_CTL:
                dev >>= 4;
@@ -247,15 +248,15 @@ static int sound_open(struct inode *inode, struct file *file)
                retval = -ENXIO;
        }
 
-       unlock_kernel();
-       return 0;
+       mutex_unlock(&soundcard_mutex);
+       return retval;
 }
 
 static int sound_release(struct inode *inode, struct file *file)
 {
        int dev = iminor(inode);
 
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        DEB(printk("sound_release(dev=%d)\n", dev));
        switch (dev & 0x0f) {
        case SND_DEV_CTL:
@@ -280,7 +281,7 @@ static int sound_release(struct inode *inode, struct file *file)
        default:
                printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev);
        }
-       unlock_kernel();
+       mutex_unlock(&soundcard_mutex);
 
        return 0;
 }
@@ -354,7 +355,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        if (cmd == OSS_GETVERSION)
                return __put_user(SOUND_VERSION, (int __user *)p);
        
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 &&   /* Mixer ioctl */
            (dev & 0x0f) != SND_DEV_CTL) {              
                dtype = dev & 0x0f;
@@ -369,7 +370,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        ret = sound_mixer_ioctl(dev >> 4, cmd, p);
                        break;
                }
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return ret;
        }
 
@@ -399,7 +400,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 
        }
-       unlock_kernel();
+       mutex_unlock(&soundcard_mutex);
        return ret;
 }
 
@@ -439,35 +440,35 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
                printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
                return -EINVAL;
        }
-       lock_kernel();
+       mutex_lock(&soundcard_mutex);
        if (vma->vm_flags & VM_WRITE)   /* Map write and read/write to the output buf */
                dmap = audio_devs[dev]->dmap_out;
        else if (vma->vm_flags & VM_READ)
                dmap = audio_devs[dev]->dmap_in;
        else {
                printk(KERN_ERR "Sound: Undefined mmap() access\n");
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EINVAL;
        }
 
        if (dmap == NULL) {
                printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EIO;
        }
        if (dmap->raw_buf == NULL) {
                printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EIO;
        }
        if (dmap->mapping_flags) {
                printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EIO;
        }
        if (vma->vm_pgoff != 0) {
                printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EINVAL;
        }
        size = vma->vm_end - vma->vm_start;
@@ -478,7 +479,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
        if (remap_pfn_range(vma, vma->vm_start,
                        virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT,
                        vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
-               unlock_kernel();
+               mutex_unlock(&soundcard_mutex);
                return -EAGAIN;
        }
 
@@ -490,7 +491,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
        memset(dmap->raw_buf,
               dmap->neutral_byte,
               dmap->bytes_in_use);
-       unlock_kernel();
+       mutex_unlock(&soundcard_mutex);
        return 0;
 }
 
index b15840a..44357d8 100644 (file)
@@ -68,7 +68,6 @@
 #include <linux/delay.h>
 #include <linux/sound.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/soundcard.h>
 #include <linux/ac97_codec.h>
 #include <linux/pci.h>
@@ -94,6 +93,7 @@
 
 struct cs4297a_state;
 
+static DEFINE_MUTEX(swarm_cs4297a_mutex);
 static void stop_dac(struct cs4297a_state *s);
 static void stop_adc(struct cs4297a_state *s);
 static void start_dac(struct cs4297a_state *s);
@@ -1535,7 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
        CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
                  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
 
-       lock_kernel();
+       mutex_lock(&swarm_cs4297a_mutex);
        list_for_each(entry, &cs4297a_devs)
        {
                s = list_entry(entry, struct cs4297a_state, list);
@@ -1547,7 +1547,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
                CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
                        printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
 
-               unlock_kernel();
+               mutex_unlock(&swarm_cs4297a_mutex);
                return -ENODEV;
        }
        VALIDATE_STATE(s);
@@ -1555,7 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
 
        CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
                  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
-       unlock_kernel();
+       mutex_unlock(&swarm_cs4297a_mutex);
 
        return nonseekable_open(inode, file);
 }
@@ -1575,10 +1575,10 @@ static int cs4297a_ioctl_mixdev(struct file *file,
                               unsigned int cmd, unsigned long arg)
 {
        int ret;
-       lock_kernel();
+       mutex_lock(&swarm_cs4297a_mutex);
        ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
                           arg);
-       unlock_kernel();
+       mutex_unlock(&swarm_cs4297a_mutex);
        return ret;
 }
 
@@ -2350,9 +2350,9 @@ static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&swarm_cs4297a_mutex);
        ret = cs4297a_ioctl(file, cmd, arg);
-       unlock_kernel();
+       mutex_unlock(&swarm_cs4297a_mutex);
 
        return ret;
 }
@@ -2509,9 +2509,9 @@ static int cs4297a_open(struct inode *inode, struct file *file)
 {
        int ret;
 
-       lock_kernel();
+       mutex_lock(&swarm_cs4297a_mutex);
        ret = cs4297a_open(inode, file);
-       unlock_kernel();
+       mutex_unlock(&swarm_cs4297a_mutex);
 
        return ret;
 }
index 8cd73cd..643f111 100644 (file)
 #include <linux/init.h>
 
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/wait.h>
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 
 #ifdef VWSND_DEBUG
 
+static DEFINE_MUTEX(vwsnd_mutex);
 static int shut_up = 1;
 
 /*
@@ -2891,11 +2891,11 @@ static long vwsnd_audio_ioctl(struct file *file,
        vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
        int ret;
 
-       lock_kernel();
+       mutex_lock(&vwsnd_mutex);
        mutex_lock(&devc->io_mutex);
        ret = vwsnd_audio_do_ioctl(file, cmd, arg);
        mutex_unlock(&devc->io_mutex);
-       unlock_kernel();
+       mutex_unlock(&vwsnd_mutex);
 
        return ret;
 }
@@ -2922,7 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
        DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
 
-       lock_kernel();
+       mutex_lock(&vwsnd_mutex);
        INC_USE_COUNT;
        for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
                if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
@@ -2930,7 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
        if (devc == NULL) {
                DEC_USE_COUNT;
-               unlock_kernel();
+               mutex_unlock(&vwsnd_mutex);
                return -ENODEV;
        }
 
@@ -2939,13 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
                mutex_unlock(&devc->open_mutex);
                if (file->f_flags & O_NONBLOCK) {
                        DEC_USE_COUNT;
-                       unlock_kernel();
+                       mutex_unlock(&vwsnd_mutex);
                        return -EBUSY;
                }
                interruptible_sleep_on(&devc->open_wait);
                if (signal_pending(current)) {
                        DEC_USE_COUNT;
-                       unlock_kernel();
+                       mutex_unlock(&vwsnd_mutex);
                        return -ERESTARTSYS;
                }
                mutex_lock(&devc->open_mutex);
@@ -2998,7 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
        file->private_data = devc;
        DBGRV();
-       unlock_kernel();
+       mutex_unlock(&vwsnd_mutex);
        return 0;
 }
 
@@ -3012,7 +3012,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
        vwsnd_port_t *wport = NULL, *rport = NULL;
        int err = 0;
 
-       lock_kernel();
+       mutex_lock(&vwsnd_mutex);
        mutex_lock(&devc->io_mutex);
        {
                DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
@@ -3040,7 +3040,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
        wake_up(&devc->open_wait);
        DEC_USE_COUNT;
        DBGR();
-       unlock_kernel();
+       mutex_unlock(&vwsnd_mutex);
        return err;
 }
 
@@ -3068,18 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
        DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
 
        INC_USE_COUNT;
-       lock_kernel();
+       mutex_lock(&vwsnd_mutex);
        for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
                if (devc->mixer_minor == iminor(inode))
                        break;
 
        if (devc == NULL) {
                DEC_USE_COUNT;
-               unlock_kernel();
+               mutex_unlock(&vwsnd_mutex);
                return -ENODEV;
        }
        file->private_data = devc;
-       unlock_kernel();
+       mutex_unlock(&vwsnd_mutex);
        return 0;
 }
 
@@ -3223,7 +3223,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
 
        DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
 
-       lock_kernel();
+       mutex_lock(&vwsnd_mutex);
        mutex_lock(&devc->mix_mutex);
        {
                if ((cmd & ~nrmask) == MIXER_READ(0))
@@ -3234,7 +3234,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
                        retval = -EINVAL;
        }
        mutex_unlock(&devc->mix_mutex);
-       unlock_kernel();
+       mutex_unlock(&vwsnd_mutex);
        return retval;
 }
 
index e7a8cd0..12e3465 100644 (file)
@@ -207,12 +207,12 @@ config SND_CMIPCI
 
 config SND_OXYGEN_LIB
         tristate
-       select SND_PCM
-       select SND_MPU401_UART
 
 config SND_OXYGEN
        tristate "C-Media 8788 (Oxygen)"
        select SND_OXYGEN_LIB
+       select SND_PCM
+       select SND_MPU401_UART
        help
          Say Y here to include support for sound cards based on the
          C-Media CMI8788 (Oxygen HD Audio) chip:
@@ -581,6 +581,8 @@ config SND_HDSPM
 config SND_HIFIER
        tristate "TempoTec HiFier Fantasia"
        select SND_OXYGEN_LIB
+       select SND_PCM
+       select SND_MPU401_UART
        help
          Say Y here to include support for the MediaTek/TempoTec HiFier
          Fantasia sound card.
@@ -815,14 +817,17 @@ config SND_VIA82XX_MODEM
          will be called snd-via82xx-modem.
 
 config SND_VIRTUOSO
-       tristate "Asus Virtuoso 100/200 (Xonar)"
+       tristate "Asus Virtuoso 66/100/200 (Xonar)"
        select SND_OXYGEN_LIB
+       select SND_PCM
+       select SND_MPU401_UART
+       select SND_JACK if INPUT=y || INPUT=SND
        help
          Say Y here to include support for sound cards based on the
-         Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X,
+         Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
          Essence ST (Deluxe), and Essence STX.
-         Support for the DS is experimental.
-         Support for the HDAV1.3 (Deluxe) is very experimental.
+         Support for the HDAV1.3 (Deluxe) is incomplete; for the
+         HDAV1.3 Slim and Xense, missing.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-virtuoso.
index c92f493..557c782 100644 (file)
@@ -23,7 +23,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex)
        if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
                return err;
        memset(&ac97, 0, sizeof(ac97));
-       // Intialize AC97 codec stuff.
+       // Initialize AC97 codec stuff.
        ac97.private_data = vortex;
        ac97.scaps = AC97_SCAP_NO_SPDIF;
        err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
index 14b8d9a..f19c110 100644 (file)
@@ -670,8 +670,9 @@ struct snd_ca0106_details {
                           gpio_type = 2 -> shared side-out/line-in. */
        int i2c_adc;    /* with i2c_adc=1, the driver adds some capture volume
                           controls, phone, mic, line-in and aux. */
-       int spi_dac;    /* spi_dac=1 adds the mute switch for each analog
-                          output, front, rear, etc. */
+       u16 spi_dac;    /* spi_dac = 0 -> no spi interface for DACs
+                          spi_dac = 0x<front><rear><center-lfe><side>
+                          -> specifies DAC id for each channel pair. */
 };
 
 // definition of the chip-specific record
index 0a3d3d6..d2d12c0 100644 (file)
@@ -227,7 +227,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
           .name   = "Audigy SE [SB0570]",
           .gpio_type = 1,
           .i2c_adc = 1,
-          .spi_dac = 1 } ,
+          .spi_dac = 0x4021 } ,
         /* New Audigy LS. Has a different DAC. */
         /* SB0570:
          * CTRL:CA0106-DAT
@@ -238,7 +238,17 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
           .name   = "Audigy SE OEM [SB0570a]",
           .gpio_type = 1,
           .i2c_adc = 1,
-          .spi_dac = 1 } ,
+          .spi_dac = 0x4021 } ,
+       /* Sound Blaster 5.1vx
+        * Tested: Playback on front, rear, center/lfe speakers
+        * Not-Tested: Capture
+        */
+       { .serial = 0x10041102,
+         .name   = "Sound Blaster 5.1vx [SB1070]",
+         .gpio_type = 1,
+         .i2c_adc = 0,
+         .spi_dac = 0x0124
+        } ,
         /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
         /* SB0438
          * CTRL:CA0106-DAT
@@ -254,7 +264,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
           .name   = "MSI K8N Diamond MB",
           .gpio_type = 2,
           .i2c_adc = 1,
-          .spi_dac = 1 } ,
+          .spi_dac = 0x4021 } ,
        /* Giga-byte GA-G1975X mobo
         * Novell bnc#395807
         */
@@ -483,16 +493,18 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
 }
 
 static const int spi_dacd_reg[] = {
-       [PCM_FRONT_CHANNEL]     = SPI_DACD4_REG,
-       [PCM_REAR_CHANNEL]      = SPI_DACD0_REG,
-       [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG,
-       [PCM_UNKNOWN_CHANNEL]   = SPI_DACD1_REG,
+       SPI_DACD0_REG,
+       SPI_DACD1_REG,
+       SPI_DACD2_REG,
+       0,
+       SPI_DACD4_REG,
 };
 static const int spi_dacd_bit[] = {
-       [PCM_FRONT_CHANNEL]     = SPI_DACD4_BIT,
-       [PCM_REAR_CHANNEL]      = SPI_DACD0_BIT,
-       [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT,
-       [PCM_UNKNOWN_CHANNEL]   = SPI_DACD1_BIT,
+       SPI_DACD0_BIT,
+       SPI_DACD1_BIT,
+       SPI_DACD2_BIT,
+       0,
+       SPI_DACD4_BIT,
 };
 
 static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
@@ -504,6 +516,45 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
        }
 }
 
+static int snd_ca0106_channel_dac(struct snd_ca0106_details *details,
+                                 int channel_id)
+{
+       switch (channel_id) {
+       case PCM_FRONT_CHANNEL:
+               return (details->spi_dac & 0xf000) >> (4 * 3);
+       case PCM_REAR_CHANNEL:
+               return (details->spi_dac & 0x0f00) >> (4 * 2);
+       case PCM_CENTER_LFE_CHANNEL:
+               return (details->spi_dac & 0x00f0) >> (4 * 1);
+       case PCM_UNKNOWN_CHANNEL:
+               return (details->spi_dac & 0x000f) >> (4 * 0);
+       default:
+               snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n",
+                          channel_id);
+       }
+       return 0;
+}
+
+static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id,
+                                   int power)
+{
+       if (chip->details->spi_dac) {
+               const int dac = snd_ca0106_channel_dac(chip->details,
+                                                      channel_id);
+               const int reg = spi_dacd_reg[dac];
+               const int bit = spi_dacd_bit[dac];
+
+               if (power)
+                       /* Power up */
+                       chip->spi_dac_reg[reg] &= ~bit;
+               else
+                       /* Power down */
+                       chip->spi_dac_reg[reg] |= bit;
+               return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
+       }
+       return 0;
+}
+
 /* open_playback callback */
 static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
                                                int channel_id)
@@ -543,12 +594,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
                 return err;
        snd_pcm_set_sync(substream);
 
-       if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) {
-               const int reg = spi_dacd_reg[channel_id];
-
-               /* Power up dac */
-               chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id];
-               err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
+       /* Front channel dac should already be on */
+       if (channel_id != PCM_FRONT_CHANNEL) {
+               err = snd_ca0106_pcm_power_dac(chip, channel_id, 1);
                if (err < 0)
                        return err;
        }
@@ -568,13 +616,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
 
        restore_spdif_bits(chip, epcm->channel_id);
 
-       if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) {
-               const int reg = spi_dacd_reg[epcm->channel_id];
-
-               /* Power down DAC */
-               chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id];
-               snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
+       /* Front channel dac should stay on */
+       if (epcm->channel_id != PCM_FRONT_CHANNEL) {
+               int err;
+               err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0);
+               if (err < 0)
+                       return err;
        }
+
        /* FIXME: maybe zero others */
        return 0;
 }
@@ -1002,29 +1051,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
        struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ca0106_pcm *epcm = runtime->private_data;
-       snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
+       unsigned int ptr, prev_ptr;
        int channel = epcm->channel_id;
+       int timeout = 10;
 
        if (!epcm->running)
                return 0;
 
-       ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
-       ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
-       ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
-       if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel);
-       ptr2 = bytes_to_frames(runtime, ptr1);
-       ptr2+= (ptr4 >> 3) * runtime->period_size;
-       ptr=ptr2;
-        if (ptr >= runtime->buffer_size)
-               ptr -= runtime->buffer_size;
-       /*
-       printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
-              "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
-              ptr1, ptr2, ptr, (int)runtime->buffer_size,
-              (int)runtime->period_size, (int)runtime->frame_bits,
-              (int)runtime->rate);
-       */
-       return ptr;
+       prev_ptr = -1;
+       do {
+               ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
+               ptr = (ptr >> 3) * runtime->period_size;
+               ptr += bytes_to_frames(runtime,
+                       snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel));
+               if (ptr >= runtime->buffer_size)
+                       ptr -= runtime->buffer_size;
+               if (prev_ptr == ptr)
+                       return ptr;
+               prev_ptr = ptr;
+       } while (--timeout);
+       snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n");
+       return 0;
 }
 
 /* pointer_capture callback */
@@ -1362,7 +1409,7 @@ static unsigned int spi_dac_init[] = {
        SPI_REG(12,             0x00),
        SPI_REG(SPI_LDA4_REG,   SPI_DA_BIT_0dB),
        SPI_REG(SPI_RDA4_REG,   SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE),
-       SPI_REG(SPI_DACD4_REG,  0x00),
+       SPI_REG(SPI_DACD4_REG,  SPI_DACD4_BIT),
 };
 
 static unsigned int i2c_adc_init[][2] = {
@@ -1541,7 +1588,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
                /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
        }
 
-       if (chip->details->spi_dac == 1) {
+       if (chip->details->spi_dac) {
                /* The SB0570 use SPI to control DAC. */
                int size, n;
 
@@ -1553,6 +1600,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
                        if (reg < ARRAY_SIZE(chip->spi_dac_reg))
                                chip->spi_dac_reg[reg] = spi_dac_init[n];
                }
+
+               /* Enable front dac only */
+               snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1);
        }
 }
 
index 85fd315..630aa49 100644 (file)
@@ -676,28 +676,65 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
         I2C_VOLUME("Aux Capture Volume", 3),
 };
 
-#define SPI_SWITCH(xname,reg,bit) \
-{                                                              \
-       .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,    \
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
-       .info   = spi_mute_info,                                \
-       .get    = spi_mute_get,                                 \
-       .put    = spi_mute_put,                                 \
-       .private_value = (reg<<SPI_REG_SHIFT) | (bit)           \
-}
-
-static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
-__devinitdata = {
-       SPI_SWITCH("Analog Front Playback Switch",
-                  SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
-       SPI_SWITCH("Analog Rear Playback Switch",
-                  SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
-       SPI_SWITCH("Analog Center/LFE Playback Switch",
-                  SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
-       SPI_SWITCH("Analog Side Playback Switch",
-                  SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
+static const int spi_dmute_reg[] = {
+       SPI_DMUTE0_REG,
+       SPI_DMUTE1_REG,
+       SPI_DMUTE2_REG,
+       0,
+       SPI_DMUTE4_REG,
+};
+static const int spi_dmute_bit[] = {
+       SPI_DMUTE0_BIT,
+       SPI_DMUTE1_BIT,
+       SPI_DMUTE2_BIT,
+       0,
+       SPI_DMUTE4_BIT,
 };
 
+static struct snd_kcontrol_new __devinit
+snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
+                             int channel_id)
+{
+       struct snd_kcontrol_new spi_switch = {0};
+       int reg, bit;
+       int dac_id;
+
+       spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
+       spi_switch.info = spi_mute_info;
+       spi_switch.get = spi_mute_get;
+       spi_switch.put = spi_mute_put;
+
+       switch (channel_id) {
+       case PCM_FRONT_CHANNEL:
+               spi_switch.name = "Analog Front Playback Switch";
+               dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
+               break;
+       case PCM_REAR_CHANNEL:
+               spi_switch.name = "Analog Rear Playback Switch";
+               dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
+               break;
+       case PCM_CENTER_LFE_CHANNEL:
+               spi_switch.name = "Analog Center/LFE Playback Switch";
+               dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
+               break;
+       case PCM_UNKNOWN_CHANNEL:
+               spi_switch.name = "Analog Side Playback Switch";
+               dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
+               break;
+       default:
+               /* Unused channel */
+               spi_switch.name = NULL;
+               dac_id = 0;
+       }
+       reg = spi_dmute_reg[dac_id];
+       bit = spi_dmute_bit[dac_id];
+
+       spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
+
+       return spi_switch;
+}
+
 static int __devinit remove_ctl(struct snd_card *card, const char *name)
 {
        struct snd_ctl_elem_id id;
@@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
                if (err < 0)
                        return err;
        }
-       if (emu->details->spi_dac == 1)
-               ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
+       if (emu->details->spi_dac) {
+               int i;
+               for (i = 0;; i++) {
+                       struct snd_kcontrol_new ctl;
+                       ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
+                       if (!ctl.name)
+                               break;
+                       err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
+                       if (err < 0)
+                               return err;
+               }
+       }
 
        /* Create virtual master controls */
        vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
@@ -845,7 +892,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
                return err;
        add_slaves(card, vmaster, slave_vols);
 
-       if (emu->details->spi_dac == 1) {
+       if (emu->details->spi_dac) {
                vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
                                                      NULL);
                if (!vmaster)
index 8578c70..bab5648 100644 (file)
@@ -321,7 +321,7 @@ static struct snd_rawmidi_ops snd_emu10k1_midi_input =
 
 static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
 {
-       struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)rmidi->private_data;
+       struct snd_emu10k1_midi *midi = rmidi->private_data;
        midi->interrupt = NULL;
        midi->rmidi = NULL;
 }
index 9194c3c..0ea5cc6 100644 (file)
@@ -119,47 +119,20 @@ config SND_HDA_CODEC_VIA
          snd-hda-codec-via.
          This module is automatically loaded at probing.
 
-config SND_HDA_CODEC_ATIHDMI
-       bool "Build ATI HDMI HD-audio codec support"
-       default y
-       help
-         Say Y here to include ATI HDMI HD-audio codec support in
-         snd-hda-intel driver, such as ATI RS600 HDMI.
-
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-atihdmi.
-         This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_NVHDMI
-       bool "Build NVIDIA HDMI HD-audio codec support"
-       default y
-       help
-         Say Y here to include NVIDIA HDMI HD-audio codec support in
-         snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
-
-         When the HD-audio driver is built as a module, the codec
-         support code is also built as another module,
-         snd-hda-codec-nvhdmi.
-         This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_INTELHDMI
-       bool "Build INTEL HDMI HD-audio codec support"
+config SND_HDA_CODEC_HDMI
+       bool "Build HDMI/DisplayPort HD-audio codec support"
        select SND_DYNAMIC_MINORS
        default y
        help
-         Say Y here to include INTEL HDMI HD-audio codec support in
-         snd-hda-intel driver, such as Eaglelake integrated HDMI.
+         Say Y here to include HDMI and DisplayPort HD-audio codec
+         support in snd-hda-intel driver.  This includes all AMD/ATI,
+         Intel and Nvidia HDMI/DisplayPort codecs.
 
          When the HD-audio driver is built as a module, the codec
          support code is also built as another module,
-         snd-hda-codec-intelhdmi.
+         snd-hda-codec-hdmi.
          This module is automatically loaded at probing.
 
-config SND_HDA_ELD
-       def_bool y
-       depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
-
 config SND_HDA_CODEC_CIRRUS
        bool "Build Cirrus Logic codec support"
        depends on SND_HDA_INTEL
index 24bc195..17ef365 100644 (file)
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
 snd-hda-codec-y := hda_codec.o
 snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
 snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
 snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
 snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
 
@@ -12,13 +11,11 @@ snd-hda-codec-cmedia-objs :=        patch_cmedia.o
 snd-hda-codec-analog-objs :=   patch_analog.o
 snd-hda-codec-idt-objs :=      patch_sigmatel.o
 snd-hda-codec-si3054-objs :=   patch_si3054.o
-snd-hda-codec-atihdmi-objs :=  patch_atihdmi.o
 snd-hda-codec-cirrus-objs :=   patch_cirrus.o
 snd-hda-codec-ca0110-objs :=   patch_ca0110.o
 snd-hda-codec-conexant-objs := patch_conexant.o
 snd-hda-codec-via-objs :=      patch_via.o
-snd-hda-codec-nvhdmi-objs :=   patch_nvhdmi.o
-snd-hda-codec-intelhdmi-objs :=        patch_intelhdmi.o
+snd-hda-codec-hdmi-objs :=     patch_hdmi.o hda_eld.o
 
 # common driver
 obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
@@ -39,9 +36,6 @@ endif
 ifdef CONFIG_SND_HDA_CODEC_SI3054
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
 endif
-ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
-endif
 ifdef CONFIG_SND_HDA_CODEC_CIRRUS
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o
 endif
@@ -54,11 +48,8 @@ endif
 ifdef CONFIG_SND_HDA_CODEC_VIA
 obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
 endif
-ifdef CONFIG_SND_HDA_CODEC_NVHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_INTELHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o
+ifdef CONFIG_SND_HDA_CODEC_HDMI
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
 endif
 
 # this must be the last entry after codec drivers;
index 1482921..644e3f1 100644 (file)
@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
        struct hda_codec *c;
        struct hda_cvt_setup *p;
        unsigned int oldval, newval;
+       int type;
        int i;
 
        if (!nid)
@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
        p->dirty = 0;
 
        /* make other inactive cvts with the same stream-tag dirty */
+       type = get_wcaps_type(get_wcaps(codec, nid));
        list_for_each_entry(c, &codec->bus->codec_list, list) {
                for (i = 0; i < c->cvt_setups.used; i++) {
                        p = snd_array_elem(&c->cvt_setups, i);
-                       if (!p->active && p->stream_tag == stream_tag)
+                       if (!p->active && p->stream_tag == stream_tag &&
+                           get_wcaps_type(get_wcaps(codec, p->nid)) == type)
                                p->dirty = 1;
                }
        }
@@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
        if (!nid)
                return;
 
+       if (codec->no_sticky_stream)
+               do_now = 1;
+
        snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
        p = get_hda_cvt_setup(codec, nid);
        if (p) {
@@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        hda_nid_t nid = get_amp_nid(kcontrol);
        int dir = get_amp_direction(kcontrol);
        unsigned int ofs = get_amp_offset(kcontrol);
+       bool min_mute = get_amp_min_mute(kcontrol);
        u32 caps, val1, val2;
 
        if (size < 4 * sizeof(unsigned int))
@@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
        val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
        val1 += ofs;
        val1 = ((int)val1) * ((int)val2);
+       if (min_mute)
+               val2 |= TLV_DB_SCALE_MUTE;
        if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
                return -EFAULT;
        if (put_user(2 * sizeof(unsigned int), _tlv + 1))
@@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
                change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
                                                   HDA_AMP_MUTE,
                                                   *valp ? 0 : HDA_AMP_MUTE);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       if (codec->patch_ops.check_power_status)
-               codec->patch_ops.check_power_status(codec, nid);
-#endif
+       hda_call_check_power_status(codec, nid);
        snd_hda_power_down(codec);
        return change;
 }
@@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
 }
 
 
+/* add the found input-pin to the cfg->inputs[] table */
+static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
+                                  int type)
+{
+       if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
+               cfg->inputs[cfg->num_inputs].pin = nid;
+               cfg->inputs[cfg->num_inputs].type = type;
+               cfg->num_inputs++;
+       }
+}
+
+/* sort inputs in the order of AUTO_PIN_* type */
+static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
+{
+       int i, j;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               for (j = i + 1; j < cfg->num_inputs; j++) {
+                       if (cfg->inputs[i].type > cfg->inputs[j].type) {
+                               struct auto_pin_cfg_item tmp;
+                               tmp = cfg->inputs[i];
+                               cfg->inputs[i] = cfg->inputs[j];
+                               cfg->inputs[j] = tmp;
+                       }
+               }
+       }
+}
+
 /*
  * Parse all pin widgets and store the useful pin nids to cfg
  *
@@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
  * output, i.e. to line_out_pins[0].  So, line_outs is always positive
  * if any analog output exists.
  *
- * The analog input pins are assigned to input_pins array.
+ * The analog input pins are assigned to inputs array.
  * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
  * respectively.
  */
@@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
        short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
        short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
        short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
+       int i;
 
        memset(cfg, 0, sizeof(*cfg));
 
@@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                        sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
                        cfg->hp_outs++;
                        break;
-               case AC_JACK_MIC_IN: {
-                       int preferred, alt;
-                       if (loc == AC_JACK_LOC_FRONT ||
-                           (loc & 0x30) == AC_JACK_LOC_INTERNAL) {
-                               preferred = AUTO_PIN_FRONT_MIC;
-                               alt = AUTO_PIN_MIC;
-                       } else {
-                               preferred = AUTO_PIN_MIC;
-                               alt = AUTO_PIN_FRONT_MIC;
-                       }
-                       if (!cfg->input_pins[preferred])
-                               cfg->input_pins[preferred] = nid;
-                       else if (!cfg->input_pins[alt])
-                               cfg->input_pins[alt] = nid;
+               case AC_JACK_MIC_IN:
+                       add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
                        break;
-               }
                case AC_JACK_LINE_IN:
-                       if (loc == AC_JACK_LOC_FRONT)
-                               cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
-                       else
-                               cfg->input_pins[AUTO_PIN_LINE] = nid;
+                       add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
                        break;
                case AC_JACK_CD:
-                       cfg->input_pins[AUTO_PIN_CD] = nid;
+                       add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
                        break;
                case AC_JACK_AUX:
-                       cfg->input_pins[AUTO_PIN_AUX] = nid;
+                       add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
                        break;
                case AC_JACK_SPDIF_OUT:
                case AC_JACK_DIG_OTHER_OUT:
@@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                        memmove(sequences_hp + i, sequences_hp + i + 1,
                                sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
                }
+               memset(cfg->hp_pins + cfg->hp_outs, 0,
+                      sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
        }
 
        /* sort by sequence */
@@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
        sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
                              cfg->hp_outs);
 
-       /* if we have only one mic, make it AUTO_PIN_MIC */
-       if (!cfg->input_pins[AUTO_PIN_MIC] &&
-           cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
-               cfg->input_pins[AUTO_PIN_MIC] =
-                       cfg->input_pins[AUTO_PIN_FRONT_MIC];
-               cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
-       }
-       /* ditto for line-in */
-       if (!cfg->input_pins[AUTO_PIN_LINE] &&
-           cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
-               cfg->input_pins[AUTO_PIN_LINE] =
-                       cfg->input_pins[AUTO_PIN_FRONT_LINE];
-               cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
-       }
-
        /*
         * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
         * as a primary output
@@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
                break;
        }
 
+       sort_autocfg_input_pins(cfg);
+
        /*
         * debug prints of the parsed results
         */
@@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
        if (cfg->dig_outs)
                snd_printd("   dig-out=0x%x/0x%x\n",
                           cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
-       snd_printd("   inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x,"
-                  " cd=0x%x, aux=0x%x\n",
-                  cfg->input_pins[AUTO_PIN_MIC],
-                  cfg->input_pins[AUTO_PIN_FRONT_MIC],
-                  cfg->input_pins[AUTO_PIN_LINE],
-                  cfg->input_pins[AUTO_PIN_FRONT_LINE],
-                  cfg->input_pins[AUTO_PIN_CD],
-                  cfg->input_pins[AUTO_PIN_AUX]);
+       snd_printd("   inputs:");
+       for (i = 0; i < cfg->num_inputs; i++) {
+               snd_printdd(" %s=0x%x",
+                           hda_get_autocfg_input_label(codec, cfg, i),
+                           cfg->inputs[i].pin);
+       }
+       snd_printd("\n");
        if (cfg->dig_in_pin)
                snd_printd("   dig-in=0x%x\n", cfg->dig_in_pin);
 
@@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
 
-/* labels for input pins */
-const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
-       "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
-};
-EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
+int snd_hda_get_input_pin_attr(unsigned int def_conf)
+{
+       unsigned int loc = get_defcfg_location(def_conf);
+       unsigned int conn = get_defcfg_connect(def_conf);
+       if (conn == AC_JACK_PORT_NONE)
+               return INPUT_PIN_ATTR_UNUSED;
+       /* Windows may claim the internal mic to be BOTH, too */
+       if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
+               return INPUT_PIN_ATTR_INT;
+       if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
+               return INPUT_PIN_ATTR_INT;
+       if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
+               return INPUT_PIN_ATTR_DOCK;
+       if (loc == AC_JACK_LOC_REAR)
+               return INPUT_PIN_ATTR_REAR;
+       if (loc == AC_JACK_LOC_FRONT)
+               return INPUT_PIN_ATTR_FRONT;
+       return INPUT_PIN_ATTR_NORMAL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
+
+/**
+ * hda_get_input_pin_label - Give a label for the given input pin
+ *
+ * When check_location is true, the function checks the pin location
+ * for mic and line-in pins, and set an appropriate prefix like "Front",
+ * "Rear", "Internal".
+ */
+
+const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
+                                       int check_location)
+{
+       unsigned int def_conf;
+       static const char *mic_names[] = {
+               "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
+       };
+       int attr;
+
+       def_conf = snd_hda_codec_get_pincfg(codec, pin);
+
+       switch (get_defcfg_device(def_conf)) {
+       case AC_JACK_MIC_IN:
+               if (!check_location)
+                       return "Mic";
+               attr = snd_hda_get_input_pin_attr(def_conf);
+               if (!attr)
+                       return "None";
+               return mic_names[attr - 1];
+       case AC_JACK_LINE_IN:
+               if (!check_location)
+                       return "Line";
+               attr = snd_hda_get_input_pin_attr(def_conf);
+               if (!attr)
+                       return "None";
+               if (attr == INPUT_PIN_ATTR_DOCK)
+                       return "Dock Line";
+               return "Line";
+       case AC_JACK_AUX:
+               return "Aux";
+       case AC_JACK_CD:
+               return "CD";
+       case AC_JACK_SPDIF_IN:
+               return "SPDIF In";
+       case AC_JACK_DIG_OTHER_IN:
+               return "Digital In";
+       default:
+               return "Misc";
+       }
+}
+EXPORT_SYMBOL_HDA(hda_get_input_pin_label);
+
+/* Check whether the location prefix needs to be added to the label.
+ * If all mic-jacks are in the same location (e.g. rear panel), we don't
+ * have to put "Front" prefix to each label.  In such a case, returns false.
+ */
+static int check_mic_location_need(struct hda_codec *codec,
+                                  const struct auto_pin_cfg *cfg,
+                                  int input)
+{
+       unsigned int defc;
+       int i, attr, attr2;
+
+       defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
+       attr = snd_hda_get_input_pin_attr(defc);
+       /* for internal or docking mics, we need locations */
+       if (attr <= INPUT_PIN_ATTR_NORMAL)
+               return 1;
+
+       attr = 0;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
+               attr2 = snd_hda_get_input_pin_attr(defc);
+               if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
+                       if (attr && attr != attr2)
+                               return 1; /* different locations found */
+                       attr = attr2;
+               }
+       }
+       return 0;
+}
+
+/**
+ * hda_get_autocfg_input_label - Get a label for the given input
+ *
+ * Get a label for the given input pin defined by the autocfg item.
+ * Unlike hda_get_input_pin_label(), this function checks all inputs
+ * defined in autocfg and avoids the redundant mic/line prefix as much as
+ * possible.
+ */
+const char *hda_get_autocfg_input_label(struct hda_codec *codec,
+                                       const struct auto_pin_cfg *cfg,
+                                       int input)
+{
+       int type = cfg->inputs[input].type;
+       int has_multiple_pins = 0;
+
+       if ((input > 0 && cfg->inputs[input - 1].type == type) ||
+           (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
+               has_multiple_pins = 1;
+       if (has_multiple_pins && type == AUTO_PIN_MIC)
+               has_multiple_pins &= check_mic_location_need(codec, cfg, input);
+       return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
+                                      has_multiple_pins);
+}
+EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
+
+/**
+ * snd_hda_add_imux_item - Add an item to input_mux
+ *
+ * When the same label is used already in the existing items, the number
+ * suffix is appended to the label.  This label index number is stored
+ * to type_idx when non-NULL pointer is given.
+ */
+int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+                         int index, int *type_idx)
+{
+       int i, label_idx = 0;
+       if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
+               snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
+               return -EINVAL;
+       }
+       for (i = 0; i < imux->num_items; i++) {
+               if (!strncmp(label, imux->items[i].label, strlen(label)))
+                       label_idx++;
+       }
+       if (type_idx)
+               *type_idx = label_idx;
+       if (label_idx > 0)
+               snprintf(imux->items[imux->num_items].label,
+                        sizeof(imux->items[imux->num_items].label),
+                        "%s %d", label, label_idx);
+       else
+               strlcpy(imux->items[imux->num_items].label, label,
+                       sizeof(imux->items[imux->num_items].label));
+       imux->items[imux->num_items].index = index;
+       imux->num_items++;
+       return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
 
 
 #ifdef CONFIG_PM
index 62c7022..fdf8d44 100644 (file)
@@ -850,6 +850,7 @@ struct hda_codec {
        unsigned int pin_amp_workaround:1; /* pin out-amp takes index
                                            * (e.g. Conexant codecs)
                                            */
+       unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
        unsigned int pins_shutup:1;     /* pins are shut up */
        unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -989,6 +990,18 @@ int snd_hda_suspend(struct hda_bus *bus);
 int snd_hda_resume(struct hda_bus *bus);
 #endif
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static inline
+int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
+{
+       if (codec->patch_ops.check_power_status)
+               return codec->patch_ops.check_power_status(codec, nid);
+       return 0;
+}
+#else  
+#define hda_call_check_power_status(codec, nid)                0
+#endif
+
 /*
  * get widget information
  */
index 26c3ade..cb0c23a 100644 (file)
@@ -332,7 +332,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
        return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
                                                 AC_DIPSIZE_ELD_BUF);
 }
-EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
 
 int snd_hdmi_get_eld(struct hdmi_eld *eld,
                     struct hda_codec *codec, hda_nid_t nid)
@@ -368,7 +367,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
        kfree(buf);
        return ret;
 }
-EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
 
 static void hdmi_show_short_audio_desc(struct cea_sad *a)
 {
@@ -407,7 +405,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
        }
        buf[j] = '\0';  /* necessary when j == 0 */
 }
-EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
 
 void snd_hdmi_show_eld(struct hdmi_eld *e)
 {
@@ -426,7 +423,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e)
        for (i = 0; i < e->sad_count; i++)
                hdmi_show_short_audio_desc(e->sad + i);
 }
-EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
 
 #ifdef CONFIG_PROC_FS
 
@@ -585,7 +581,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
 
        return 0;
 }
-EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
 
 void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
 {
@@ -594,7 +589,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
                eld->proc_entry = NULL;
        }
 }
-EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
 
 #endif /* CONFIG_PROC_FS */
 
@@ -645,4 +639,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
        pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
        pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
 }
-EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info);
index 5ea2128..fb0582f 100644 (file)
@@ -61,7 +61,6 @@ struct hda_gspec {
        struct hda_gnode *cap_vol_node; /* Node for capture volume */
        unsigned int cur_cap_src;       /* current capture source */
        struct hda_input_mux input_mux;
-       char cap_labels[HDA_MAX_NUM_INPUTS][16];
 
        unsigned int def_amp_in_caps;
        unsigned int def_amp_out_caps;
@@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
  * returns 0 if not found, 1 if found, or a negative error code.
  */
 static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
-                              struct hda_gnode *node)
+                              struct hda_gnode *node, int idx)
 {
        int i, err;
        unsigned int pinctl;
-       char *label;
        const char *type;
 
        if (node->checked)
@@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
                        child = hda_get_node(spec, node->conn_list[i]);
                        if (! child)
                                continue;
-                       err = parse_adc_sub_nodes(codec, spec, child);
+                       err = parse_adc_sub_nodes(codec, spec, child, idx);
                        if (err < 0)
                                return err;
                        if (err > 0) {
@@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
                        return 0;
                type = "Input";
        }
-       label = spec->cap_labels[spec->input_mux.num_items];
-       strcpy(label, type);
-       spec->input_mux.items[spec->input_mux.num_items].label = label;
+       snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL);
 
        /* unmute the PIN external input */
        unmute_input(codec, node, 0); /* index = 0? */
@@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
        return 1; /* found */
 }
 
-/* add a capture source element */
-static void add_cap_src(struct hda_gspec *spec, int idx)
-{
-       struct hda_input_mux_item *csrc;
-       char *buf;
-       int num, ocap;
-
-       num = spec->input_mux.num_items;
-       csrc = &spec->input_mux.items[num];
-       buf = spec->cap_labels[num];
-       for (ocap = 0; ocap < num; ocap++) {
-               if (! strcmp(buf, spec->cap_labels[ocap])) {
-                       /* same label already exists,
-                        * put the index number to be unique
-                        */
-                       sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
-                       break;
-               }
-       }
-       csrc->index = idx;
-       spec->input_mux.num_items++;
-}
-
 /*
  * parse input
  */
@@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
        for (i = 0; i < adc_node->nconns; i++) {
                node = hda_get_node(spec, adc_node->conn_list[i]);
                if (node && node->type == AC_WID_PIN) {
-                       err = parse_adc_sub_nodes(codec, spec, node);
+                       err = parse_adc_sub_nodes(codec, spec, node, i);
                        if (err < 0)
                                return err;
-                       else if (err > 0)
-                               add_cap_src(spec, i);
                }
        }
        /* ... then check the rests, more complicated connections */
        for (i = 0; i < adc_node->nconns; i++) {
                node = hda_get_node(spec, adc_node->conn_list[i]);
                if (node && node->type != AC_WID_PIN) {
-                       err = parse_adc_sub_nodes(codec, spec, node);
+                       err = parse_adc_sub_nodes(codec, spec, node, i);
                        if (err < 0)
                                return err;
-                       else if (err > 0)
-                               add_cap_src(spec, i);
                }
        }
 
index 34940a0..21aa9b0 100644 (file)
@@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 module_param_array(position_fix, int, NULL, 0444);
-MODULE_PARM_DESC(position_fix, "Fix DMA pointer "
-                "(0 = auto, 1 = none, 2 = POSBUF).");
+MODULE_PARM_DESC(position_fix, "DMA pointer read method."
+                "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
 module_param_array(bdl_pos_adj, int, NULL, 0644);
 MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
 module_param_array(probe_mask, int, NULL, 0444);
@@ -305,6 +305,7 @@ enum {
        POS_FIX_AUTO,
        POS_FIX_LPIB,
        POS_FIX_POSBUF,
+       POS_FIX_VIACOMBO,
 };
 
 /* Defines for ATI HD Audio support in SB450 south bridge */
@@ -433,7 +434,6 @@ struct azx {
        unsigned int polling_mode :1;
        unsigned int msi :1;
        unsigned int irq_pending_warned :1;
-       unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
        unsigned int probing :1; /* codec probing phase */
 
        /* for debugging */
@@ -458,6 +458,7 @@ enum {
        AZX_DRIVER_ULI,
        AZX_DRIVER_NVIDIA,
        AZX_DRIVER_TERA,
+       AZX_DRIVER_CTX,
        AZX_DRIVER_GENERIC,
        AZX_NUM_DRIVERS, /* keep this as last entry */
 };
@@ -473,6 +474,7 @@ static char *driver_short_names[] __devinitdata = {
        [AZX_DRIVER_ULI] = "HDA ULI M5461",
        [AZX_DRIVER_NVIDIA] = "HDA NVidia",
        [AZX_DRIVER_TERA] = "HDA Teradici", 
+       [AZX_DRIVER_CTX] = "HDA Creative", 
        [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
 };
 
@@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *chip)
        /* reset the rirb hw write pointer */
        azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
        /* set N=1, get RIRB response interrupt for new entry */
-       azx_writew(chip, RINTCNT, 1);
+       if (chip->driver_type == AZX_DRIVER_CTX)
+               azx_writew(chip, RINTCNT, 0xc0);
+       else
+               azx_writew(chip, RINTCNT, 1);
        /* enable rirb dma and response irq */
        azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
        spin_unlock_irq(&chip->reg_lock);
@@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
        /* clear rirb int */
        status = azx_readb(chip, RIRBSTS);
        if (status & RIRB_INT_MASK) {
-               if (status & RIRB_INT_RESPONSE)
+               if (status & RIRB_INT_RESPONSE) {
+                       if (chip->driver_type == AZX_DRIVER_CTX)
+                               udelay(80);
                        azx_update_rirb(chip);
+               }
                azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
        }
 
@@ -1309,11 +1317,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
        azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
 
        /* enable the position buffer */
-       if (chip->position_fix[0] == POS_FIX_POSBUF ||
-           chip->position_fix[0] == POS_FIX_AUTO ||
-           chip->position_fix[1] == POS_FIX_POSBUF ||
-           chip->position_fix[1] == POS_FIX_AUTO ||
-           chip->via_dmapos_patch) {
+       if (chip->position_fix[0] != POS_FIX_LPIB ||
+           chip->position_fix[1] != POS_FIX_LPIB) {
                if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
                        azx_writel(chip, DPLBASE,
                                (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
@@ -1647,7 +1652,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        struct azx_dev *azx_dev = get_azx_dev(substream);
        struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
        struct snd_pcm_runtime *runtime = substream->runtime;
-       unsigned int bufsize, period_bytes, format_val;
+       unsigned int bufsize, period_bytes, format_val, stream_tag;
        int err;
 
        azx_stream_reset(chip, azx_dev);
@@ -1689,7 +1694,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        else
                azx_dev->fifo_size = 0;
 
-       return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag,
+       stream_tag = azx_dev->stream_tag;
+       /* CA-IBG chips need the playback stream starting from 1 */
+       if (chip->driver_type == AZX_DRIVER_CTX &&
+           stream_tag > chip->capture_streams)
+               stream_tag -= chip->capture_streams;
+       return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
                                     azx_dev->format_val, substream);
 }
 
@@ -1852,20 +1862,21 @@ static unsigned int azx_get_position(struct azx *chip,
                                     struct azx_dev *azx_dev)
 {
        unsigned int pos;
+       int stream = azx_dev->substream->stream;
 
-       if (chip->via_dmapos_patch)
+       switch (chip->position_fix[stream]) {
+       case POS_FIX_LPIB:
+               /* read LPIB */
+               pos = azx_sd_readl(azx_dev, SD_LPIB);
+               break;
+       case POS_FIX_VIACOMBO:
                pos = azx_via_get_position(chip, azx_dev);
-       else {
-               int stream = azx_dev->substream->stream;
-               if (chip->position_fix[stream] == POS_FIX_POSBUF ||
-                   chip->position_fix[stream] == POS_FIX_AUTO) {
-                       /* use the position buffer */
-                       pos = le32_to_cpu(*azx_dev->posbuf);
-               } else {
-                       /* read LPIB */
-                       pos = azx_sd_readl(azx_dev, SD_LPIB);
-               }
+               break;
+       default:
+               /* use the position buffer */
+               pos = le32_to_cpu(*azx_dev->posbuf);
        }
+
        if (pos >= azx_dev->bufsize)
                pos = 0;
        return pos;
@@ -2313,19 +2324,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
        switch (fix) {
        case POS_FIX_LPIB:
        case POS_FIX_POSBUF:
+       case POS_FIX_VIACOMBO:
                return fix;
        }
 
-       /* Check VIA/ATI HD Audio Controller exist */
-       switch (chip->driver_type) {
-       case AZX_DRIVER_VIA:
-       case AZX_DRIVER_ATI:
-               chip->via_dmapos_patch = 1;
-               /* Use link position directly, avoid any transfer problem. */
-               return POS_FIX_LPIB;
-       }
-       chip->via_dmapos_patch = 0;
-
        q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
        if (q) {
                printk(KERN_INFO
@@ -2334,6 +2336,15 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
                       q->value, q->subvendor, q->subdevice);
                return q->value;
        }
+
+       /* Check VIA/ATI HD Audio Controller exist */
+       switch (chip->driver_type) {
+       case AZX_DRIVER_VIA:
+       case AZX_DRIVER_ATI:
+               /* Use link position directly, avoid any transfer problem. */
+               return POS_FIX_VIACOMBO;
+       }
+
        return POS_FIX_AUTO;
 }
 
@@ -2735,25 +2746,17 @@ static void __devexit azx_remove(struct pci_dev *pci)
 
 /* PCI IDs */
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
-       /* ICH 6..10 */
-       { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
-       /* PCH */
-       { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
-       { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+       /* Generic Intel */
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+         .class_mask = 0xffffff,
+         .driver_data = AZX_DRIVER_ICH },
        /* ATI SB 450/600 */
        { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
        { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
@@ -2794,11 +2797,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
          .class_mask = 0xffffff,
-         .driver_data = AZX_DRIVER_GENERIC },
+         .driver_data = AZX_DRIVER_CTX },
 #else
        /* this entry seems still valid -- i.e. without emu20kx chip */
-       { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC },
+       { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX },
 #endif
+       /* Vortex86MX */
+       { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
        /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
index 28ab4ae..46bbefe 100644 (file)
  */
 #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs)           \
        ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
+#define HDA_AMP_VAL_MIN_MUTE (1<<29)
 #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
        HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
 /* mono volume with index (index=0,1,...) (channel=1,2) */
-#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
+#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx,  \
          .subdevice = HDA_SUBDEV_AMP_FLAG, \
          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
          .get = snd_hda_mixer_amp_volume_get, \
          .put = snd_hda_mixer_amp_volume_put, \
          .tlv = { .c = snd_hda_mixer_amp_tlv },                \
-         .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
+         .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags }
 /* stereo volume with index */
 #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
-       HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
+       HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0)
 /* mono volume */
 #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
-       HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction)
+       HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0)
 /* stereo volume */
 #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
        HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
+/* stereo volume with min=mute */
+#define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \
+       HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \
+                                 HDA_AMP_VAL_MIN_MUTE)
 /* mono mute switch with index (index=0,1,...) (channel=1,2) */
 #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
@@ -215,7 +220,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
  */
 #define HDA_MAX_NUM_INPUTS     16
 struct hda_input_mux_item {
-       const char *label;
+       char label[32];
        unsigned int index;
 };
 struct hda_input_mux {
@@ -366,9 +371,7 @@ struct hda_bus_unsolicited {
 
 enum {
        AUTO_PIN_MIC,
-       AUTO_PIN_FRONT_MIC,
-       AUTO_PIN_LINE,
-       AUTO_PIN_FRONT_LINE,
+       AUTO_PIN_LINE_IN,
        AUTO_PIN_CD,
        AUTO_PIN_AUX,
        AUTO_PIN_LAST
@@ -380,9 +383,33 @@ enum {
        AUTO_PIN_HP_OUT
 };
 
-extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
-
 #define AUTO_CFG_MAX_OUTS      5
+#define AUTO_CFG_MAX_INS       8
+
+struct auto_pin_cfg_item {
+       hda_nid_t pin;
+       int type;
+};
+
+struct auto_pin_cfg;
+const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
+                                   int check_location);
+const char *hda_get_autocfg_input_label(struct hda_codec *codec,
+                                       const struct auto_pin_cfg *cfg,
+                                       int input);
+int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+                         int index, int *type_index_ret);
+
+enum {
+       INPUT_PIN_ATTR_UNUSED,  /* pin not connected */
+       INPUT_PIN_ATTR_INT,     /* internal mic/line-in */
+       INPUT_PIN_ATTR_DOCK,    /* docking mic/line-in */
+       INPUT_PIN_ATTR_NORMAL,  /* mic/line-in jack */
+       INPUT_PIN_ATTR_FRONT,   /* mic/line-in jack in front */
+       INPUT_PIN_ATTR_REAR,    /* mic/line-in jack in rear */
+};
+
+int snd_hda_get_input_pin_attr(unsigned int def_conf);
 
 struct auto_pin_cfg {
        int line_outs;
@@ -393,7 +420,8 @@ struct auto_pin_cfg {
        int hp_outs;
        int line_out_type;      /* AUTO_PIN_XXX_OUT */
        hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
-       hda_nid_t input_pins[AUTO_PIN_LAST];
+       int num_inputs;
+       struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
        int dig_outs;
        hda_nid_t dig_out_pins[2];
        hda_nid_t dig_in_pin;
@@ -558,6 +586,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
 #define get_amp_direction(kc)  (((kc)->private_value >> 18) & 0x1)
 #define get_amp_index(kc)      (((kc)->private_value >> 19) & 0xf)
 #define get_amp_offset(kc)     (((kc)->private_value >> 23) & 0x3f)
+#define get_amp_min_mute(kc)   (((kc)->private_value >> 29) & 0x1)
 
 /*
  * CEA Short Audio Descriptor data
index 10bbbaf..f7ff3f7 100644 (file)
@@ -1276,6 +1276,7 @@ static int patch_ad1986a(struct hda_codec *codec)
        spec->multiout.no_share_stream = 1;
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -1463,6 +1464,7 @@ static int patch_ad1983(struct hda_codec *codec)
        codec->patch_ops = ad198x_patch_ops;
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -1917,6 +1919,7 @@ static int patch_ad1981(struct hda_codec *codec)
        }
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -2880,7 +2883,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 
 /* create input playback/capture controls for the given pin */
 static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
-                           const char *ctlname, int boost)
+                           const char *ctlname, int ctlidx, int boost)
 {
        char name[32];
        int err, idx;
@@ -2909,25 +2912,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
 }
 
 /* create playback/capture controls for input pins */
-static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
+static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
+       struct ad198x_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux;
-       int i, err;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               err = new_analog_input(spec, cfg->input_pins[i],
-                                      auto_pin_cfg_labels[i],
-                                      i <= AUTO_PIN_FRONT_MIC);
+       int i, err, type, type_idx;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               const char *label;
+               type = cfg->inputs[i].type;
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               snd_hda_add_imux_item(imux, label,
+                                     ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
+                                     &type_idx);
+               err = new_analog_input(spec, cfg->inputs[i].pin,
+                                      label, type_idx,
+                                      type == AUTO_PIN_MIC);
                if (err < 0)
                        return err;
-               imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-               imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
-               imux->num_items++;
        }
-       imux->items[imux->num_items].label = "Mix";
-       imux->items[imux->num_items].index = 9;
-       imux->num_items++;
+       snd_hda_add_imux_item(imux, "Mix", 9, NULL);
 
        if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
                               "Analog Mix Playback Volume",
@@ -2994,12 +2999,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec)
 static void ad1988_auto_init_analog_input(struct hda_codec *codec)
 {
        struct ad198x_spec *spec = codec->spec;
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        int i, idx;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (! nid)
-                       continue;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                switch (nid) {
                case 0x15: /* port-C */
                        snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3009,7 +3013,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
                        break;
                }
                snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                   i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+                                   i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
                if (nid != AD1988_PIN_CD_NID)
                        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
                                            AMP_OUT_MUTE);
@@ -3040,7 +3044,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
                                                "Speaker")) < 0 ||
            (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
                                                "Headphone")) < 0 ||
-           (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+           (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
                return err;
 
        spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -3235,6 +3239,7 @@ static int patch_ad1988(struct hda_codec *codec)
        spec->vmaster_nid = 0x04;
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -3449,6 +3454,7 @@ static int patch_ad1884(struct hda_codec *codec)
        codec->patch_ops = ad198x_patch_ops;
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -4422,6 +4428,7 @@ static int patch_ad1884a(struct hda_codec *codec)
        }
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
@@ -4761,6 +4768,7 @@ static int patch_ad1882(struct hda_codec *codec)
        }
 
        codec->no_trigger_sense = 1;
+       codec->no_sticky_stream = 1;
 
        return 0;
 }
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
deleted file mode 100644 (file)
index fb684f0..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for ATI HDMI codecs
- *
- * Copyright (c) 2006 ATI Technologies Inc.
- *
- *
- *  This driver 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 driver 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "hda_codec.h"
-#include "hda_local.h"
-
-struct atihdmi_spec {
-       struct hda_multi_out multiout;
-
-       struct hda_pcm pcm_rec;
-};
-
-#define CVT_NID                0x02    /* audio converter */
-#define PIN_NID                0x03    /* HDMI output pin */
-
-static struct hda_verb atihdmi_basic_init[] = {
-       /* enable digital output on pin widget */
-       { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-       {} /* terminator */
-};
-
-/*
- * Controls
- */
-static int atihdmi_build_controls(struct hda_codec *codec)
-{
-       struct atihdmi_spec *spec = codec->spec;
-       int err;
-
-       err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
-       if (err < 0)
-               return err;
-
-       return 0;
-}
-
-static int atihdmi_init(struct hda_codec *codec)
-{
-       snd_hda_sequence_write(codec, atihdmi_basic_init);
-       /* SI codec requires to unmute the pin */
-       if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
-               snd_hda_codec_write(codec, PIN_NID, 0,
-                                   AC_VERB_SET_AMP_GAIN_MUTE,
-                                   AMP_OUT_UNMUTE);
-       return 0;
-}
-
-/*
- * Digital out
- */
-static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-                                    struct hda_codec *codec,
-                                    struct snd_pcm_substream *substream)
-{
-       struct atihdmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-                                     struct hda_codec *codec,
-                                     struct snd_pcm_substream *substream)
-{
-       struct atihdmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-                                           struct hda_codec *codec,
-                                           unsigned int stream_tag,
-                                           unsigned int format,
-                                           struct snd_pcm_substream *substream)
-{
-       struct atihdmi_spec *spec = codec->spec;
-       int chans = substream->runtime->channels;
-       int i, err;
-
-       err = snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-                                           format, substream);
-       if (err < 0)
-               return err;
-       snd_hda_codec_write(codec, CVT_NID, 0, AC_VERB_SET_CVT_CHAN_COUNT,
-                           chans - 1);
-       /* FIXME: XXX */
-       for (i = 0; i < chans; i++) {
-               snd_hda_codec_write(codec, CVT_NID, 0,
-                                   AC_VERB_SET_HDMI_CHAN_SLOT,
-                                   (i << 4) | i);
-       }
-       return 0;
-}
-
-static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 2,
-       .nid = CVT_NID, /* NID to query formats and rates and setup streams */
-       .ops = {
-               .open = atihdmi_dig_playback_pcm_open,
-               .close = atihdmi_dig_playback_pcm_close,
-               .prepare = atihdmi_dig_playback_pcm_prepare
-       },
-};
-
-static int atihdmi_build_pcms(struct hda_codec *codec)
-{
-       struct atihdmi_spec *spec = codec->spec;
-       struct hda_pcm *info = &spec->pcm_rec;
-       unsigned int chans;
-
-       codec->num_pcms = 1;
-       codec->pcm_info = info;
-
-       info->name = "ATI HDMI";
-       info->pcm_type = HDA_PCM_TYPE_HDMI;
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
-
-       /* FIXME: we must check ELD and change the PCM parameters dynamically
-        */
-       chans = get_wcaps(codec, CVT_NID);
-       chans = get_wcaps_channels(chans);
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
-
-       return 0;
-}
-
-static void atihdmi_free(struct hda_codec *codec)
-{
-       kfree(codec->spec);
-}
-
-static struct hda_codec_ops atihdmi_patch_ops = {
-       .build_controls = atihdmi_build_controls,
-       .build_pcms = atihdmi_build_pcms,
-       .init = atihdmi_init,
-       .free = atihdmi_free,
-};
-
-static int patch_atihdmi(struct hda_codec *codec)
-{
-       struct atihdmi_spec *spec;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
-
-       spec->multiout.num_dacs = 0;      /* no analog */
-       spec->multiout.max_channels = 2;
-       /* NID for copying analog to digital,
-        * seems to be unused in pure-digital
-        * case.
-        */
-       spec->multiout.dig_out_nid = CVT_NID;
-
-       codec->patch_ops = atihdmi_patch_ops;
-
-       return 0;
-}
-
-/*
- * patch entries
- */
-static struct hda_codec_preset snd_hda_preset_atihdmi[] = {
-       { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
-       { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
-       { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
-       { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi },
-       { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi },
-       { .id = 0x17e80047, .name = "Chrontel HDMI",  .patch = patch_atihdmi },
-       {} /* terminator */
-};
-
-MODULE_ALIAS("snd-hda-codec-id:1002793c");
-MODULE_ALIAS("snd-hda-codec-id:10027919");
-MODULE_ALIAS("snd-hda-codec-id:1002791a");
-MODULE_ALIAS("snd-hda-codec-id:1002aa01");
-MODULE_ALIAS("snd-hda-codec-id:10951390");
-MODULE_ALIAS("snd-hda-codec-id:17e80047");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ATI HDMI HD-audio codec");
-
-static struct hda_codec_preset_list atihdmi_list = {
-       .preset = snd_hda_preset_atihdmi,
-       .owner = THIS_MODULE,
-};
-
-static int __init patch_atihdmi_init(void)
-{
-       return snd_hda_add_codec_preset(&atihdmi_list);
-}
-
-static void __exit patch_atihdmi_exit(void)
-{
-       snd_hda_delete_codec_preset(&atihdmi_list);
-}
-
-module_init(patch_atihdmi_init)
-module_exit(patch_atihdmi_exit)
index af47801..46c8bf4 100644 (file)
@@ -468,13 +468,13 @@ static void parse_input(struct hda_codec *codec)
                        spec->dig_in = nid;
                        continue;
                }
-               for (j = 0; j < AUTO_PIN_LAST; j++)
-                       if (cfg->input_pins[j] == pin)
+               for (j = 0; j < cfg->num_inputs; j++)
+                       if (cfg->inputs[j].pin == pin)
                                break;
-               if (j >= AUTO_PIN_LAST)
+               if (j >= cfg->num_inputs)
                        continue;
                spec->input_pins[n] = pin;
-               spec->input_labels[n] = auto_pin_cfg_labels[j];
+               spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1);
                spec->adcs[n] = nid;
                n++;
        }
@@ -489,7 +489,7 @@ static void parse_digital(struct hda_codec *codec)
        if (cfg->dig_outs &&
            snd_hda_get_connections(codec, cfg->dig_out_pins[0],
                                    &spec->dig_out, 1) == 1)
-               spec->multiout.dig_out_nid = cfg->dig_out_pins[0];
+               spec->multiout.dig_out_nid = spec->dig_out;
 }
 
 static int ca0110_parse_auto_config(struct hda_codec *codec)
index 488fd9a..460fb2e 100644 (file)
@@ -65,6 +65,7 @@ struct cs_spec {
 
 /* available models */
 enum {
+       CS420X_MBP53,
        CS420X_MBP55,
        CS420X_IMAC27,
        CS420X_AUTO,
@@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
 {
        struct cs_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       hda_nid_t pin = cfg->input_pins[idx];
+       hda_nid_t pin = cfg->inputs[idx].pin;
        unsigned int val = snd_hda_query_pin_caps(codec, pin);
        if (!(val & AC_PINCAP_PRES_DETECT))
                return 0;
        val = snd_hda_codec_get_pincfg(codec, pin);
-       return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX);
+       return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT);
 }
 
 static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
@@ -424,10 +425,8 @@ static int parse_input(struct hda_codec *codec)
        struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t pin = cfg->input_pins[i];
-               if (!pin)
-                       continue;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t pin = cfg->inputs[i].pin;
                spec->input_idx[spec->num_inputs] = i;
                spec->capsrc_idx[i] = spec->num_inputs++;
                spec->cur_input = i;
@@ -438,16 +437,17 @@ static int parse_input(struct hda_codec *codec)
 
        /* check whether the automatic mic switch is available */
        if (spec->num_inputs == 2 &&
-           spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) {
-               if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) {
-                       if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) {
+           cfg->inputs[0].type == AUTO_PIN_MIC &&
+           cfg->inputs[1].type == AUTO_PIN_MIC) {
+               if (is_ext_mic(codec, cfg->inputs[0].pin)) {
+                       if (!is_ext_mic(codec, cfg->inputs[1].pin)) {
                                spec->mic_detect = 1;
-                               spec->automic_idx = AUTO_PIN_FRONT_MIC;
+                               spec->automic_idx = 0;
                        }
                } else {
-                       if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) {
+                       if (is_ext_mic(codec, cfg->inputs[1].pin)) {
                                spec->mic_detect = 1;
-                               spec->automic_idx = AUTO_PIN_MIC;
+                               spec->automic_idx = 1;
                        }
                }
        }
@@ -674,6 +674,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct cs_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int idx;
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -682,7 +683,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
        if (uinfo->value.enumerated.item >= spec->num_inputs)
                uinfo->value.enumerated.item = spec->num_inputs - 1;
        idx = spec->input_idx[uinfo->value.enumerated.item];
-       strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]);
+       strcpy(uinfo->value.enumerated.name,
+              hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1));
        return 0;
 }
 
@@ -740,6 +742,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec,
        return bind;
 }
 
+/* add a (input-boost) volume control to the given input pin */
+static int add_input_volume_control(struct hda_codec *codec,
+                                   struct auto_pin_cfg *cfg,
+                                   int item)
+{
+       hda_nid_t pin = cfg->inputs[item].pin;
+       u32 caps;
+       const char *label;
+       struct snd_kcontrol *kctl;
+               
+       if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
+               return 0;
+       caps = query_amp_caps(codec, pin, HDA_INPUT);
+       caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+       if (caps <= 1)
+               return 0;
+       label = hda_get_autocfg_input_label(codec, cfg, item);
+       return add_volume(codec, label, 0,
+                         HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
+}
+
 static int build_input(struct hda_codec *codec)
 {
        struct cs_spec *spec = codec->spec;
@@ -779,6 +802,12 @@ static int build_input(struct hda_codec *codec)
                        return err;
        }
 
+       for (i = 0; i < spec->num_inputs; i++) {
+               err = add_input_volume_control(codec, &spec->autocfg, i);
+               if (err < 0)
+                       return err;
+       }
+
        return 0;
 }
 
@@ -838,7 +867,8 @@ static void cs_automute(struct hda_codec *codec)
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    hp_present ? 0 : PIN_OUT);
        }
-       if (spec->board_config == CS420X_MBP55 ||
+       if (spec->board_config == CS420X_MBP53 ||
+           spec->board_config == CS420X_MBP55 ||
            spec->board_config == CS420X_IMAC27) {
                unsigned int gpio = hp_present ? 0x02 : 0x08;
                snd_hda_codec_write(codec, 0x01, 0,
@@ -853,15 +883,12 @@ static void cs_automic(struct hda_codec *codec)
        hda_nid_t nid;
        unsigned int present;
        
-       nid = cfg->input_pins[spec->automic_idx];
+       nid = cfg->inputs[spec->automic_idx].pin;
        present = snd_hda_jack_detect(codec, nid);
        if (present)
                change_cur_input(codec, spec->automic_idx, 0);
-       else {
-               unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ?
-                       AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC;
-               change_cur_input(codec, imic, 0);
-       }
+       else
+               change_cur_input(codec, !spec->automic_idx, 0);
 }
 
 /*
@@ -918,14 +945,14 @@ static void init_input(struct hda_codec *codec)
        unsigned int coef;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
+       for (i = 0; i < cfg->num_inputs; i++) {
                unsigned int ctl;
-               hda_nid_t pin = cfg->input_pins[i];
-               if (!pin || !spec->adc_nid[i])
+               hda_nid_t pin = cfg->inputs[i].pin;
+               if (!spec->adc_nid[i])
                        continue;
                /* set appropriate pin control and mute first */
                ctl = PIN_IN;
-               if (i <= AUTO_PIN_FRONT_MIC) {
+               if (cfg->inputs[i].type == AUTO_PIN_MIC) {
                        unsigned int caps = snd_hda_query_pin_caps(codec, pin);
                        caps >>= AC_PINCAP_VREF_SHIFT;
                        if (caps & AC_PINCAP_VREF_80)
@@ -1130,6 +1157,7 @@ static int cs_parse_auto_config(struct hda_codec *codec)
 }
 
 static const char *cs420x_models[CS420X_MODELS] = {
+       [CS420X_MBP53] = "mbp53",
        [CS420X_MBP55] = "mbp55",
        [CS420X_IMAC27] = "imac27",
        [CS420X_AUTO] = "auto",
@@ -1137,7 +1165,9 @@ static const char *cs420x_models[CS420X_MODELS] = {
 
 
 static struct snd_pci_quirk cs420x_cfg_tbl[] = {
+       SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
        SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+       SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
        SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
        {} /* terminator */
 };
@@ -1147,6 +1177,20 @@ struct cs_pincfg {
        u32 val;
 };
 
+static struct cs_pincfg mbp53_pincfgs[] = {
+       { 0x09, 0x012b4050 },
+       { 0x0a, 0x90100141 },
+       { 0x0b, 0x90100140 },
+       { 0x0c, 0x018b3020 },
+       { 0x0d, 0x90a00110 },
+       { 0x0e, 0x400000f0 },
+       { 0x0f, 0x01cbe030 },
+       { 0x10, 0x014be060 },
+       { 0x12, 0x400000f0 },
+       { 0x15, 0x400000f0 },
+       {} /* terminator */
+};
+
 static struct cs_pincfg mbp55_pincfgs[] = {
        { 0x09, 0x012b4030 },
        { 0x0a, 0x90100121 },
@@ -1176,6 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = {
 };
 
 static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
+       [CS420X_MBP53] = mbp53_pincfgs,
        [CS420X_MBP55] = mbp55_pincfgs,
        [CS420X_IMAC27] = imac27_pincfgs,
 };
@@ -1208,6 +1253,7 @@ static int patch_cs420x(struct hda_codec *codec)
 
        switch (spec->board_config) {
        case CS420X_IMAC27:
+       case CS420X_MBP53:
        case CS420X_MBP55:
                /* GPIO1 = headphones */
                /* GPIO3 = speakers */
index 972e7c4..6361f75 100644 (file)
@@ -57,6 +57,12 @@ struct conexant_jack {
 
 };
 
+struct pin_dac_pair {
+       hda_nid_t pin;
+       hda_nid_t dac;
+       int type;
+};
+
 struct conexant_spec {
 
        struct snd_kcontrol_new *mixers[5];
@@ -77,6 +83,7 @@ struct conexant_spec {
        unsigned int cur_eapd;
        unsigned int hp_present;
        unsigned int auto_mic;
+       int auto_mic_ext;               /* autocfg.inputs[] index for ext mic */
        unsigned int need_dac_fix;
 
        /* capture */
@@ -110,9 +117,12 @@ struct conexant_spec {
        struct auto_pin_cfg autocfg;
        struct hda_input_mux private_imux;
        hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
+       struct pin_dac_pair dac_info[8];
+       int dac_info_filled;
 
-       unsigned int dell_automute;
        unsigned int port_d_mode;
+       unsigned int auto_mute:1;       /* used in auto-parser */
+       unsigned int dell_automute:1;
        unsigned int dell_vostro:1;
        unsigned int ideapad:1;
        unsigned int thinkpad:1;
@@ -3065,7 +3075,7 @@ enum {
        CXT5066_LAPTOP,         /* Laptops w/ EAPD support */
        CXT5066_DELL_LAPTOP,    /* Dell Laptop */
        CXT5066_OLPC_XO_1_5,    /* OLPC XO 1.5 */
-       CXT5066_DELL_VOSTO,     /* Dell Vostro 1015i */
+       CXT5066_DELL_VOSTRO,    /* Dell Vostro 1015i */
        CXT5066_IDEAPAD,        /* Lenovo IdeaPad U150 */
        CXT5066_THINKPAD,       /* Lenovo ThinkPad T410s, others? */
        CXT5066_HP_LAPTOP,      /* HP Laptop */
@@ -3076,25 +3086,26 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
        [CXT5066_LAPTOP]        = "laptop",
        [CXT5066_DELL_LAPTOP]   = "dell-laptop",
        [CXT5066_OLPC_XO_1_5]   = "olpc-xo-1_5",
-       [CXT5066_DELL_VOSTO]    = "dell-vostro",
+       [CXT5066_DELL_VOSTRO]   = "dell-vostro",
        [CXT5066_IDEAPAD]       = "ideapad",
        [CXT5066_THINKPAD]      = "thinkpad",
        [CXT5066_HP_LAPTOP]     = "hp-laptop",
 };
 
 static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
-       SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
-                     CXT5066_LAPTOP),
+       SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
+       SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
                      CXT5066_DELL_LAPTOP),
-       SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
-       SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO),
-       SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
+       SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
        SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
        SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
+       SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
+                     CXT5066_LAPTOP),
+       SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
@@ -3196,7 +3207,7 @@ static int patch_cxt5066(struct hda_codec *codec)
                spec->capture_prepare = cxt5066_olpc_capture_prepare;
                spec->capture_cleanup = cxt5066_olpc_capture_cleanup;
                break;
-       case CXT5066_DELL_VOSTO:
+       case CXT5066_DELL_VOSTRO:
                codec->patch_ops.init = cxt5066_init;
                codec->patch_ops.unsol_event = cxt5066_vostro_event;
                spec->init_verbs[0] = cxt5066_init_verbs_vostro;
@@ -3254,6 +3265,604 @@ static int patch_cxt5066(struct hda_codec *codec)
 }
 
 /*
+ * Automatic parser for CX20641 & co
+ */
+
+static hda_nid_t cx_auto_adc_nids[] = { 0x14 };
+
+/* get the connection index of @nid in the widget @mux */
+static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
+                               hda_nid_t nid)
+{
+       hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+       int i, nums;
+
+       nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+       for (i = 0; i < nums; i++)
+               if (conn[i] == nid)
+                       return i;
+       return -1;
+}
+
+/* get an unassigned DAC from the given list.
+ * Return the nid if found and reduce the DAC list, or return zero if
+ * not found
+ */
+static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
+                                   hda_nid_t *dacs, int *num_dacs)
+{
+       int i, nums = *num_dacs;
+       hda_nid_t ret = 0;
+
+       for (i = 0; i < nums; i++) {
+               if (get_connection_index(codec, pin, dacs[i]) >= 0) {
+                       ret = dacs[i];
+                       break;
+               }
+       }
+       if (!ret)
+               return 0;
+       if (--nums > 0)
+               memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t));
+       *num_dacs = nums;
+       return ret;
+}
+
+#define MAX_AUTO_DACS  5
+
+/* fill analog DAC list from the widget tree */
+static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
+{
+       hda_nid_t nid, end_nid;
+       int nums = 0;
+
+       end_nid = codec->start_nid + codec->num_nodes;
+       for (nid = codec->start_nid; nid < end_nid; nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               unsigned int type = get_wcaps_type(wcaps);
+               if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) {
+                       dacs[nums++] = nid;
+                       if (nums >= MAX_AUTO_DACS)
+                               break;
+               }
+       }
+       return nums;
+}
+
+/* fill pin_dac_pair list from the pin and dac list */
+static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
+                             int num_pins, hda_nid_t *dacs, int *rest,
+                             struct pin_dac_pair *filled, int type)
+{
+       int i, nums;
+
+       nums = 0;
+       for (i = 0; i < num_pins; i++) {
+               filled[nums].pin = pins[i];
+               filled[nums].type = type;
+               filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
+               nums++;
+       }
+       return nums;
+}
+
+/* parse analog output paths */
+static void cx_auto_parse_output(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       hda_nid_t dacs[MAX_AUTO_DACS];
+       int i, j, nums, rest;
+
+       rest = fill_cx_auto_dacs(codec, dacs);
+       /* parse all analog output pins */
+       nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
+                                 dacs, &rest, spec->dac_info,
+                                 AUTO_PIN_LINE_OUT);
+       nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
+                                 dacs, &rest, spec->dac_info + nums,
+                                 AUTO_PIN_HP_OUT);
+       nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
+                                 dacs, &rest, spec->dac_info + nums,
+                                 AUTO_PIN_SPEAKER_OUT);
+       spec->dac_info_filled = nums;
+       /* fill multiout struct */
+       for (i = 0; i < nums; i++) {
+               hda_nid_t dac = spec->dac_info[i].dac;
+               if (!dac)
+                       continue;
+               switch (spec->dac_info[i].type) {
+               case AUTO_PIN_LINE_OUT:
+                       spec->private_dac_nids[spec->multiout.num_dacs] = dac;
+                       spec->multiout.num_dacs++;
+                       break;
+               case AUTO_PIN_HP_OUT:
+               case AUTO_PIN_SPEAKER_OUT:
+                       if (!spec->multiout.hp_nid) {
+                               spec->multiout.hp_nid = dac;
+                               break;
+                       }
+                       for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++)
+                               if (!spec->multiout.extra_out_nid[j]) {
+                                       spec->multiout.extra_out_nid[j] = dac;
+                                       break;
+                               }
+                       break;
+               }
+       }
+       spec->multiout.dac_nids = spec->private_dac_nids;
+       spec->multiout.max_channels = nums * 2;
+
+       if (cfg->hp_outs > 0)
+               spec->auto_mute = 1;
+       spec->vmaster_nid = spec->private_dac_nids[0];
+}
+
+/* auto-mute/unmute speaker and line outs according to headphone jack */
+static void cx_auto_hp_automute(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i, present;
+
+       if (!spec->auto_mute)
+               return;
+       present = 0;
+       for (i = 0; i < cfg->hp_outs; i++) {
+               if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) {
+                       present = 1;
+                       break;
+               }
+       }
+       for (i = 0; i < cfg->line_outs; i++) {
+               snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   present ? 0 : PIN_OUT);
+       }
+       for (i = 0; i < cfg->speaker_outs; i++) {
+               snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   present ? 0 : PIN_OUT);
+       }
+}
+
+/* automatic switch internal and external mic */
+static void cx_auto_automic(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       struct hda_input_mux *imux = &spec->private_imux;
+       int ext_idx = spec->auto_mic_ext;
+
+       if (!spec->auto_mic)
+               return;
+       if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) {
+               snd_hda_codec_write(codec, spec->adc_nids[0], 0,
+                                   AC_VERB_SET_CONNECT_SEL,
+                                   imux->items[ext_idx].index);
+       } else {
+               snd_hda_codec_write(codec, spec->adc_nids[0], 0,
+                                   AC_VERB_SET_CONNECT_SEL,
+                                   imux->items[!ext_idx].index);
+       }
+}
+
+static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+       int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
+       switch (res >> 26) {
+       case CONEXANT_HP_EVENT:
+               cx_auto_hp_automute(codec);
+               conexant_report_jack(codec, nid);
+               break;
+       case CONEXANT_MIC_EVENT:
+               cx_auto_automic(codec);
+               conexant_report_jack(codec, nid);
+               break;
+       }
+}
+
+/* return true if it's an internal-mic pin */
+static int is_int_mic(struct hda_codec *codec, hda_nid_t pin)
+{
+       unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
+       return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
+               snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT;
+}
+
+/* return true if it's an external-mic pin */
+static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin)
+{
+       unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
+       return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
+               snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL &&
+               (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT);
+}
+
+/* check whether the pin config is suitable for auto-mic switching;
+ * auto-mic is enabled only when one int-mic and one-ext mic exist
+ */
+static void cx_auto_check_auto_mic(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+
+       if (is_ext_mic(codec, cfg->inputs[0].pin) &&
+           is_int_mic(codec, cfg->inputs[1].pin)) {
+               spec->auto_mic = 1;
+               spec->auto_mic_ext = 1;
+               return;
+       }
+       if (is_int_mic(codec, cfg->inputs[1].pin) &&
+           is_ext_mic(codec, cfg->inputs[0].pin)) {
+               spec->auto_mic = 1;
+               spec->auto_mic_ext = 0;
+               return;
+       }
+}
+
+static void cx_auto_parse_input(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       struct hda_input_mux *imux;
+       int i;
+
+       imux = &spec->private_imux;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               int idx = get_connection_index(codec, spec->adc_nids[0],
+                                              cfg->inputs[i].pin);
+               if (idx >= 0) {
+                       const char *label;
+                       label = hda_get_autocfg_input_label(codec, cfg, i);
+                       snd_hda_add_imux_item(imux, label, idx, NULL);
+               }
+       }
+       if (imux->num_items == 2 && cfg->num_inputs == 2)
+               cx_auto_check_auto_mic(codec);
+       if (imux->num_items > 1 && !spec->auto_mic)
+               spec->input_mux = imux;
+}
+
+/* get digital-input audio widget corresponding to the given pin */
+static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin)
+{
+       hda_nid_t nid, end_nid;
+
+       end_nid = codec->start_nid + codec->num_nodes;
+       for (nid = codec->start_nid; nid < end_nid; nid++) {
+               unsigned int wcaps = get_wcaps(codec, nid);
+               unsigned int type = get_wcaps_type(wcaps);
+               if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) {
+                       if (get_connection_index(codec, nid, pin) >= 0)
+                               return nid;
+               }
+       }
+       return 0;
+}
+
+static void cx_auto_parse_digital(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       hda_nid_t nid;
+
+       if (cfg->dig_outs &&
+           snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1)
+               spec->multiout.dig_out_nid = nid;
+       if (cfg->dig_in_pin)
+               spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin);
+}
+
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+static void cx_auto_parse_beep(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       hda_nid_t nid, end_nid;
+
+       end_nid = codec->start_nid + codec->num_nodes;
+       for (nid = codec->start_nid; nid < end_nid; nid++)
+               if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
+                       set_beep_amp(spec, nid, 0, HDA_OUTPUT);
+                       break;
+               }
+}
+#else
+#define cx_auto_parse_beep(codec)
+#endif
+
+static int cx_auto_parse_auto_config(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       int err;
+
+       err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+       if (err < 0)
+               return err;
+
+       cx_auto_parse_output(codec);
+       cx_auto_parse_input(codec);
+       cx_auto_parse_digital(codec);
+       cx_auto_parse_beep(codec);
+       return 0;
+}
+
+static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins,
+                                hda_nid_t *pins)
+{
+       int i;
+       for (i = 0; i < num_pins; i++) {
+               if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
+                       snd_hda_codec_write(codec, pins[i], 0,
+                                           AC_VERB_SET_EAPD_BTLENABLE, 0x02);
+       }
+}
+
+static void select_connection(struct hda_codec *codec, hda_nid_t pin,
+                             hda_nid_t src)
+{
+       int idx = get_connection_index(codec, pin, src);
+       if (idx >= 0)
+               snd_hda_codec_write(codec, pin, 0,
+                                   AC_VERB_SET_CONNECT_SEL, idx);
+}
+
+static void cx_auto_init_output(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       hda_nid_t nid;
+       int i;
+
+       for (i = 0; i < spec->multiout.num_dacs; i++)
+               snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+       for (i = 0; i < cfg->hp_outs; i++)
+               snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+       if (spec->auto_mute) {
+               for (i = 0; i < cfg->hp_outs; i++) {
+                       snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
+                                   AC_VERB_SET_UNSOLICITED_ENABLE,
+                                   AC_USRSP_EN | CONEXANT_HP_EVENT);
+               }
+               cx_auto_hp_automute(codec);
+       } else {
+               for (i = 0; i < cfg->line_outs; i++)
+                       snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+               for (i = 0; i < cfg->speaker_outs; i++)
+                       snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       }
+
+       for (i = 0; i < spec->dac_info_filled; i++) {
+               nid = spec->dac_info[i].dac;
+               if (!nid)
+                       nid = spec->multiout.dac_nids[0];
+               select_connection(codec, spec->dac_info[i].pin, nid);
+       }
+
+       /* turn on EAPD */
+       cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins);
+       cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins);
+       cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins);
+}
+
+static void cx_auto_init_input(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+       for (i = 0; i < spec->num_adc_nids; i++)
+               snd_hda_codec_write(codec, spec->adc_nids[i], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0));
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               unsigned int type;
+               if (cfg->inputs[i].type == AUTO_PIN_MIC)
+                       type = PIN_VREF80;
+               else
+                       type = PIN_IN;
+               snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, type);
+       }
+
+       if (spec->auto_mic) {
+               int ext_idx = spec->auto_mic_ext;
+               snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0,
+                                   AC_VERB_SET_UNSOLICITED_ENABLE,
+                                   AC_USRSP_EN | CONEXANT_MIC_EVENT);
+               cx_auto_automic(codec);
+       } else {
+               for (i = 0; i < spec->num_adc_nids; i++) {
+                       snd_hda_codec_write(codec, spec->adc_nids[i], 0,
+                                           AC_VERB_SET_CONNECT_SEL,
+                                           spec->private_imux.items[0].index);
+               }
+       }
+}
+
+static void cx_auto_init_digital(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+
+       if (spec->multiout.dig_out_nid)
+               snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+       if (spec->dig_in_nid)
+               snd_hda_codec_write(codec, cfg->dig_in_pin, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
+}
+
+static int cx_auto_init(struct hda_codec *codec)
+{
+       /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
+       cx_auto_init_output(codec);
+       cx_auto_init_input(codec);
+       cx_auto_init_digital(codec);
+       return 0;
+}
+
+static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
+                             const char *dir, int cidx,
+                             hda_nid_t nid, int hda_dir)
+{
+       static char name[32];
+       static struct snd_kcontrol_new knew[] = {
+               HDA_CODEC_VOLUME(name, 0, 0, 0),
+               HDA_CODEC_MUTE(name, 0, 0, 0),
+       };
+       static char *sfx[2] = { "Volume", "Switch" };
+       int i, err;
+
+       for (i = 0; i < 2; i++) {
+               struct snd_kcontrol *kctl;
+               knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir);
+               knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
+               knew[i].index = cidx;
+               snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]);
+               kctl = snd_ctl_new1(&knew[i], codec);
+               if (!kctl)
+                       return -ENOMEM;
+               err = snd_hda_ctl_add(codec, nid, kctl);
+               if (err < 0)
+                       return err;
+               if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
+                       break;
+       }
+       return 0;
+}
+
+#define cx_auto_add_pb_volume(codec, nid, str, idx)                    \
+       cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
+
+static int cx_auto_build_output_controls(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       int i, err;
+       int num_line = 0, num_hp = 0, num_spk = 0;
+       static const char *texts[3] = { "Front", "Surround", "CLFE" };
+
+       if (spec->dac_info_filled == 1)
+               return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac,
+                                            "Master", 0);
+       for (i = 0; i < spec->dac_info_filled; i++) {
+               const char *label;
+               int idx, type;
+               if (!spec->dac_info[i].dac)
+                       continue;
+               type = spec->dac_info[i].type;
+               if (type == AUTO_PIN_LINE_OUT)
+                       type = spec->autocfg.line_out_type;
+               switch (type) {
+               case AUTO_PIN_LINE_OUT:
+               default:
+                       label = texts[num_line++];
+                       idx = 0;
+                       break;
+               case AUTO_PIN_HP_OUT:
+                       label = "Headphone";
+                       idx = num_hp++;
+                       break;
+               case AUTO_PIN_SPEAKER_OUT:
+                       label = "Speaker";
+                       idx = num_spk++;
+                       break;
+               }
+               err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac,
+                                           label, idx);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int cx_auto_build_input_controls(struct hda_codec *codec)
+{
+       struct conexant_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       static const char *prev_label;
+       int i, err, cidx;
+
+       err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0],
+                                HDA_INPUT);
+       if (err < 0)
+               return err;
+       prev_label = NULL;
+       cidx = 0;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               const char *label;
+               if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP))
+                       continue;
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               if (label == prev_label)
+                       cidx++;
+               else
+                       cidx = 0;
+               prev_label = label;
+               err = cx_auto_add_volume(codec, label, " Capture", cidx,
+                                        nid, HDA_INPUT);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static int cx_auto_build_controls(struct hda_codec *codec)
+{
+       int err;
+
+       err = cx_auto_build_output_controls(codec);
+       if (err < 0)
+               return err;
+       err = cx_auto_build_input_controls(codec);
+       if (err < 0)
+               return err;
+       return conexant_build_controls(codec);
+}
+
+static struct hda_codec_ops cx_auto_patch_ops = {
+       .build_controls = cx_auto_build_controls,
+       .build_pcms = conexant_build_pcms,
+       .init = cx_auto_init,
+       .free = conexant_free,
+       .unsol_event = cx_auto_unsol_event,
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       .suspend = conexant_suspend,
+#endif
+       .reboot_notify = snd_hda_shutup_pins,
+};
+
+static int patch_conexant_auto(struct hda_codec *codec)
+{
+       struct conexant_spec *spec;
+       int err;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return -ENOMEM;
+       codec->spec = spec;
+       spec->adc_nids = cx_auto_adc_nids;
+       spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids);
+       spec->capsrc_nids = spec->adc_nids;
+       err = cx_auto_parse_auto_config(codec);
+       if (err < 0) {
+               kfree(codec->spec);
+               codec->spec = NULL;
+               return err;
+       }
+       codec->patch_ops = cx_auto_patch_ops;
+       if (spec->beep_amp)
+               snd_hda_attach_beep_device(codec, spec->beep_amp);
+       return 0;
+}
+
+/*
  */
 
 static struct hda_codec_preset snd_hda_preset_conexant[] = {
@@ -3271,6 +3880,22 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
          .patch = patch_cxt5066 },
        { .id = 0x14f15069, .name = "CX20585",
          .patch = patch_cxt5066 },
+       { .id = 0x14f15097, .name = "CX20631",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f15098, .name = "CX20632",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150a1, .name = "CX20641",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150a2, .name = "CX20642",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150ab, .name = "CX20651",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150ac, .name = "CX20652",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150b8, .name = "CX20664",
+         .patch = patch_conexant_auto },
+       { .id = 0x14f150b9, .name = "CX20665",
+         .patch = patch_conexant_auto },
        {} /* terminator */
 };
 
@@ -3281,6 +3906,14 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066");
 MODULE_ALIAS("snd-hda-codec-id:14f15067");
 MODULE_ALIAS("snd-hda-codec-id:14f15068");
 MODULE_ALIAS("snd-hda-codec-id:14f15069");
+MODULE_ALIAS("snd-hda-codec-id:14f15097");
+MODULE_ALIAS("snd-hda-codec-id:14f15098");
+MODULE_ALIAS("snd-hda-codec-id:14f150a1");
+MODULE_ALIAS("snd-hda-codec-id:14f150a2");
+MODULE_ALIAS("snd-hda-codec-id:14f150ab");
+MODULE_ALIAS("snd-hda-codec-id:14f150ac");
+MODULE_ALIAS("snd-hda-codec-id:14f150b8");
+MODULE_ALIAS("snd-hda-codec-id:14f150b9");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Conexant HD-audio codec");
index afd6022..d3e49aa 100644 (file)
@@ -3,6 +3,9 @@
  *  patch_hdmi.c - routines for HDMI/DisplayPort codecs
  *
  *  Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
+ *  Copyright (c) 2006 ATI Technologies Inc.
+ *  Copyright (c) 2008 NVIDIA Corp.  All rights reserved.
+ *  Copyright (c) 2008 Wei Ni <wni@nvidia.com>
  *
  *  Authors:
  *                     Wu Fengguang <wfg@linux.intel.com>
  *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+/*
+ * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
+ * could support two independent pipes, each of them can be connected to one or
+ * more ports (DVI, HDMI or DisplayPort).
+ *
+ * The HDA correspondence of pipes/ports are converter/pin nodes.
+ */
+#define MAX_HDMI_CVTS  3
+#define MAX_HDMI_PINS  3
 
 struct hdmi_spec {
        int num_cvts;
@@ -49,10 +68,10 @@ struct hdmi_spec {
        struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
 
        /*
-        * nvhdmi specific
+        * ati/nvhdmi specific
         */
        struct hda_multi_out multiout;
-       unsigned int codec_type;
+       struct hda_pcm_stream *pcm_playback;
 
        /* misc flags */
        /* PD bit indicates only the update, not the current state */
@@ -65,13 +84,25 @@ struct hdmi_audio_infoframe {
        u8 ver;  /* 0x01 */
        u8 len;  /* 0x0a */
 
-       u8 checksum;    /* PB0 */
+       u8 checksum;
+
        u8 CC02_CT47;   /* CC in bits 0:2, CT in 4:7 */
        u8 SS01_SF24;
        u8 CXT04;
        u8 CA;
        u8 LFEPBL01_LSV36_DM_INH7;
-       u8 reserved[5]; /* PB6 - PB10 */
+};
+
+struct dp_audio_infoframe {
+       u8 type; /* 0x84 */
+       u8 len;  /* 0x1b */
+       u8 ver;  /* 0x11 << 2 */
+
+       u8 CC02_CT47;   /* match with HDMI infoframe from this on */
+       u8 SS01_SF24;
+       u8 CXT04;
+       u8 CA;
+       u8 LFEPBL01_LSV36_DM_INH7;
 };
 
 /*
@@ -162,7 +193,7 @@ static int hdmi_channel_mapping[0x32][8] = {
        /* 4ch */
        [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
        /* surround41 */
-       [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+       [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 },
        /* surround50 */
        [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
        /* surround51 */
@@ -175,7 +206,7 @@ static int hdmi_channel_mapping[0x32][8] = {
  * This is an ordered list!
  *
  * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
+ * hdmi_channel_allocation().
  */
 static struct cea_channel_speaker_allocation channel_allocations[] = {
 /*                       channel:   7     6    5    4    3     2    1    0  */
@@ -352,14 +383,14 @@ static void init_channel_allocations(void)
  *
  * TODO: it could select the wrong CA from multiple candidates.
 */
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
-                                        struct hdmi_audio_infoframe *ai)
+static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+                                  int channels)
 {
        struct hdmi_spec *spec = codec->spec;
        struct hdmi_eld *eld;
        int i;
+       int ca = 0;
        int spk_mask = 0;
-       int channels = 1 + (ai->CC02_CT47 & 0x7);
        char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 
        /*
@@ -397,16 +428,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
                if (channels == channel_allocations[i].channels &&
                    (spk_mask & channel_allocations[i].spk_mask) ==
                                channel_allocations[i].spk_mask) {
-                       ai->CA = channel_allocations[i].ca_index;
+                       ca = channel_allocations[i].ca_index;
                        break;
                }
        }
 
        snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
        snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
-                   ai->CA, channels, buf);
+                   ca, channels, buf);
 
-       return ai->CA;
+       return ca;
 }
 
 static void hdmi_debug_channel_mapping(struct hda_codec *codec,
@@ -428,10 +459,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec,
 
 static void hdmi_setup_channel_mapping(struct hda_codec *codec,
                                       hda_nid_t pin_nid,
-                                      struct hdmi_audio_infoframe *ai)
+                                      int ca)
 {
        int i;
-       int ca = ai->CA;
        int err;
 
        if (hdmi_channel_mapping[ca][1] == 0) {
@@ -528,41 +558,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
 #endif
 }
 
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai)
 {
-       u8 *bytes = (u8 *)ai;
+       u8 *bytes = (u8 *)hdmi_ai;
        u8 sum = 0;
        int i;
 
-       ai->checksum = 0;
+       hdmi_ai->checksum = 0;
 
-       for (i = 0; i < sizeof(*ai); i++)
+       for (i = 0; i < sizeof(*hdmi_ai); i++)
                sum += bytes[i];
 
-       ai->checksum = -sum;
+       hdmi_ai->checksum = -sum;
 }
 
 static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
                                      hda_nid_t pin_nid,
-                                     struct hdmi_audio_infoframe *ai)
+                                     u8 *dip, int size)
 {
-       u8 *bytes = (u8 *)ai;
        int i;
 
        hdmi_debug_dip_size(codec, pin_nid);
        hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
 
-       hdmi_checksum_audio_infoframe(ai);
-
        hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++)
-               hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+       for (i = 0; i < size; i++)
+               hdmi_write_dip_byte(codec, pin_nid, dip[i]);
 }
 
 static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
-                                   struct hdmi_audio_infoframe *ai)
+                                   u8 *dip, int size)
 {
-       u8 *bytes = (u8 *)ai;
        u8 val;
        int i;
 
@@ -571,10 +597,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
                return false;
 
        hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
-       for (i = 0; i < sizeof(*ai); i++) {
+       for (i = 0; i < size; i++) {
                val = snd_hda_codec_read(codec, pin_nid, 0,
                                         AC_VERB_GET_HDMI_DIP_DATA, 0);
-               if (val != bytes[i])
+               if (val != dip[i])
                        return false;
        }
 
@@ -586,15 +612,13 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 {
        struct hdmi_spec *spec = codec->spec;
        hda_nid_t pin_nid;
+       int channels = substream->runtime->channels;
+       int ca;
        int i;
-       struct hdmi_audio_infoframe ai = {
-               .type           = 0x84,
-               .ver            = 0x01,
-               .len            = 0x0a,
-               .CC02_CT47      = substream->runtime->channels - 1,
-       };
+       u8 ai[max(sizeof(struct hdmi_audio_infoframe),
+                 sizeof(struct dp_audio_infoframe))];
 
-       hdmi_setup_channel_allocation(codec, nid, &ai);
+       ca = hdmi_channel_allocation(codec, nid, channels);
 
        for (i = 0; i < spec->num_pins; i++) {
                if (spec->pin_cvt[i] != nid)
@@ -603,14 +627,45 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
                        continue;
 
                pin_nid = spec->pin[i];
-               if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+
+               memset(ai, 0, sizeof(ai));
+               if (spec->sink_eld[i].conn_type == 0) { /* HDMI */
+                       struct hdmi_audio_infoframe *hdmi_ai;
+
+                       hdmi_ai = (struct hdmi_audio_infoframe *)ai;
+                       hdmi_ai->type           = 0x84;
+                       hdmi_ai->ver            = 0x01;
+                       hdmi_ai->len            = 0x0a;
+                       hdmi_ai->CC02_CT47      = channels - 1;
+                       hdmi_checksum_audio_infoframe(hdmi_ai);
+               } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */
+                       struct dp_audio_infoframe *dp_ai;
+
+                       dp_ai = (struct dp_audio_infoframe *)ai;
+                       dp_ai->type             = 0x84;
+                       dp_ai->len              = 0x1b;
+                       dp_ai->ver              = 0x11 << 2;
+                       dp_ai->CC02_CT47        = channels - 1;
+               } else {
+                       snd_printd("HDMI: unknown connection type at pin %d\n",
+                                  pin_nid);
+                       continue;
+               }
+
+               /*
+                * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
+                * sizeof(*dp_ai) to avoid partial match/update problems when
+                * the user switches between HDMI/DP monitors.
+                */
+               if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) {
                        snd_printdd("hdmi_setup_audio_infoframe: "
                                    "cvt=%d pin=%d channels=%d\n",
                                    nid, pin_nid,
-                                   substream->runtime->channels);
-                       hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+                                   channels);
+                       hdmi_setup_channel_mapping(codec, pin_nid, ca);
                        hdmi_stop_infoframe_trans(codec, pin_nid);
-                       hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+                       hdmi_fill_audio_infoframe(codec, pin_nid,
+                                                 ai, sizeof(ai));
                        hdmi_start_infoframe_trans(codec, pin_nid);
                }
        }
@@ -791,7 +846,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
 /*
  * HDA/HDMI auto parsing
  */
-
 static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
 {
        struct hdmi_spec *spec = codec->spec;
@@ -922,3 +976,664 @@ static int hdmi_parse_codec(struct hda_codec *codec)
        return 0;
 }
 
+/*
+ */
+static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = {
+       "HDMI 0",
+       "HDMI 1",
+       "HDMI 2",
+};
+
+/*
+ * HDMI callbacks
+ */
+
+static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                          struct hda_codec *codec,
+                                          unsigned int stream_tag,
+                                          unsigned int format,
+                                          struct snd_pcm_substream *substream)
+{
+       hdmi_set_channel_count(codec, hinfo->nid,
+                              substream->runtime->channels);
+
+       hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+       return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+}
+
+static struct hda_pcm_stream generic_hdmi_pcm_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .ops = {
+               .open = hdmi_pcm_open,
+               .prepare = generic_hdmi_playback_pcm_prepare,
+       },
+};
+
+static int generic_hdmi_build_pcms(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec = codec->spec;
+       struct hda_pcm *info = spec->pcm_rec;
+       int i;
+
+       codec->num_pcms = spec->num_cvts;
+       codec->pcm_info = info;
+
+       for (i = 0; i < codec->num_pcms; i++, info++) {
+               unsigned int chans;
+               struct hda_pcm_stream *pstr;
+
+               chans = get_wcaps(codec, spec->cvt[i]);
+               chans = get_wcaps_channels(chans);
+
+               info->name = generic_hdmi_pcm_names[i];
+               info->pcm_type = HDA_PCM_TYPE_HDMI;
+               pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
+               if (spec->pcm_playback)
+                       *pstr = *spec->pcm_playback;
+               else
+                       *pstr = generic_hdmi_pcm_playback;
+               pstr->nid = spec->cvt[i];
+               if (pstr->channels_max <= 2 && chans && chans <= 16)
+                       pstr->channels_max = chans;
+       }
+
+       return 0;
+}
+
+static int generic_hdmi_build_controls(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int err;
+       int i;
+
+       for (i = 0; i < codec->num_pcms; i++) {
+               err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int generic_hdmi_init(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int i;
+
+       for (i = 0; spec->pin[i]; i++) {
+               hdmi_enable_output(codec, spec->pin[i]);
+               snd_hda_codec_write(codec, spec->pin[i], 0,
+                                   AC_VERB_SET_UNSOLICITED_ENABLE,
+                                   AC_USRSP_EN | spec->pin[i]);
+       }
+       return 0;
+}
+
+static void generic_hdmi_free(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int i;
+
+       for (i = 0; i < spec->num_pins; i++)
+               snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+
+       kfree(spec);
+}
+
+static struct hda_codec_ops generic_hdmi_patch_ops = {
+       .init                   = generic_hdmi_init,
+       .free                   = generic_hdmi_free,
+       .build_pcms             = generic_hdmi_build_pcms,
+       .build_controls         = generic_hdmi_build_controls,
+       .unsol_event            = hdmi_unsol_event,
+};
+
+static int patch_generic_hdmi(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+       int i;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+       if (hdmi_parse_codec(codec) < 0) {
+               codec->spec = NULL;
+               kfree(spec);
+               return -EINVAL;
+       }
+       codec->patch_ops = generic_hdmi_patch_ops;
+
+       for (i = 0; i < spec->num_pins; i++)
+               snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+       init_channel_allocations();
+
+       return 0;
+}
+
+/*
+ * Nvidia specific implementations
+ */
+
+#define Nv_VERB_SET_Channel_Allocation          0xF79
+#define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
+#define Nv_VERB_SET_Audio_Protection_On         0xF98
+#define Nv_VERB_SET_Audio_Protection_Off        0xF99
+
+#define nvhdmi_master_con_nid_7x       0x04
+#define nvhdmi_master_pin_nid_7x       0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
+       /*front, rear, clfe, rear_surr */
+       0x6, 0x8, 0xa, 0xc,
+};
+
+static struct hda_verb nvhdmi_basic_init_7x[] = {
+       /* set audio protect on */
+       { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
+       /* enable digital output on pin widget */
+       { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
+       { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
+       { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
+       { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
+       { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
+       {} /* terminator */
+};
+
+#ifdef LIMITED_RATE_FMT_SUPPORT
+/* support only the safe format and rate */
+#define SUPPORTED_RATES                SNDRV_PCM_RATE_48000
+#define SUPPORTED_MAXBPS       16
+#define SUPPORTED_FORMATS      SNDRV_PCM_FMTBIT_S16_LE
+#else
+/* support all rates and formats */
+#define SUPPORTED_RATES \
+       (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
+       SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
+        SNDRV_PCM_RATE_192000)
+#define SUPPORTED_MAXBPS       24
+#define SUPPORTED_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
+#endif
+
+static int nvhdmi_7x_init(struct hda_codec *codec)
+{
+       snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+       return 0;
+}
+
+static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
+                                   struct hda_codec *codec,
+                                   struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo,
+                                    struct hda_codec *codec,
+                                    struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                      struct hda_codec *codec,
+                                      unsigned int stream_tag,
+                                      unsigned int format,
+                                      struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+                                            stream_tag, format, substream);
+}
+
+static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
+                                  struct hda_codec *codec,
+                                  struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int i;
+
+       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
+                       0, AC_VERB_SET_CHANNEL_STREAMID, 0);
+       for (i = 0; i < 4; i++) {
+               /* set the stream id */
+               snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
+                               AC_VERB_SET_CHANNEL_STREAMID, 0);
+               /* set the stream format */
+               snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
+                               AC_VERB_SET_STREAM_FORMAT, 0);
+       }
+
+       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                    struct hda_codec *codec,
+                                    unsigned int stream_tag,
+                                    unsigned int format,
+                                    struct snd_pcm_substream *substream)
+{
+       int chs;
+       unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
+       int i;
+
+       mutex_lock(&codec->spdif_mutex);
+
+       chs = substream->runtime->channels;
+       chan = chs ? (chs - 1) : 1;
+
+       switch (chs) {
+       default:
+       case 0:
+       case 2:
+               chanmask = 0x00;
+               break;
+       case 4:
+               chanmask = 0x08;
+               break;
+       case 6:
+               chanmask = 0x0b;
+               break;
+       case 8:
+               chanmask = 0x13;
+               break;
+       }
+       dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
+       dataDCC2 = 0x2;
+
+       /* set the Audio InforFrame Channel Allocation */
+       snd_hda_codec_write(codec, 0x1, 0,
+                       Nv_VERB_SET_Channel_Allocation, chanmask);
+
+       /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
+       if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
+               snd_hda_codec_write(codec,
+                               nvhdmi_master_con_nid_7x,
+                               0,
+                               AC_VERB_SET_DIGI_CONVERT_1,
+                               codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+
+       /* set the stream id */
+       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
+                       AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
+
+       /* set the stream format */
+       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
+                       AC_VERB_SET_STREAM_FORMAT, format);
+
+       /* turn on again (if needed) */
+       /* enable and set the channel status audio/data flag */
+       if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
+               snd_hda_codec_write(codec,
+                               nvhdmi_master_con_nid_7x,
+                               0,
+                               AC_VERB_SET_DIGI_CONVERT_1,
+                               codec->spdif_ctls & 0xff);
+               snd_hda_codec_write(codec,
+                               nvhdmi_master_con_nid_7x,
+                               0,
+                               AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (chs == 2)
+                       channel_id = 0;
+               else
+                       channel_id = i * 2;
+
+               /* turn off SPDIF once;
+                *otherwise the IEC958 bits won't be updated
+                */
+               if (codec->spdif_status_reset &&
+               (codec->spdif_ctls & AC_DIG1_ENABLE))
+                       snd_hda_codec_write(codec,
+                               nvhdmi_con_nids_7x[i],
+                               0,
+                               AC_VERB_SET_DIGI_CONVERT_1,
+                               codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+               /* set the stream id */
+               snd_hda_codec_write(codec,
+                               nvhdmi_con_nids_7x[i],
+                               0,
+                               AC_VERB_SET_CHANNEL_STREAMID,
+                               (stream_tag << 4) | channel_id);
+               /* set the stream format */
+               snd_hda_codec_write(codec,
+                               nvhdmi_con_nids_7x[i],
+                               0,
+                               AC_VERB_SET_STREAM_FORMAT,
+                               format);
+               /* turn on again (if needed) */
+               /* enable and set the channel status audio/data flag */
+               if (codec->spdif_status_reset &&
+               (codec->spdif_ctls & AC_DIG1_ENABLE)) {
+                       snd_hda_codec_write(codec,
+                                       nvhdmi_con_nids_7x[i],
+                                       0,
+                                       AC_VERB_SET_DIGI_CONVERT_1,
+                                       codec->spdif_ctls & 0xff);
+                       snd_hda_codec_write(codec,
+                                       nvhdmi_con_nids_7x[i],
+                                       0,
+                                       AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
+               }
+       }
+
+       /* set the Audio Info Frame Checksum */
+       snd_hda_codec_write(codec, 0x1, 0,
+                       Nv_VERB_SET_Info_Frame_Checksum,
+                       (0x71 - chan - chanmask));
+
+       mutex_unlock(&codec->spdif_mutex);
+       return 0;
+}
+
+static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 8,
+       .nid = nvhdmi_master_con_nid_7x,
+       .rates = SUPPORTED_RATES,
+       .maxbps = SUPPORTED_MAXBPS,
+       .formats = SUPPORTED_FORMATS,
+       .ops = {
+               .open = simple_playback_pcm_open,
+               .close = nvhdmi_8ch_7x_pcm_close,
+               .prepare = nvhdmi_8ch_7x_pcm_prepare
+       },
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = nvhdmi_master_con_nid_7x,
+       .rates = SUPPORTED_RATES,
+       .maxbps = SUPPORTED_MAXBPS,
+       .formats = SUPPORTED_FORMATS,
+       .ops = {
+               .open = simple_playback_pcm_open,
+               .close = simple_playback_pcm_close,
+               .prepare = simple_playback_pcm_prepare
+       },
+};
+
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
+       .build_controls = generic_hdmi_build_controls,
+       .build_pcms = generic_hdmi_build_pcms,
+       .init = nvhdmi_7x_init,
+       .free = generic_hdmi_free,
+};
+
+static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
+       .build_controls = generic_hdmi_build_controls,
+       .build_pcms = generic_hdmi_build_pcms,
+       .init = nvhdmi_7x_init,
+       .free = generic_hdmi_free,
+};
+
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+       int err = patch_generic_hdmi(codec);
+
+       if (err < 0)
+               return err;
+       spec = codec->spec;
+       spec->old_pin_detect = 1;
+       return 0;
+}
+
+static int patch_nvhdmi_2ch(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+
+       spec->multiout.num_dacs = 0;  /* no analog */
+       spec->multiout.max_channels = 2;
+       spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+       spec->old_pin_detect = 1;
+       spec->num_cvts = 1;
+       spec->cvt[0] = nvhdmi_master_con_nid_7x;
+       spec->pcm_playback = &nvhdmi_pcm_playback_2ch;
+
+       codec->patch_ops = nvhdmi_patch_ops_2ch;
+
+       return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+       int err = patch_nvhdmi_2ch(codec);
+
+       if (err < 0)
+               return err;
+       spec = codec->spec;
+       spec->multiout.max_channels = 8;
+       spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x;
+       codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
+       return 0;
+}
+
+/*
+ * ATI-specific implementations
+ *
+ * FIXME: we may omit the whole this and use the generic code once after
+ * it's confirmed to work.
+ */
+
+#define ATIHDMI_CVT_NID                0x02    /* audio converter */
+#define ATIHDMI_PIN_NID                0x03    /* HDMI output pin */
+
+static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+                                       struct hda_codec *codec,
+                                       unsigned int stream_tag,
+                                       unsigned int format,
+                                       struct snd_pcm_substream *substream)
+{
+       struct hdmi_spec *spec = codec->spec;
+       int chans = substream->runtime->channels;
+       int i, err;
+
+       err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format,
+                                         substream);
+       if (err < 0)
+               return err;
+       snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT,
+                           chans - 1);
+       /* FIXME: XXX */
+       for (i = 0; i < chans; i++) {
+               snd_hda_codec_write(codec, spec->cvt[0], 0,
+                                   AC_VERB_SET_HDMI_CHAN_SLOT,
+                                   (i << 4) | i);
+       }
+       return 0;
+}
+
+static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
+       .substreams = 1,
+       .channels_min = 2,
+       .channels_max = 2,
+       .nid = ATIHDMI_CVT_NID,
+       .ops = {
+               .open = simple_playback_pcm_open,
+               .close = simple_playback_pcm_close,
+               .prepare = atihdmi_playback_pcm_prepare
+       },
+};
+
+static struct hda_verb atihdmi_basic_init[] = {
+       /* enable digital output on pin widget */
+       { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+       {} /* terminator */
+};
+
+static int atihdmi_init(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec = codec->spec;
+
+       snd_hda_sequence_write(codec, atihdmi_basic_init);
+       /* SI codec requires to unmute the pin */
+       if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP)
+               snd_hda_codec_write(codec, spec->pin[0], 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE,
+                                   AMP_OUT_UNMUTE);
+       return 0;
+}
+
+static struct hda_codec_ops atihdmi_patch_ops = {
+       .build_controls = generic_hdmi_build_controls,
+       .build_pcms = generic_hdmi_build_pcms,
+       .init = atihdmi_init,
+       .free = generic_hdmi_free,
+};
+
+
+static int patch_atihdmi(struct hda_codec *codec)
+{
+       struct hdmi_spec *spec;
+
+       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+       if (spec == NULL)
+               return -ENOMEM;
+
+       codec->spec = spec;
+
+       spec->multiout.num_dacs = 0;      /* no analog */
+       spec->multiout.max_channels = 2;
+       spec->multiout.dig_out_nid = ATIHDMI_CVT_NID;
+       spec->num_cvts = 1;
+       spec->cvt[0] = ATIHDMI_CVT_NID;
+       spec->pin[0] = ATIHDMI_PIN_NID;
+       spec->pcm_playback = &atihdmi_pcm_digital_playback;
+
+       codec->patch_ops = atihdmi_patch_ops;
+
+       return 0;
+}
+
+
+/*
+ * patch entries
+ */
+static struct hda_codec_preset snd_hda_preset_hdmi[] = {
+{ .id = 0x1002793c, .name = "RS600 HDMI",      .patch = patch_atihdmi },
+{ .id = 0x10027919, .name = "RS600 HDMI",      .patch = patch_atihdmi },
+{ .id = 0x1002791a, .name = "RS690/780 HDMI",  .patch = patch_atihdmi },
+{ .id = 0x1002aa01, .name = "R6xx HDMI",       .patch = patch_atihdmi },
+{ .id = 0x10951390, .name = "SiI1390 HDMI",    .patch = patch_generic_hdmi },
+{ .id = 0x10951392, .name = "SiI1392 HDMI",    .patch = patch_generic_hdmi },
+{ .id = 0x17e80047, .name = "Chrontel HDMI",   .patch = patch_generic_hdmi },
+{ .id = 0x10de0002, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
+{ .id = 0x10de0003, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
+{ .id = 0x10de0005, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
+{ .id = 0x10de0006, .name = "MCP77/78 HDMI",   .patch = patch_nvhdmi_8ch_7x },
+{ .id = 0x10de0007, .name = "MCP79/7A HDMI",   .patch = patch_nvhdmi_8ch_7x },
+{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de000c, .name = "MCP89 HDMI",      .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP",  .patch = patch_nvhdmi_8ch_89 },
+{ .id = 0x10de0067, .name = "MCP67 HDMI",      .patch = patch_nvhdmi_2ch },
+{ .id = 0x10de8001, .name = "MCP73 HDMI",      .patch = patch_nvhdmi_2ch },
+{ .id = 0x80860054, .name = "IbexPeak HDMI",   .patch = patch_generic_hdmi },
+{ .id = 0x80862801, .name = "Bearlake HDMI",   .patch = patch_generic_hdmi },
+{ .id = 0x80862802, .name = "Cantiga HDMI",    .patch = patch_generic_hdmi },
+{ .id = 0x80862803, .name = "Eaglelake HDMI",  .patch = patch_generic_hdmi },
+{ .id = 0x80862804, .name = "IbexPeak HDMI",   .patch = patch_generic_hdmi },
+{ .id = 0x80862805, .name = "CougarPoint HDMI",        .patch = patch_generic_hdmi },
+{ .id = 0x808629fb, .name = "Crestline HDMI",  .patch = patch_generic_hdmi },
+{} /* terminator */
+};
+
+MODULE_ALIAS("snd-hda-codec-id:1002793c");
+MODULE_ALIAS("snd-hda-codec-id:10027919");
+MODULE_ALIAS("snd-hda-codec-id:1002791a");
+MODULE_ALIAS("snd-hda-codec-id:1002aa01");
+MODULE_ALIAS("snd-hda-codec-id:10951390");
+MODULE_ALIAS("snd-hda-codec-id:10951392");
+MODULE_ALIAS("snd-hda-codec-id:10de0002");
+MODULE_ALIAS("snd-hda-codec-id:10de0003");
+MODULE_ALIAS("snd-hda-codec-id:10de0005");
+MODULE_ALIAS("snd-hda-codec-id:10de0006");
+MODULE_ALIAS("snd-hda-codec-id:10de0007");
+MODULE_ALIAS("snd-hda-codec-id:10de000a");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
+MODULE_ALIAS("snd-hda-codec-id:10de0010");
+MODULE_ALIAS("snd-hda-codec-id:10de0011");
+MODULE_ALIAS("snd-hda-codec-id:10de0012");
+MODULE_ALIAS("snd-hda-codec-id:10de0013");
+MODULE_ALIAS("snd-hda-codec-id:10de0014");
+MODULE_ALIAS("snd-hda-codec-id:10de0018");
+MODULE_ALIAS("snd-hda-codec-id:10de0019");
+MODULE_ALIAS("snd-hda-codec-id:10de001a");
+MODULE_ALIAS("snd-hda-codec-id:10de001b");
+MODULE_ALIAS("snd-hda-codec-id:10de001c");
+MODULE_ALIAS("snd-hda-codec-id:10de0040");
+MODULE_ALIAS("snd-hda-codec-id:10de0041");
+MODULE_ALIAS("snd-hda-codec-id:10de0042");
+MODULE_ALIAS("snd-hda-codec-id:10de0043");
+MODULE_ALIAS("snd-hda-codec-id:10de0044");
+MODULE_ALIAS("snd-hda-codec-id:10de0067");
+MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:17e80047");
+MODULE_ALIAS("snd-hda-codec-id:80860054");
+MODULE_ALIAS("snd-hda-codec-id:80862801");
+MODULE_ALIAS("snd-hda-codec-id:80862802");
+MODULE_ALIAS("snd-hda-codec-id:80862803");
+MODULE_ALIAS("snd-hda-codec-id:80862804");
+MODULE_ALIAS("snd-hda-codec-id:80862805");
+MODULE_ALIAS("snd-hda-codec-id:808629fb");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HDMI HD-audio codec");
+MODULE_ALIAS("snd-hda-codec-intelhdmi");
+MODULE_ALIAS("snd-hda-codec-nvhdmi");
+MODULE_ALIAS("snd-hda-codec-atihdmi");
+
+static struct hda_codec_preset_list intel_list = {
+       .preset = snd_hda_preset_hdmi,
+       .owner = THIS_MODULE,
+};
+
+static int __init patch_hdmi_init(void)
+{
+       return snd_hda_add_codec_preset(&intel_list);
+}
+
+static void __exit patch_hdmi_exit(void)
+{
+       snd_hda_delete_codec_preset(&intel_list);
+}
+
+module_init(patch_hdmi_init)
+module_exit(patch_hdmi_exit)
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
deleted file mode 100644 (file)
index 36a9b83..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- *
- *  patch_intelhdmi.c - Patch for Intel HDMI codecs
- *
- *  Copyright(c) 2008 Intel Corporation. All rights reserved.
- *
- *  Authors:
- *                     Jiang Zhe <zhe.jiang@intel.com>
- *                     Wu Fengguang <wfg@linux.intel.com>
- *
- *  Maintained by:
- *                     Wu Fengguang <wfg@linux.intel.com>
- *
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License as published by the Free
- *  Software Foundation; 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, write to the Free Software Foundation,
- *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "hda_codec.h"
-#include "hda_local.h"
-
-/*
- * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
- * could support two independent pipes, each of them can be connected to one or
- * more ports (DVI, HDMI or DisplayPort).
- *
- * The HDA correspondence of pipes/ports are converter/pin nodes.
- */
-#define MAX_HDMI_CVTS  3
-#define MAX_HDMI_PINS  3
-
-#include "patch_hdmi.c"
-
-static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
-       "INTEL HDMI 0",
-       "INTEL HDMI 1",
-       "INTEL HDMI 2",
-};
-
-/*
- * HDMI callbacks
- */
-
-static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-                                          struct hda_codec *codec,
-                                          unsigned int stream_tag,
-                                          unsigned int format,
-                                          struct snd_pcm_substream *substream)
-{
-       hdmi_set_channel_count(codec, hinfo->nid,
-                              substream->runtime->channels);
-
-       hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
-
-       return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
-}
-
-static struct hda_pcm_stream intel_hdmi_pcm_playback = {
-       .substreams = 1,
-       .channels_min = 2,
-       .ops = {
-               .open = hdmi_pcm_open,
-               .prepare = intel_hdmi_playback_pcm_prepare,
-       },
-};
-
-static int intel_hdmi_build_pcms(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
-       int i;
-
-       codec->num_pcms = spec->num_cvts;
-       codec->pcm_info = info;
-
-       for (i = 0; i < codec->num_pcms; i++, info++) {
-               unsigned int chans;
-
-               chans = get_wcaps(codec, spec->cvt[i]);
-               chans = get_wcaps_channels(chans);
-
-               info->name = intel_hdmi_pcm_names[i];
-               info->pcm_type = HDA_PCM_TYPE_HDMI;
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-                                                       intel_hdmi_pcm_playback;
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
-       }
-
-       return 0;
-}
-
-static int intel_hdmi_build_controls(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int err;
-       int i;
-
-       for (i = 0; i < codec->num_pcms; i++) {
-               err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int intel_hdmi_init(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int i;
-
-       for (i = 0; spec->pin[i]; i++) {
-               hdmi_enable_output(codec, spec->pin[i]);
-               snd_hda_codec_write(codec, spec->pin[i], 0,
-                                   AC_VERB_SET_UNSOLICITED_ENABLE,
-                                   AC_USRSP_EN | spec->pin[i]);
-       }
-       return 0;
-}
-
-static void intel_hdmi_free(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int i;
-
-       for (i = 0; i < spec->num_pins; i++)
-               snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
-
-       kfree(spec);
-}
-
-static struct hda_codec_ops intel_hdmi_patch_ops = {
-       .init                   = intel_hdmi_init,
-       .free                   = intel_hdmi_free,
-       .build_pcms             = intel_hdmi_build_pcms,
-       .build_controls         = intel_hdmi_build_controls,
-       .unsol_event            = hdmi_unsol_event,
-};
-
-static int patch_intel_hdmi(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec;
-       int i;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
-       if (hdmi_parse_codec(codec) < 0) {
-               codec->spec = NULL;
-               kfree(spec);
-               return -EINVAL;
-       }
-       codec->patch_ops = intel_hdmi_patch_ops;
-
-       for (i = 0; i < spec->num_pins; i++)
-               snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
-
-       init_channel_allocations();
-
-       return 0;
-}
-
-static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
-{ .id = 0x808629fb, .name = "Crestline HDMI",  .patch = patch_intel_hdmi },
-{ .id = 0x80862801, .name = "Bearlake HDMI",   .patch = patch_intel_hdmi },
-{ .id = 0x80862802, .name = "Cantiga HDMI",    .patch = patch_intel_hdmi },
-{ .id = 0x80862803, .name = "Eaglelake HDMI",  .patch = patch_intel_hdmi },
-{ .id = 0x80862804, .name = "IbexPeak HDMI",   .patch = patch_intel_hdmi },
-{ .id = 0x80860054, .name = "IbexPeak HDMI",   .patch = patch_intel_hdmi },
-{ .id = 0x80862805, .name = "CougarPoint HDMI",        .patch = patch_intel_hdmi },
-{ .id = 0x10951392, .name = "SiI1392 HDMI",    .patch = patch_intel_hdmi },
-{} /* terminator */
-};
-
-MODULE_ALIAS("snd-hda-codec-id:808629fb");
-MODULE_ALIAS("snd-hda-codec-id:80862801");
-MODULE_ALIAS("snd-hda-codec-id:80862802");
-MODULE_ALIAS("snd-hda-codec-id:80862803");
-MODULE_ALIAS("snd-hda-codec-id:80862804");
-MODULE_ALIAS("snd-hda-codec-id:80862805");
-MODULE_ALIAS("snd-hda-codec-id:80860054");
-MODULE_ALIAS("snd-hda-codec-id:10951392");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
-
-static struct hda_codec_preset_list intel_list = {
-       .preset = snd_hda_preset_intelhdmi,
-       .owner = THIS_MODULE,
-};
-
-static int __init patch_intelhdmi_init(void)
-{
-       return snd_hda_add_codec_preset(&intel_list);
-}
-
-static void __exit patch_intelhdmi_exit(void)
-{
-       snd_hda_delete_codec_preset(&intel_list);
-}
-
-module_init(patch_intelhdmi_init)
-module_exit(patch_intelhdmi_exit)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
deleted file mode 100644 (file)
index baa108b..0000000
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * Universal Interface for Intel High Definition Audio Codec
- *
- * HD audio interface patch for NVIDIA HDMI codecs
- *
- * Copyright (c) 2008 NVIDIA Corp.  All rights reserved.
- * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
- *
- *
- *  This driver 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 driver 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "hda_codec.h"
-#include "hda_local.h"
-
-#define MAX_HDMI_CVTS  1
-#define MAX_HDMI_PINS  1
-
-#include "patch_hdmi.c"
-
-static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
-       "NVIDIA HDMI",
-};
-
-/* define below to restrict the supported rates and formats */
-/* #define LIMITED_RATE_FMT_SUPPORT */
-
-enum HDACodec {
-       HDA_CODEC_NVIDIA_MCP7X,
-       HDA_CODEC_NVIDIA_MCP89,
-       HDA_CODEC_NVIDIA_GT21X,
-       HDA_CODEC_INVALID
-};
-
-#define Nv_VERB_SET_Channel_Allocation          0xF79
-#define Nv_VERB_SET_Info_Frame_Checksum         0xF7A
-#define Nv_VERB_SET_Audio_Protection_On         0xF98
-#define Nv_VERB_SET_Audio_Protection_Off        0xF99
-
-#define nvhdmi_master_con_nid_7x       0x04
-#define nvhdmi_master_pin_nid_7x       0x05
-
-#define nvhdmi_master_con_nid_89       0x04
-#define nvhdmi_master_pin_nid_89       0x05
-
-static hda_nid_t nvhdmi_con_nids_7x[4] = {
-       /*front, rear, clfe, rear_surr */
-       0x6, 0x8, 0xa, 0xc,
-};
-
-static struct hda_verb nvhdmi_basic_init_7x[] = {
-       /* set audio protect on */
-       { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
-       /* enable digital output on pin widget */
-       { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
-       { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
-       { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
-       { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
-       { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
-       {} /* terminator */
-};
-
-#ifdef LIMITED_RATE_FMT_SUPPORT
-/* support only the safe format and rate */
-#define SUPPORTED_RATES                SNDRV_PCM_RATE_48000
-#define SUPPORTED_MAXBPS       16
-#define SUPPORTED_FORMATS      SNDRV_PCM_FMTBIT_S16_LE
-#else
-/* support all rates and formats */
-#define SUPPORTED_RATES \
-       (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
-       SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
-        SNDRV_PCM_RATE_192000)
-#define SUPPORTED_MAXBPS       24
-#define SUPPORTED_FORMATS \
-       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-#endif
-
-/*
- * Controls
- */
-static int nvhdmi_build_controls(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int err;
-       int i;
-
-       if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
-       || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
-               for (i = 0; i < codec->num_pcms; i++) {
-                       err = snd_hda_create_spdif_out_ctls(codec,
-                                                           spec->cvt[i]);
-                       if (err < 0)
-                               return err;
-               }
-       } else {
-               err = snd_hda_create_spdif_out_ctls(codec,
-                                                   spec->multiout.dig_out_nid);
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
-}
-
-static int nvhdmi_init(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int i;
-       if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
-       || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
-               for (i = 0; spec->pin[i]; i++) {
-                       hdmi_enable_output(codec, spec->pin[i]);
-                       snd_hda_codec_write(codec, spec->pin[i], 0,
-                                           AC_VERB_SET_UNSOLICITED_ENABLE,
-                                           AC_USRSP_EN | spec->pin[i]);
-               }
-       } else {
-               snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
-       }
-       return 0;
-}
-
-static void nvhdmi_free(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int i;
-
-       if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
-       || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
-               for (i = 0; i < spec->num_pins; i++)
-                       snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
-       }
-
-       kfree(spec);
-}
-
-/*
- * Digital out
- */
-static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       struct snd_pcm_substream *substream)
-{
-       struct hdmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       struct snd_pcm_substream *substream)
-{
-       struct hdmi_spec *spec = codec->spec;
-       int i;
-
-       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
-                       0, AC_VERB_SET_CHANNEL_STREAMID, 0);
-       for (i = 0; i < 4; i++) {
-               /* set the stream id */
-               snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
-                               AC_VERB_SET_CHANNEL_STREAMID, 0);
-               /* set the stream format */
-               snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
-                               AC_VERB_SET_STREAM_FORMAT, 0);
-       }
-
-       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       struct snd_pcm_substream *substream)
-{
-       struct hdmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       unsigned int stream_tag,
-                                       unsigned int format,
-                                       struct snd_pcm_substream *substream)
-{
-       hdmi_set_channel_count(codec, hinfo->nid,
-                              substream->runtime->channels);
-
-       hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
-
-       return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
-}
-
-static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       unsigned int stream_tag,
-                                       unsigned int format,
-                                       struct snd_pcm_substream *substream)
-{
-       int chs;
-       unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
-       int i;
-
-       mutex_lock(&codec->spdif_mutex);
-
-       chs = substream->runtime->channels;
-       chan = chs ? (chs - 1) : 1;
-
-       switch (chs) {
-       default:
-       case 0:
-       case 2:
-               chanmask = 0x00;
-               break;
-       case 4:
-               chanmask = 0x08;
-               break;
-       case 6:
-               chanmask = 0x0b;
-               break;
-       case 8:
-               chanmask = 0x13;
-               break;
-       }
-       dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
-       dataDCC2 = 0x2;
-
-       /* set the Audio InforFrame Channel Allocation */
-       snd_hda_codec_write(codec, 0x1, 0,
-                       Nv_VERB_SET_Channel_Allocation, chanmask);
-
-       /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
-       if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
-               snd_hda_codec_write(codec,
-                               nvhdmi_master_con_nid_7x,
-                               0,
-                               AC_VERB_SET_DIGI_CONVERT_1,
-                               codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
-
-       /* set the stream id */
-       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
-                       AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
-
-       /* set the stream format */
-       snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
-                       AC_VERB_SET_STREAM_FORMAT, format);
-
-       /* turn on again (if needed) */
-       /* enable and set the channel status audio/data flag */
-       if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
-               snd_hda_codec_write(codec,
-                               nvhdmi_master_con_nid_7x,
-                               0,
-                               AC_VERB_SET_DIGI_CONVERT_1,
-                               codec->spdif_ctls & 0xff);
-               snd_hda_codec_write(codec,
-                               nvhdmi_master_con_nid_7x,
-                               0,
-                               AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
-       }
-
-       for (i = 0; i < 4; i++) {
-               if (chs == 2)
-                       channel_id = 0;
-               else
-                       channel_id = i * 2;
-
-               /* turn off SPDIF once;
-                *otherwise the IEC958 bits won't be updated
-                */
-               if (codec->spdif_status_reset &&
-               (codec->spdif_ctls & AC_DIG1_ENABLE))
-                       snd_hda_codec_write(codec,
-                               nvhdmi_con_nids_7x[i],
-                               0,
-                               AC_VERB_SET_DIGI_CONVERT_1,
-                               codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
-               /* set the stream id */
-               snd_hda_codec_write(codec,
-                               nvhdmi_con_nids_7x[i],
-                               0,
-                               AC_VERB_SET_CHANNEL_STREAMID,
-                               (stream_tag << 4) | channel_id);
-               /* set the stream format */
-               snd_hda_codec_write(codec,
-                               nvhdmi_con_nids_7x[i],
-                               0,
-                               AC_VERB_SET_STREAM_FORMAT,
-                               format);
-               /* turn on again (if needed) */
-               /* enable and set the channel status audio/data flag */
-               if (codec->spdif_status_reset &&
-               (codec->spdif_ctls & AC_DIG1_ENABLE)) {
-                       snd_hda_codec_write(codec,
-                                       nvhdmi_con_nids_7x[i],
-                                       0,
-                                       AC_VERB_SET_DIGI_CONVERT_1,
-                                       codec->spdif_ctls & 0xff);
-                       snd_hda_codec_write(codec,
-                                       nvhdmi_con_nids_7x[i],
-                                       0,
-                                       AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
-               }
-       }
-
-       /* set the Audio Info Frame Checksum */
-       snd_hda_codec_write(codec, 0x1, 0,
-                       Nv_VERB_SET_Info_Frame_Checksum,
-                       (0x71 - chan - chanmask));
-
-       mutex_unlock(&codec->spdif_mutex);
-       return 0;
-}
-
-static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
-                                       struct hda_codec *codec,
-                                       unsigned int stream_tag,
-                                       unsigned int format,
-                                       struct snd_pcm_substream *substream)
-{
-       struct hdmi_spec *spec = codec->spec;
-       return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-                                       format, substream);
-}
-
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
-       .substreams = 1,
-       .channels_min = 2,
-       .ops = {
-               .open = hdmi_pcm_open,
-               .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
-       },
-};
-
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 8,
-       .nid = nvhdmi_master_con_nid_7x,
-       .rates = SUPPORTED_RATES,
-       .maxbps = SUPPORTED_MAXBPS,
-       .formats = SUPPORTED_FORMATS,
-       .ops = {
-               .open = nvhdmi_dig_playback_pcm_open,
-               .close = nvhdmi_dig_playback_pcm_close_8ch_7x,
-               .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
-       },
-};
-
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
-       .substreams = 1,
-       .channels_min = 2,
-       .channels_max = 2,
-       .nid = nvhdmi_master_con_nid_7x,
-       .rates = SUPPORTED_RATES,
-       .maxbps = SUPPORTED_MAXBPS,
-       .formats = SUPPORTED_FORMATS,
-       .ops = {
-               .open = nvhdmi_dig_playback_pcm_open,
-               .close = nvhdmi_dig_playback_pcm_close_2ch,
-               .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
-       },
-};
-
-static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
-       int i;
-
-       codec->num_pcms = spec->num_cvts;
-       codec->pcm_info = info;
-
-       for (i = 0; i < codec->num_pcms; i++, info++) {
-               unsigned int chans;
-
-               chans = get_wcaps(codec, spec->cvt[i]);
-               chans = get_wcaps_channels(chans);
-
-               info->name = nvhdmi_pcm_names[i];
-               info->pcm_type = HDA_PCM_TYPE_HDMI;
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-                                       = nvhdmi_pcm_digital_playback_8ch_89;
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
-               info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
-       }
-
-       return 0;
-}
-
-static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
-
-       codec->num_pcms = 1;
-       codec->pcm_info = info;
-
-       info->name = "NVIDIA HDMI";
-       info->pcm_type = HDA_PCM_TYPE_HDMI;
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-                                       = nvhdmi_pcm_digital_playback_8ch_7x;
-
-       return 0;
-}
-
-static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec = codec->spec;
-       struct hda_pcm *info = spec->pcm_rec;
-
-       codec->num_pcms = 1;
-       codec->pcm_info = info;
-
-       info->name = "NVIDIA HDMI";
-       info->pcm_type = HDA_PCM_TYPE_HDMI;
-       info->stream[SNDRV_PCM_STREAM_PLAYBACK]
-                                       = nvhdmi_pcm_digital_playback_2ch;
-
-       return 0;
-}
-
-static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
-       .build_controls = nvhdmi_build_controls,
-       .build_pcms = nvhdmi_build_pcms_8ch_89,
-       .init = nvhdmi_init,
-       .free = nvhdmi_free,
-       .unsol_event = hdmi_unsol_event,
-};
-
-static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
-       .build_controls = nvhdmi_build_controls,
-       .build_pcms = nvhdmi_build_pcms_8ch_7x,
-       .init = nvhdmi_init,
-       .free = nvhdmi_free,
-};
-
-static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
-       .build_controls = nvhdmi_build_controls,
-       .build_pcms = nvhdmi_build_pcms_2ch,
-       .init = nvhdmi_init,
-       .free = nvhdmi_free,
-};
-
-static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec;
-       int i;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
-       spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
-       spec->old_pin_detect = 1;
-
-       if (hdmi_parse_codec(codec) < 0) {
-               codec->spec = NULL;
-               kfree(spec);
-               return -EINVAL;
-       }
-       codec->patch_ops = nvhdmi_patch_ops_8ch_89;
-
-       for (i = 0; i < spec->num_pins; i++)
-               snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
-
-       init_channel_allocations();
-
-       return 0;
-}
-
-static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
-
-       spec->multiout.num_dacs = 0;  /* no analog */
-       spec->multiout.max_channels = 8;
-       spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
-       spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
-       spec->old_pin_detect = 1;
-
-       codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
-
-       return 0;
-}
-
-static int patch_nvhdmi_2ch(struct hda_codec *codec)
-{
-       struct hdmi_spec *spec;
-
-       spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-       if (spec == NULL)
-               return -ENOMEM;
-
-       codec->spec = spec;
-
-       spec->multiout.num_dacs = 0;  /* no analog */
-       spec->multiout.max_channels = 2;
-       spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
-       spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
-       spec->old_pin_detect = 1;
-
-       codec->patch_ops = nvhdmi_patch_ops_2ch;
-
-       return 0;
-}
-
-/*
- * patch entries
- */
-static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
-       { .id = 0x10de0002, .name = "MCP77/78 HDMI",  .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de0003, .name = "MCP77/78 HDMI",  .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de0005, .name = "MCP77/78 HDMI",  .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de0006, .name = "MCP77/78 HDMI",  .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de0007, .name = "MCP79/7A HDMI",  .patch = patch_nvhdmi_8ch_7x },
-       { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de000c, .name = "MCP89 HDMI",     .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
-       { .id = 0x10de0067, .name = "MCP67 HDMI",     .patch = patch_nvhdmi_2ch },
-       { .id = 0x10de8001, .name = "MCP73 HDMI",     .patch = patch_nvhdmi_2ch },
-       {} /* terminator */
-};
-
-MODULE_ALIAS("snd-hda-codec-id:10de0002");
-MODULE_ALIAS("snd-hda-codec-id:10de0003");
-MODULE_ALIAS("snd-hda-codec-id:10de0005");
-MODULE_ALIAS("snd-hda-codec-id:10de0006");
-MODULE_ALIAS("snd-hda-codec-id:10de0007");
-MODULE_ALIAS("snd-hda-codec-id:10de000a");
-MODULE_ALIAS("snd-hda-codec-id:10de000b");
-MODULE_ALIAS("snd-hda-codec-id:10de000c");
-MODULE_ALIAS("snd-hda-codec-id:10de000d");
-MODULE_ALIAS("snd-hda-codec-id:10de0010");
-MODULE_ALIAS("snd-hda-codec-id:10de0011");
-MODULE_ALIAS("snd-hda-codec-id:10de0012");
-MODULE_ALIAS("snd-hda-codec-id:10de0013");
-MODULE_ALIAS("snd-hda-codec-id:10de0014");
-MODULE_ALIAS("snd-hda-codec-id:10de0018");
-MODULE_ALIAS("snd-hda-codec-id:10de0019");
-MODULE_ALIAS("snd-hda-codec-id:10de001a");
-MODULE_ALIAS("snd-hda-codec-id:10de001b");
-MODULE_ALIAS("snd-hda-codec-id:10de001c");
-MODULE_ALIAS("snd-hda-codec-id:10de0040");
-MODULE_ALIAS("snd-hda-codec-id:10de0041");
-MODULE_ALIAS("snd-hda-codec-id:10de0042");
-MODULE_ALIAS("snd-hda-codec-id:10de0043");
-MODULE_ALIAS("snd-hda-codec-id:10de0044");
-MODULE_ALIAS("snd-hda-codec-id:10de0067");
-MODULE_ALIAS("snd-hda-codec-id:10de8001");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
-
-static struct hda_codec_preset_list nvhdmi_list = {
-       .preset = snd_hda_preset_nvhdmi,
-       .owner = THIS_MODULE,
-};
-
-static int __init patch_nvhdmi_init(void)
-{
-       return snd_hda_add_codec_preset(&nvhdmi_list);
-}
-
-static void __exit patch_nvhdmi_exit(void)
-{
-       snd_hda_delete_codec_preset(&nvhdmi_list);
-}
-
-module_init(patch_nvhdmi_init)
-module_exit(patch_nvhdmi_exit)
index a432e6e..5f00589 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <sound/core.h>
+#include <sound/jack.h>
 #include "hda_codec.h"
 #include "hda_local.h"
 #include "hda_beep.h"
@@ -282,6 +283,12 @@ struct alc_mic_route {
        unsigned char amix_idx;
 };
 
+struct alc_jack {
+       hda_nid_t nid;
+       int type;
+       struct snd_jack *jack;
+};
+
 #define MUX_IDX_UNDEF  ((unsigned char)-1)
 
 struct alc_customize_define {
@@ -294,6 +301,7 @@ struct alc_customize_define {
        unsigned int  platform_type:1;
        unsigned int  swap:1;
        unsigned int  override:1;
+       unsigned int  fixup:1; /* Means that this sku is set by driver, not read from hw */
 };
 
 struct alc_spec {
@@ -357,6 +365,9 @@ struct alc_spec {
        /* PCM information */
        struct hda_pcm pcm_rec[3];      /* used in alc_build_pcms() */
 
+       /* jack detection */
+       struct snd_array jacks;
+
        /* dynamic controls, init_verbs and input_mux */
        struct auto_pin_cfg autocfg;
        struct alc_customize_define cdefine;
@@ -383,6 +394,7 @@ struct alc_spec {
        unsigned int no_analog :1; /* digital I/O only */
        unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
        int init_amp;
+       int codec_variant;      /* flag for other variants */
 
        /* for virtual master */
        hda_nid_t vmaster_nid;
@@ -846,7 +858,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
 {
        unsigned int val = PIN_IN;
 
-       if (auto_pin_type <= AUTO_PIN_FRONT_MIC) {
+       if (auto_pin_type == AUTO_PIN_MIC) {
                unsigned int pincap;
                unsigned int oldval;
                oldval = snd_hda_codec_read(codec, nid, 0,
@@ -866,6 +878,28 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
 }
 
+static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+
+       if (!cfg->line_outs) {
+               while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
+                      cfg->line_out_pins[cfg->line_outs])
+                       cfg->line_outs++;
+       }
+       if (!cfg->speaker_outs) {
+               while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
+                      cfg->speaker_pins[cfg->speaker_outs])
+                       cfg->speaker_outs++;
+       }
+       if (!cfg->hp_outs) {
+               while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
+                      cfg->hp_pins[cfg->hp_outs])
+                       cfg->hp_outs++;
+       }
+}
+
 /*
  */
 static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
@@ -934,6 +968,8 @@ static void setup_preset(struct hda_codec *codec,
 
        if (preset->setup)
                preset->setup(codec);
+
+       alc_fixup_autocfg_pin_nums(codec);
 }
 
 /* Enable GPIO mask and set output */
@@ -990,25 +1026,136 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
        alc_fix_pll(codec);
 }
 
-static void alc_automute_pin(struct hda_codec *codec)
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+static void alc_free_jack_priv(struct snd_jack *jack)
+{
+       struct alc_jack *jacks = jack->private_data;
+       jacks->nid = 0;
+       jacks->jack = NULL;
+}
+
+static int alc_add_jack(struct hda_codec *codec,
+               hda_nid_t nid, int type)
+{
+       struct alc_spec *spec;
+       struct alc_jack *jack;
+       const char *name;
+       int err;
+
+       spec = codec->spec;
+       snd_array_init(&spec->jacks, sizeof(*jack), 32);
+       jack = snd_array_new(&spec->jacks);
+       if (!jack)
+               return -ENOMEM;
+
+       jack->nid = nid;
+       jack->type = type;
+       name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
+
+       err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
+       if (err < 0)
+               return err;
+       jack->jack->private_data = jack;
+       jack->jack->private_free = alc_free_jack_priv;
+       return 0;
+}
+
+static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
 {
        struct alc_spec *spec = codec->spec;
-       unsigned int nid = spec->autocfg.hp_pins[0];
+       struct alc_jack *jacks = spec->jacks.list;
+
+       if (jacks) {
+               int i;
+               for (i = 0; i < spec->jacks.used; i++) {
+                       if (jacks->nid == nid) {
+                               unsigned int present;
+                               present = snd_hda_jack_detect(codec, nid);
+
+                               present = (present) ? jacks->type : 0;
+
+                               snd_jack_report(jacks->jack, present);
+                       }
+                       jacks++;
+               }
+       }
+}
+
+static int alc_init_jacks(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       int err;
+       unsigned int hp_nid = spec->autocfg.hp_pins[0];
+       unsigned int mic_nid = spec->ext_mic.pin;
+
+       if (hp_nid) {
+               err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE);
+               if (err < 0)
+                       return err;
+               alc_report_jack(codec, hp_nid);
+       }
+
+       if (mic_nid) {
+               err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE);
+               if (err < 0)
+                       return err;
+               alc_report_jack(codec, mic_nid);
+       }
+
+       return 0;
+}
+#else
+static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
+{
+}
+
+static inline int alc_init_jacks(struct hda_codec *codec)
+{
+       return 0;
+}
+#endif
+
+static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
+{
+       struct alc_spec *spec = codec->spec;
+       unsigned int mute;
+       hda_nid_t nid;
        int i;
 
-       if (!nid)
-               return;
-       spec->jack_present = snd_hda_jack_detect(codec, nid);
+       spec->jack_present = 0;
+       for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+               nid = spec->autocfg.hp_pins[i];
+               if (!nid)
+                       break;
+               if (snd_hda_jack_detect(codec, nid)) {
+                       spec->jack_present = 1;
+                       break;
+               }
+               alc_report_jack(codec, spec->autocfg.hp_pins[i]);
+       }
+
+       mute = spec->jack_present ? HDA_AMP_MUTE : 0;
+       /* Toggle internal speakers muting */
        for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
                nid = spec->autocfg.speaker_pins[i];
                if (!nid)
                        break;
-               snd_hda_codec_write(codec, nid, 0,
+               if (pinctl) {
+                       snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_PIN_WIDGET_CONTROL,
                                    spec->jack_present ? 0 : PIN_OUT);
+               } else {
+                       snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+                                        HDA_AMP_MUTE, mute);
+               }
        }
 }
 
+static void alc_automute_pin(struct hda_codec *codec)
+{
+       alc_automute_speaker(codec, 1);
+}
+
 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
                                hda_nid_t nid)
 {
@@ -1090,6 +1237,7 @@ static void alc_mic_automute(struct hda_codec *codec)
                                          AC_VERB_SET_CONNECT_SEL,
                                          alive->mux_idx);
        }
+       alc_report_jack(codec, spec->ext_mic.pin);
 
        /* FIXME: analog mixer */
 }
@@ -1236,24 +1384,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 static void alc_init_auto_hp(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
 
-       if (!spec->autocfg.hp_pins[0])
-               return;
+       if (!cfg->hp_pins[0]) {
+               if (cfg->line_out_type != AUTO_PIN_HP_OUT)
+                       return;
+       }
 
-       if (!spec->autocfg.speaker_pins[0]) {
-               if (spec->autocfg.line_out_pins[0] &&
-                   spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
-                       spec->autocfg.speaker_pins[0] =
-                               spec->autocfg.line_out_pins[0];
-               else
+       if (!cfg->speaker_pins[0]) {
+               if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
                        return;
+               memcpy(cfg->speaker_pins, cfg->line_out_pins,
+                      sizeof(cfg->speaker_pins));
+               cfg->speaker_outs = cfg->line_outs;
        }
 
-       snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
-                   spec->autocfg.hp_pins[0]);
-       snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0,
+       if (!cfg->hp_pins[0]) {
+               memcpy(cfg->hp_pins, cfg->line_out_pins,
+                      sizeof(cfg->hp_pins));
+               cfg->hp_outs = cfg->line_outs;
+       }
+
+       for (i = 0; i < cfg->hp_outs; i++) {
+               snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
+                           cfg->hp_pins[i]);
+               snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
                                  AC_VERB_SET_UNSOLICITED_ENABLE,
                                  AC_USRSP_EN | ALC880_HP_EVENT);
+       }
        spec->unsol_event = alc_sku_unsol_event;
 }
 
@@ -1265,30 +1424,28 @@ static void alc_init_auto_mic(struct hda_codec *codec)
        int i;
 
        /* there must be only two mic inputs exclusively */
-       for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++)
-               if (cfg->input_pins[i])
+       for (i = 0; i < cfg->num_inputs; i++)
+               if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
                        return;
 
        fixed = ext = 0;
-       for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) {
-               hda_nid_t nid = cfg->input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                unsigned int defcfg;
-               if (!nid)
-                       return;
                defcfg = snd_hda_codec_get_pincfg(codec, nid);
-               switch (get_defcfg_connect(defcfg)) {
-               case AC_JACK_PORT_FIXED:
+               switch (snd_hda_get_input_pin_attr(defcfg)) {
+               case INPUT_PIN_ATTR_INT:
                        if (fixed)
                                return; /* already occupied */
                        fixed = nid;
                        break;
-               case AC_JACK_PORT_COMPLEX:
+               case INPUT_PIN_ATTR_UNUSED:
+                       return; /* invalid entry */
+               default:
                        if (ext)
                                return; /* already occupied */
                        ext = nid;
                        break;
-               default:
-                       return; /* invalid entry */
                }
        }
        if (!ext || !fixed)
@@ -1308,6 +1465,11 @@ static void alc_init_auto_mic(struct hda_codec *codec)
        spec->unsol_event = alc_sku_unsol_event;
 }
 
+/* Could be any non-zero and even value. When used as fixup, tells
+ * the driver to ignore any present sku defines.
+ */
+#define ALC_FIXUP_SKU_IGNORE (2)
+
 static int alc_auto_parse_customize_define(struct hda_codec *codec)
 {
        unsigned int ass, tmp, i;
@@ -1316,6 +1478,13 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec)
 
        spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
 
+       if (spec->cdefine.fixup) {
+               ass = spec->cdefine.sku_cfg;
+               if (ass == ALC_FIXUP_SKU_IGNORE)
+                       return -1;
+               goto do_sku;
+       }
+
        ass = codec->subsystem_id & 0xffff;
        if (ass != codec->bus->pci->subsystem_device && (ass & 1))
                goto do_sku;
@@ -1383,6 +1552,13 @@ static int alc_subsystem_id(struct hda_codec *codec,
        unsigned nid;
        struct alc_spec *spec = codec->spec;
 
+       if (spec->cdefine.fixup) {
+               ass = spec->cdefine.sku_cfg;
+               if (ass == ALC_FIXUP_SKU_IGNORE)
+                       return 0;
+               goto do_sku;
+       }
+
        ass = codec->subsystem_id & 0xffff;
        if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
                goto do_sku;
@@ -1502,6 +1678,7 @@ struct alc_pincfg {
 };
 
 struct alc_fixup {
+       unsigned int sku;
        const struct alc_pincfg *pins;
        const struct hda_verb *verbs;
 };
@@ -1512,12 +1689,22 @@ static void alc_pick_fixup(struct hda_codec *codec,
                           int pre_init)
 {
        const struct alc_pincfg *cfg;
+       struct alc_spec *spec;
 
        quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
        if (!quirk)
                return;
        fix += quirk->value;
        cfg = fix->pins;
+       if (pre_init && fix->sku) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+               snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n",
+                           codec->chip_name, quirk->name);
+#endif
+               spec = codec->spec;
+               spec->cdefine.sku_cfg = fix->sku;
+               spec->cdefine.fixup = 1;
+       }
        if (pre_init && cfg) {
 #ifdef CONFIG_SND_DEBUG_VERBOSE
                snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
@@ -1546,6 +1733,15 @@ static int alc_read_coef_idx(struct hda_codec *codec,
        return val;
 }
 
+static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
+                                                       unsigned int coef_val)
+{
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
+                           coef_idx);
+       snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
+                           coef_val);
+}
+
 /* set right pin controls for digital I/O */
 static void alc_auto_init_digital(struct hda_codec *codec)
 {
@@ -1723,31 +1919,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
 
 static void alc_automute_amp(struct hda_codec *codec)
 {
-       struct alc_spec *spec = codec->spec;
-       unsigned int mute;
-       hda_nid_t nid;
-       int i;
-
-       spec->jack_present = 0;
-       for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-               nid = spec->autocfg.hp_pins[i];
-               if (!nid)
-                       break;
-               if (snd_hda_jack_detect(codec, nid)) {
-                       spec->jack_present = 1;
-                       break;
-               }
-       }
-
-       mute = spec->jack_present ? HDA_AMP_MUTE : 0;
-       /* Toggle internal speakers muting */
-       for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-               nid = spec->autocfg.speaker_pins[i];
-               if (!nid)
-                       break;
-               snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-                                        HDA_AMP_MUTE, mute);
-       }
+       alc_automute_speaker(codec, 0);
 }
 
 static void alc_automute_amp_unsol_event(struct hda_codec *codec,
@@ -3602,10 +3774,7 @@ static int alc_init(struct hda_codec *codec)
        if (spec->init_hook)
                spec->init_hook(codec);
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       if (codec->patch_ops.check_power_status)
-               codec->patch_ops.check_power_status(codec, 0x01);
-#endif
+       hda_call_check_power_status(codec, 0x01);
        return 0;
 }
 
@@ -4001,10 +4170,7 @@ static int alc_resume(struct hda_codec *codec)
        codec->patch_ops.init(codec);
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-       if (codec->patch_ops.check_power_status)
-               codec->patch_ops.check_power_status(codec, 0x01);
-#endif
+       hda_call_check_power_status(codec, 0x01);
        return 0;
 }
 #endif
@@ -4729,7 +4895,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
 
 /* add dynamic controls */
 static int add_control(struct alc_spec *spec, int type, const char *name,
-                      unsigned long val)
+                      int cidx, unsigned long val)
 {
        struct snd_kcontrol_new *knew;
 
@@ -4741,6 +4907,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
        knew->name = kstrdup(name, GFP_KERNEL);
        if (!knew->name)
                return -ENOMEM;
+       knew->index = cidx;
        if (get_amp_nid_(val))
                knew->subdevice = HDA_SUBDEV_AMP_FLAG;
        knew->private_value = val;
@@ -4749,17 +4916,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
 
 static int add_control_with_pfx(struct alc_spec *spec, int type,
                                const char *pfx, const char *dir,
-                               const char *sfx, unsigned long val)
+                               const char *sfx, int cidx, unsigned long val)
 {
        char name[32];
        snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
-       return add_control(spec, type, name, val);
+       return add_control(spec, type, name, cidx, val);
 }
 
-#define add_pb_vol_ctrl(spec, type, pfx, val) \
-       add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val)
-#define add_pb_sw_ctrl(spec, type, pfx, val) \
-       add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val)
+#define add_pb_vol_ctrl(spec, type, pfx, val)                  \
+       add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
+#define add_pb_sw_ctrl(spec, type, pfx, val)                   \
+       add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
+#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)                  \
+       add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
+#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)                   \
+       add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
 
 #define alc880_is_fixed_pin(nid)       ((nid) >= 0x14 && (nid) <= 0x17)
 #define alc880_fixed_pin_idx(nid)      ((nid) - 0x14)
@@ -4912,16 +5083,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
 
 /* create input playback/capture controls for the given pin */
 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
-                           const char *ctlname,
+                           const char *ctlname, int ctlidx,
                            int idx, hda_nid_t mix_nid)
 {
        int err;
 
-       err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname,
+       err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
                          HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
-       err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname,
+       err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
                          HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
@@ -4942,20 +5113,27 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec,
 {
        struct alc_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx;
+       int i, err, idx, type, type_idx = 0;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
+       for (i = 0; i < cfg->num_inputs; i++) {
                hda_nid_t pin;
+               const char *label;
 
-               pin = cfg->input_pins[i];
+               pin = cfg->inputs[i].pin;
                if (!alc_is_input_pin(codec, pin))
                        continue;
 
+               type = cfg->inputs[i].type;
+               if (i > 0 && type == cfg->inputs[i - 1].type)
+                       type_idx++;
+               else
+                       type_idx = 0;
+               label = hda_get_autocfg_input_label(codec, cfg, i);
                if (mixer) {
                        idx = get_connection_index(codec, mixer, pin);
                        if (idx >= 0) {
                                err = new_analog_input(spec, pin,
-                                                      auto_pin_cfg_labels[i],
+                                                      label, type_idx,
                                                       idx, mixer);
                                if (err < 0)
                                        return err;
@@ -4967,12 +5145,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec,
                idx = get_connection_index(codec, cap1, pin);
                if (idx < 0 && cap2)
                        idx = get_connection_index(codec, cap2, pin);
-               if (idx >= 0) {
-                       imux->items[imux->num_items].label =
-                               auto_pin_cfg_labels[i];
-                       imux->items[imux->num_items].index = idx;
-                       imux->num_items++;
-               }
+               if (idx >= 0)
+                       snd_hda_add_imux_item(imux, label, idx, NULL);
        }
        return 0;
 }
@@ -5044,12 +5218,13 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec)
 static void alc880_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (alc_is_input_pin(codec, nid)) {
-                       alc_set_input_pin(codec, nid, i);
+                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
                        if (nid != ALC880_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
                                snd_hda_codec_write(codec, nid, 0,
@@ -5214,19 +5389,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
 static void fixup_single_adc(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t pin = 0;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
        /* search for the input pin; there must be only one */
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (spec->autocfg.input_pins[i]) {
-                       pin = spec->autocfg.input_pins[i];
-                       break;
-               }
-       }
-       if (!pin)
+       if (cfg->num_inputs != 1)
                return;
-       i = init_capsrc_for_pin(codec, pin);
+       i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
        if (i >= 0) {
                /* use only this ADC */
                if (spec->capsrc_nids)
@@ -5279,6 +5448,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
                                 int num_nids)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int n;
        hda_nid_t fallback_adc = 0, fallback_cap = 0;
 
@@ -5304,10 +5474,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
                        fallback_adc = adc;
                        fallback_cap = cap;
                }
-               for (i = 0; i < AUTO_PIN_LAST; i++) {
-                       hda_nid_t nid = spec->autocfg.input_pins[i];
-                       if (!nid)
-                               continue;
+               for (i = 0; i < cfg->num_inputs; i++) {
+                       hda_nid_t nid = cfg->inputs[i].pin;
                        for (j = 0; j < nconns; j++) {
                                if (conn[j] == nid)
                                        break;
@@ -5315,7 +5483,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
                        if (j >= nconns)
                                break;
                }
-               if (i >= AUTO_PIN_LAST) {
+               if (i >= cfg->num_inputs) {
                        int num_adcs = spec->num_adc_nids;
                        spec->private_adc_nids[num_adcs] = adc;
                        spec->private_capsrc_nids[num_adcs] = cap;
@@ -6683,12 +6851,13 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
 static void alc260_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (nid >= 0x12) {
-                       alc_set_input_pin(codec, nid, i);
+                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
                        if (nid != ALC260_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
                                snd_hda_codec_write(codec, nid, 0,
@@ -6810,14 +6979,12 @@ enum {
        PINFIX_HP_DC5750,
 };
 
-static struct alc_pincfg alc260_hp_dc5750_pinfix[] = {
-       { 0x11, 0x90130110 }, /* speaker */
-       { }
-};
-
 static const struct alc_fixup alc260_fixups[] = {
        [PINFIX_HP_DC5750] = {
-               .pins = alc260_hp_dc5750_pinfix
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x11, 0x90130110 }, /* speaker */
+                       { }
+               }
        },
 };
 
@@ -10461,32 +10628,33 @@ static struct alc_config_preset alc882_presets[] = {
 enum {
        PINFIX_ABIT_AW9D_MAX,
        PINFIX_PB_M5210,
-};
-
-static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
-       { 0x15, 0x01080104 }, /* side */
-       { 0x16, 0x01011012 }, /* rear */
-       { 0x17, 0x01016011 }, /* clfe */
-       { }
-};
-
-static const struct hda_verb pb_m5210_verbs[] = {
-       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
-       {}
+       PINFIX_ACER_ASPIRE_7736,
 };
 
 static const struct alc_fixup alc882_fixups[] = {
        [PINFIX_ABIT_AW9D_MAX] = {
-               .pins = alc882_abit_aw9d_pinfix
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x15, 0x01080104 }, /* side */
+                       { 0x16, 0x01011012 }, /* rear */
+                       { 0x17, 0x01016011 }, /* clfe */
+                       { }
+               }
        },
        [PINFIX_PB_M5210] = {
-               .verbs = pb_m5210_verbs
+               .verbs = (const struct hda_verb[]) {
+                       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+                       {}
+               }
+       },
+       [PINFIX_ACER_ASPIRE_7736] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
        },
 };
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
+       SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
        {}
 };
 
@@ -10535,16 +10703,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        hda_nid_t pin, dac;
+       int i;
 
-       pin = spec->autocfg.hp_pins[0];
-       if (pin) {
+       for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+               pin = spec->autocfg.hp_pins[i];
+               if (!pin)
+                       break;
                dac = spec->multiout.hp_nid;
                if (!dac)
                        dac = spec->multiout.dac_nids[0]; /* to front */
                alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
        }
-       pin = spec->autocfg.speaker_pins[0];
-       if (pin) {
+       for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+               pin = spec->autocfg.speaker_pins[i];
+               if (!pin)
+                       break;
                dac = spec->multiout.extra_out_nid[0];
                if (!dac)
                        dac = spec->multiout.dac_nids[0]; /* to front */
@@ -10555,13 +10728,12 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
 static void alc882_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (!nid)
-                       continue;
-               alc_set_input_pin(codec, nid, i);
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               alc_set_input_pin(codec, nid, cfg->inputs[i].type);
                if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_AMP_GAIN_MUTE,
@@ -10623,24 +10795,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
 static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int err;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i, err;
        hda_nid_t nid;
 
-       nid = spec->autocfg.input_pins[AUTO_PIN_MIC];
-       if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
-               err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                 "Mic Boost",
-                                 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
-               if (err < 0)
-                       return err;
-       }
-       nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC];
-       if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
-               err = add_control(spec, ALC_CTL_WIDGET_VOL,
-                                 "Front Mic Boost",
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (cfg->inputs[i].type > AUTO_PIN_MIC)
+                       break;
+               nid = cfg->inputs[i].pin;
+               if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
+                       char label[32];
+                       snprintf(label, sizeof(label), "%s Boost",
+                                hda_get_autocfg_input_label(codec, cfg, i));
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
-               if (err < 0)
-                       return err;
+                       if (err < 0)
+                               return err;
+               }
        }
        return 0;
 }
@@ -10726,8 +10897,6 @@ static int patch_alc882(struct hda_codec *codec)
 
        codec->spec = spec;
 
-       alc_auto_parse_customize_define(codec);
-
        switch (codec->vendor_id) {
        case 0x10ec0882:
        case 0x10ec0885:
@@ -10755,6 +10924,8 @@ static int patch_alc882(struct hda_codec *codec)
        if (board_config == ALC882_AUTO)
                alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1);
 
+       alc_auto_parse_customize_define(codec);
+
        if (board_config == ALC882_AUTO) {
                /* automatic parse from the BIOS config */
                err = alc882_parse_auto_config(codec);
@@ -10835,6 +11006,8 @@ static int patch_alc882(struct hda_codec *codec)
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC882_AUTO)
                spec->init_hook = alc882_auto_init;
+
+       alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc882_loopbacks;
@@ -11831,7 +12004,7 @@ static int alc262_check_volbit(hda_nid_t nid)
 }
 
 static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
-                                 const char *pfx, int *vbits)
+                                 const char *pfx, int *vbits, int idx)
 {
        unsigned long val;
        int vbit;
@@ -11846,11 +12019,11 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
                val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
        else
                val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
-       return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val);
+       return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
 }
 
 static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
-                                const char *pfx)
+                                const char *pfx, int idx)
 {
        unsigned long val;
 
@@ -11860,7 +12033,7 @@ static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
                val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
        else
                val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
-       return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val);
+       return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
 }
 
 /* add playback controls from the parsed DAC table */
@@ -11869,7 +12042,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
 {
        const char *pfx;
        int vbits;
-       int err;
+       int i, err;
 
        spec->multiout.num_dacs = 1;    /* only use one dac */
        spec->multiout.dac_nids = spec->private_dac_nids;
@@ -11879,39 +12052,52 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
                pfx = "Master";
        else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
                pfx = "Speaker";
+       else if (cfg->line_out_type == AUTO_PIN_HP_OUT)
+               pfx = "Headphone";
        else
                pfx = "Front";
-       err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx);
-       if (err < 0)
-               return err;
-       err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker");
-       if (err < 0)
-               return err;
-       err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone");
-       if (err < 0)
-               return err;
+       for (i = 0; i < 2; i++) {
+               err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
+               if (err < 0)
+                       return err;
+               if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+                       err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
+                                                   "Speaker", i);
+                       if (err < 0)
+                               return err;
+               }
+               if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+                       err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
+                                                   "Headphone", i);
+                       if (err < 0)
+                               return err;
+               }
+       }
 
        vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
                alc262_check_volbit(cfg->speaker_pins[0]) |
                alc262_check_volbit(cfg->hp_pins[0]);
        if (vbits == 1 || vbits == 2)
                pfx = "Master"; /* only one mixer is used */
-       else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
-               pfx = "Speaker";
-       else
-               pfx = "Front";
        vbits = 0;
-       err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits);
-       if (err < 0)
-               return err;
-       err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker",
-                                    &vbits);
-       if (err < 0)
-               return err;
-       err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone",
-                                    &vbits);
-       if (err < 0)
-               return err;
+       for (i = 0; i < 2; i++) {
+               err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
+                                            &vbits, i);
+               if (err < 0)
+                       return err;
+               if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+                       err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
+                                                    "Speaker", &vbits, i);
+                       if (err < 0)
+                               return err;
+               }
+               if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+                       err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
+                                                    "Headphone", &vbits, i);
+                       if (err < 0)
+                               return err;
+               }
+       }
        return 0;
 }
 
@@ -12199,6 +12385,35 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
        {}
 };
 
+/*
+ * Pin config fixes
+ */
+enum {
+       PINFIX_FSC_H270,
+};
+
+static const struct alc_fixup alc262_fixups[] = {
+       [PINFIX_FSC_H270] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x14, 0x99130110 }, /* speaker */
+                       { 0x15, 0x0221142f }, /* front HP */
+                       { 0x1b, 0x0121141f }, /* rear HP */
+                       { }
+               }
+       },
+       [PINFIX_PB_M5210] = {
+               .verbs = (const struct hda_verb[]) {
+                       { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+                       {}
+               }
+       },
+};
+
+static struct snd_pci_quirk alc262_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
+       {}
+};
+
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 #define alc262_loopbacks       alc880_loopbacks
@@ -12622,6 +12837,9 @@ static int patch_alc262(struct hda_codec *codec)
                board_config = ALC262_AUTO;
        }
 
+       if (board_config == ALC262_AUTO)
+               alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1);
+
        if (board_config == ALC262_AUTO) {
                /* automatic parse from the BIOS config */
                err = alc262_parse_auto_config(codec);
@@ -12690,11 +12908,16 @@ static int patch_alc262(struct hda_codec *codec)
        if (!spec->no_analog && has_cdefine_beep(codec))
                set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
 
+       if (board_config == ALC262_AUTO)
+               alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0);
+
        spec->vmaster_nid = 0x0c;
 
        codec->patch_ops = alc_patch_ops;
        if (board_config == ALC262_AUTO)
                spec->init_hook = alc262_auto_init;
+
+       alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc262_loopbacks;
@@ -13310,8 +13533,10 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
 static void alc268_auto_init_multi_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t nid = spec->autocfg.line_out_pins[0];
-       if (nid) {
+       int i;
+
+       for (i = 0; i < spec->autocfg.line_outs; i++) {
+               hda_nid_t nid = spec->autocfg.line_out_pins[i];
                int pin_type = get_pin_type(spec->autocfg.line_out_type);
                alc268_auto_set_output_and_unmute(codec, nid, pin_type);
        }
@@ -13321,13 +13546,19 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        hda_nid_t pin;
+       int i;
 
-       pin = spec->autocfg.hp_pins[0];
-       if (pin)
+       for (i = 0; i < spec->autocfg.hp_outs; i++) {
+               pin = spec->autocfg.hp_pins[i];
                alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
-       pin = spec->autocfg.speaker_pins[0];
-       if (pin)
+       }
+       for (i = 0; i < spec->autocfg.speaker_outs; i++) {
+               pin = spec->autocfg.speaker_pins[i];
                alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
+       }
+       if (spec->autocfg.mono_out_pin)
+               snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
 }
 
 static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
@@ -13766,6 +13997,8 @@ static int patch_alc268(struct hda_codec *codec)
        if (board_config == ALC268_AUTO)
                spec->init_hook = alc268_auto_init;
 
+       alc_init_jacks(codec);
+
        return 0;
 }
 
@@ -14132,6 +14365,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
                                 HDA_AMP_MUTE, bits);
        snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
                                 HDA_AMP_MUTE, bits);
+       alc_report_jack(codec, nid);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -14386,6 +14620,13 @@ static int alc275_setup_dual_adc(struct hda_codec *codec)
        return 0;
 }
 
+/* different alc269-variants */
+enum {
+       ALC269_TYPE_NORMAL,
+       ALC269_TYPE_ALC259,
+       ALC269_TYPE_ALC271X,
+};
+
 /*
  * BIOS auto configuration
  */
@@ -14403,7 +14644,11 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
        if (err < 0)
                return err;
-       err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
+       if (spec->codec_variant == ALC269_TYPE_NORMAL)
+               err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
+       else
+               err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0,
+                                                0x22, 0);
        if (err < 0)
                return err;
 
@@ -14414,7 +14659,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        if (spec->kctls.list)
                add_mixer(spec, spec->kctls.list);
 
-       if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
+       if (spec->codec_variant != ALC269_TYPE_NORMAL) {
                add_verb(spec, alc269vb_init_verbs);
                alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
        } else {
@@ -14461,19 +14706,71 @@ static void alc269_auto_init(struct hda_codec *codec)
                alc_inithook(codec);
 }
 
+#ifdef SND_HDA_NEEDS_RESUME
+static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
+{
+       int val = alc_read_coef_idx(codec, 0x04);
+       if (power_up)
+               val |= 1 << 11;
+       else
+               val &= ~(1 << 11);
+       alc_write_coef_idx(codec, 0x04, val);
+}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
+               alc269_toggle_power_output(codec, 0);
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+               alc269_toggle_power_output(codec, 0);
+               msleep(150);
+       }
+
+       alc_shutup(codec);
+       if (spec && spec->power_hook)
+               spec->power_hook(codec);
+       return 0;
+}
+#endif /* CONFIG_SND_HDA_POWER_SAVE */
+
+static int alc269_resume(struct hda_codec *codec)
+{
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+               alc269_toggle_power_output(codec, 0);
+               msleep(150);
+       }
+
+       codec->patch_ops.init(codec);
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+               alc269_toggle_power_output(codec, 1);
+               msleep(200);
+       }
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
+               alc269_toggle_power_output(codec, 1);
+
+       snd_hda_codec_resume_amp(codec);
+       snd_hda_codec_resume_cache(codec);
+       hda_call_check_power_status(codec, 0x01);
+       return 0;
+}
+#endif /* SND_HDA_NEEDS_RESUME */
+
 enum {
        ALC269_FIXUP_SONY_VAIO,
        ALC269_FIXUP_DELL_M101Z,
 };
 
-static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = {
-       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
-       {}
-};
-
 static const struct alc_fixup alc269_fixups[] = {
        [ALC269_FIXUP_SONY_VAIO] = {
-               .verbs = alc269_sony_vaio_fixup_verbs
+               .verbs = (const struct hda_verb[]) {
+                       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
+                       {}
+               }
        },
        [ALC269_FIXUP_DELL_M101Z] = {
                .verbs = (const struct hda_verb[]) {
@@ -14486,8 +14783,7 @@ static const struct alc_fixup alc269_fixups[] = {
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
-       SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
-       SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+       SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        {}
 };
@@ -14689,12 +14985,46 @@ static struct alc_config_preset alc269_presets[] = {
        },
 };
 
+static int alc269_fill_coef(struct hda_codec *codec)
+{
+       int val;
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
+               alc_write_coef_idx(codec, 0xf, 0x960b);
+               alc_write_coef_idx(codec, 0xe, 0x8817);
+       }
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
+               alc_write_coef_idx(codec, 0xf, 0x960b);
+               alc_write_coef_idx(codec, 0xe, 0x8814);
+       }
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+               val = alc_read_coef_idx(codec, 0x04);
+               /* Power up output pin */
+               alc_write_coef_idx(codec, 0x04, val | (1<<11));
+       }
+
+       if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+               val = alc_read_coef_idx(codec, 0xd);
+               if ((val & 0x0c00) >> 10 != 0x1) {
+                       /* Capless ramp up clock control */
+                       alc_write_coef_idx(codec, 0xd, val | 1<<10);
+               }
+               val = alc_read_coef_idx(codec, 0x17);
+               if ((val & 0x01c0) >> 6 != 0x4) {
+                       /* Class D power on reset */
+                       alc_write_coef_idx(codec, 0x17, val | 1<<7);
+               }
+       }
+       return 0;
+}
+
 static int patch_alc269(struct hda_codec *codec)
 {
        struct alc_spec *spec;
        int board_config;
        int err;
-       int is_alc269vb = 0;
 
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (spec == NULL)
@@ -14706,14 +15036,18 @@ static int patch_alc269(struct hda_codec *codec)
 
        if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
                if (codec->bus->pci->subsystem_vendor == 0x1025 &&
-                   spec->cdefine.platform_type == 1)
+                   spec->cdefine.platform_type == 1) {
                        alc_codec_rename(codec, "ALC271X");
-               else
+                       spec->codec_variant = ALC269_TYPE_ALC271X;
+               } else {
                        alc_codec_rename(codec, "ALC259");
-               is_alc269vb = 1;
+                       spec->codec_variant = ALC269_TYPE_ALC259;
+               }
        } else
                alc_fix_pll_init(codec, 0x20, 0x04, 15);
 
+       alc269_fill_coef(codec);
+
        board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
                                                  alc269_models,
                                                  alc269_cfg_tbl);
@@ -14770,7 +15104,7 @@ static int patch_alc269(struct hda_codec *codec)
        spec->stream_digital_capture = &alc269_pcm_digital_capture;
 
        if (!spec->adc_nids) { /* wasn't filled automatically? use default */
-               if (!is_alc269vb) {
+               if (spec->codec_variant != ALC269_TYPE_NORMAL) {
                        spec->adc_nids = alc269_adc_nids;
                        spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
                        spec->capsrc_nids = alc269_capsrc_nids;
@@ -14792,8 +15126,16 @@ static int patch_alc269(struct hda_codec *codec)
        spec->vmaster_nid = 0x02;
 
        codec->patch_ops = alc_patch_ops;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+       codec->patch_ops.suspend = alc269_suspend;
+#endif
+#ifdef SND_HDA_NEEDS_RESUME
+       codec->patch_ops.resume = alc269_resume;
+#endif
        if (board_config == ALC269_AUTO)
                spec->init_hook = alc269_auto_init;
+
+       alc_init_jacks(codec);
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc269_loopbacks;
@@ -15606,12 +15948,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
 static void alc861_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (nid >= 0x0c && nid <= 0x11)
-                       alc_set_input_pin(codec, nid, i);
+                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
        }
 }
 
@@ -15840,15 +16183,13 @@ enum {
        PINFIX_FSC_AMILO_PI1505,
 };
 
-static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = {
-       { 0x0b, 0x0221101f }, /* HP */
-       { 0x0f, 0x90170310 }, /* speaker */
-       { }
-};
-
 static const struct alc_fixup alc861_fixups[] = {
        [PINFIX_FSC_AMILO_PI1505] = {
-               .pins = alc861_fsc_amilo_pi1505_pinfix
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x0b, 0x0221101f }, /* HP */
+                       { 0x0f, 0x90170310 }, /* speaker */
+                       { }
+               }
        },
 };
 
@@ -16600,12 +16941,13 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
 static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (alc_is_input_pin(codec, nid)) {
-                       alc_set_input_pin(codec, nid, i);
+                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
                        if (nid != ALC861VD_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
                                snd_hda_codec_write(codec, nid, 0,
@@ -16815,16 +17157,14 @@ enum {
 };
 
 /* reset GPIO1 */
-static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = {
-       {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
-       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-       {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-       { }
-};
-
 static const struct alc_fixup alc861vd_fixups[] = {
        [ALC660VD_FIX_ASUS_GPIO1] = {
-               .verbs = alc660vd_fix_asus_gpio1_verbs,
+               .verbs = (const struct hda_verb[]) {
+                       {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
+                       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+                       {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+                       { }
+               }
        },
 };
 
@@ -18838,12 +19178,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
 static void alc662_auto_init_analog_input(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (alc_is_input_pin(codec, nid)) {
-                       alc_set_input_pin(codec, nid, i);
+                       alc_set_input_pin(codec, nid, cfg->inputs[i].type);
                        if (nid != ALC662_PIN_CD_NID &&
                            (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
                                snd_hda_codec_write(codec, nid, 0,
@@ -18935,10 +19276,40 @@ static void alc662_auto_init(struct hda_codec *codec)
                alc_inithook(codec);
 }
 
+enum {
+       ALC662_FIXUP_ASPIRE,
+       ALC662_FIXUP_IDEAPAD,
+};
+
+static const struct alc_fixup alc662_fixups[] = {
+       [ALC662_FIXUP_ASPIRE] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x15, 0x99130112 }, /* subwoofer */
+                       { }
+               }
+       },
+       [ALC662_FIXUP_IDEAPAD] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130112 }, /* subwoofer */
+                       { }
+               }
+       },
+};
+
+static struct snd_pci_quirk alc662_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
+       SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
+       SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
+       {}
+};
+
+
+
 static int patch_alc662(struct hda_codec *codec)
 {
        struct alc_spec *spec;
        int err, board_config;
+       int coef;
 
        spec = kzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
@@ -18950,12 +19321,15 @@ static int patch_alc662(struct hda_codec *codec)
 
        alc_fix_pll_init(codec, 0x20, 0x04, 15);
 
-       if (alc_read_coef_idx(codec, 0) == 0x8020)
+       coef = alc_read_coef_idx(codec, 0);
+       if (coef == 0x8020 || coef == 0x8011)
                alc_codec_rename(codec, "ALC661");
-       else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) &&
-                codec->bus->pci->subsystem_vendor == 0x1025 &&
-                spec->cdefine.platform_type == 1)
+       else if (coef & (1 << 14) &&
+               codec->bus->pci->subsystem_vendor == 0x1025 &&
+               spec->cdefine.platform_type == 1)
                alc_codec_rename(codec, "ALC272X");
+       else if (coef == 0x4011)
+               alc_codec_rename(codec, "ALC656");
 
        board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
                                                  alc662_models,
@@ -18967,6 +19341,7 @@ static int patch_alc662(struct hda_codec *codec)
        }
 
        if (board_config == ALC662_AUTO) {
+               alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1);
                /* automatic parse from the BIOS config */
                err = alc662_parse_auto_config(codec);
                if (err < 0) {
@@ -19025,8 +19400,13 @@ static int patch_alc662(struct hda_codec *codec)
        spec->vmaster_nid = 0x02;
 
        codec->patch_ops = alc_patch_ops;
-       if (board_config == ALC662_AUTO)
+       if (board_config == ALC662_AUTO) {
                spec->init_hook = alc662_auto_init;
+               alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0);
+       }
+
+       alc_init_jacks(codec);
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        if (!spec->loopback.amplist)
                spec->loopback.amplist = alc662_loopbacks;
@@ -19070,6 +19450,39 @@ static hda_nid_t alc680_adc_nids[3] = {
 /*
  * Analog capture ADC cgange
  */
+static void alc680_rec_autoswitch(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       int pin_found = 0;
+       int type_found = AUTO_PIN_LAST;
+       hda_nid_t nid;
+       int i;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               nid = cfg->inputs[i].pin;
+               if (!(snd_hda_query_pin_caps(codec, nid) &
+                     AC_PINCAP_PRES_DETECT))
+                       continue;
+               if (snd_hda_jack_detect(codec, nid)) {
+                       if (cfg->inputs[i].type < type_found) {
+                               type_found = cfg->inputs[i].type;
+                               pin_found = nid;
+                       }
+               }
+       }
+
+       nid = 0x07;
+       if (pin_found)
+               snd_hda_get_connections(codec, pin_found, &nid, 1);
+
+       if (nid != spec->cur_adc)
+               __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
+       spec->cur_adc = nid;
+       snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
+                                  spec->cur_adc_format);
+}
+
 static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
                                      struct hda_codec *codec,
                                      unsigned int stream_tag,
@@ -19077,24 +19490,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
                                      struct snd_pcm_substream *substream)
 {
        struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       unsigned int pre_mic, pre_line;
-
-       pre_mic  = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]);
-       pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]);
 
+       spec->cur_adc = 0x07;
        spec->cur_adc_stream_tag = stream_tag;
        spec->cur_adc_format = format;
 
-       if (pre_mic || pre_line) {
-               if (pre_mic)
-                       snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0,
-                                                                       format);
-               else
-                       snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0,
-                                                                       format);
-       } else
-               snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format);
+       alc680_rec_autoswitch(codec);
        return 0;
 }
 
@@ -19180,6 +19581,7 @@ static struct hda_verb alc680_init_verbs[] = {
 
        {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT   | AC_USRSP_EN},
        {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT  | AC_USRSP_EN},
+       {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT  | AC_USRSP_EN},
 
        { }
 };
@@ -19192,25 +19594,11 @@ static void alc680_base_setup(struct hda_codec *codec)
        spec->autocfg.hp_pins[0] = 0x16;
        spec->autocfg.speaker_pins[0] = 0x14;
        spec->autocfg.speaker_pins[1] = 0x15;
-       spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18;
-       spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19;
-}
-
-static void alc680_rec_autoswitch(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       struct auto_pin_cfg *cfg = &spec->autocfg;
-       unsigned int present;
-       hda_nid_t new_adc;
-
-       present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]);
-
-       new_adc = present ? 0x8 : 0x7;
-       __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1);
-       snd_hda_codec_setup_stream(codec, new_adc,
-                                  spec->cur_adc_stream_tag, 0,
-                                  spec->cur_adc_format);
-
+       spec->autocfg.num_inputs = 2;
+       spec->autocfg.inputs[0].pin = 0x18;
+       spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
+       spec->autocfg.inputs[1].pin = 0x19;
+       spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
 }
 
 static void alc680_unsol_event(struct hda_codec *codec,
index c16c5ba..82ebeb9 100644 (file)
@@ -32,6 +32,7 @@
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/jack.h>
+#include <sound/tlv.h>
 #include "hda_codec.h"
 #include "hda_local.h"
 #include "hda_beep.h"
@@ -263,6 +264,7 @@ struct sigmatel_spec {
 
        struct sigmatel_mic_route ext_mic;
        struct sigmatel_mic_route int_mic;
+       struct sigmatel_mic_route dock_mic;
 
        const char **spdif_labels;
 
@@ -382,6 +384,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = {
        0x03, 0x0c, 0x20, 0x40,
 };
 
+#define STAC92HD83XXX_NUM_DMICS         2
+static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
+       0x11, 0x20, 0
+};
+
 #define STAC92HD83XXX_NUM_CAPS 2
 static unsigned long stac92hd83xxx_capvols[] = {
        HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
@@ -986,7 +993,7 @@ static struct hda_verb stac9205_core_init[] = {
        }
 
 static struct snd_kcontrol_new stac9200_mixer[] = {
-       HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
        HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
@@ -1014,7 +1021,7 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
 };
 
 static struct snd_kcontrol_new stac925x_mixer[] = {
-       HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT),
+       HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
        HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
        { } /* end */
 };
@@ -1105,9 +1112,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                struct hda_input_mux *smux = &spec->private_smux;
                /* check for mute support on SPDIF out */
                if (wcaps & AC_WCAP_OUT_AMP) {
-                       smux->items[smux->num_items].label = "Off";
-                       smux->items[smux->num_items].index = 0;
-                       smux->num_items++;
+                       snd_hda_add_imux_item(smux, "Off", 0, NULL);
                        spec->spdif_mute = 1;
                }
                stac_smux_mixer.count = spec->num_smuxes;
@@ -1140,6 +1145,8 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                                        HDA_OUTPUT, vmaster_tlv);
                /* correct volume offset */
                vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
+               /* minimum value is actually mute */
+               vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
                                          vmaster_tlv, slave_vols);
                if (err < 0)
@@ -1180,14 +1187,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
                if (err < 0)
                        return err;
        }
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               nid = cfg->input_pins[i];
-               if (nid) {
-                       err = stac92xx_add_jack(codec, nid,
-                                               SND_JACK_MICROPHONE);
-                       if (err < 0)
-                               return err;
-               }
+       for (i = 0; i < cfg->num_inputs; i++) {
+               nid = cfg->inputs[i].pin;
+               err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE);
+               if (err < 0)
+                       return err;
        }
 
        return 0;       
@@ -2779,7 +2783,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        struct sigmatel_spec *spec = codec->spec;
        char name[22];
 
-       if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) {
+       if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
                if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
                        && nid == spec->line_switch)
                        control = STAC_CTL_WIDGET_IO_SWITCH;
@@ -2791,7 +2795,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        }
 
        if (control) {
-               strcpy(name, auto_pin_cfg_labels[idx]);
+               strcpy(name, hda_get_input_pin_label(codec, nid, 1));
                return stac92xx_add_control(codec->spec, control,
                                        strcat(name, " Jack Mode"), nid);
        }
@@ -2823,41 +2827,49 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
        struct auto_pin_cfg *cfg = &spec->autocfg;
        hda_nid_t nid;
        unsigned int pincap;
+       int i;
 
        if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
                return 0;
-       nid = cfg->input_pins[AUTO_PIN_LINE];
-       pincap = snd_hda_query_pin_caps(codec, nid);
-       if (pincap & AC_PINCAP_OUT)
-               return nid;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) {
+                       nid = cfg->inputs[i].pin;
+                       pincap = snd_hda_query_pin_caps(codec, nid);
+                       if (pincap & AC_PINCAP_OUT)
+                               return nid;
+               }
+       }
        return 0;
 }
 
+static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid);
+
 /* check whether the mic-input can be used as line-out */
-static hda_nid_t check_mic_out_switch(struct hda_codec *codec)
+static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac)
 {
        struct sigmatel_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int def_conf, pincap;
-       unsigned int mic_pin;
+       int i;
 
+       *dac = 0;
        if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
                return 0;
-       mic_pin = AUTO_PIN_MIC;
-       for (;;) {
-               hda_nid_t nid = cfg->input_pins[mic_pin];
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               if (cfg->inputs[i].type != AUTO_PIN_MIC)
+                       continue;
                def_conf = snd_hda_codec_get_pincfg(codec, nid);
                /* some laptops have an internal analog microphone
                 * which can't be used as a output */
-               if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) {
+               if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
                        pincap = snd_hda_query_pin_caps(codec, nid);
-                       if (pincap & AC_PINCAP_OUT)
-                               return nid;
+                       if (pincap & AC_PINCAP_OUT) {
+                               *dac = get_unassigned_dac(codec, nid);
+                               if (*dac)
+                                       return nid;
+                       }
                }
-               if (mic_pin == AUTO_PIN_MIC)
-                       mic_pin = AUTO_PIN_FRONT_MIC;
-               else
-                       break;
        }
        return 0;
 }
@@ -3004,17 +3016,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
                }
        }
        /* add mic as output */
-       nid = check_mic_out_switch(codec);
-       if (nid) {
-               dac = get_unassigned_dac(codec, nid);
-               if (dac) {
-                       snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
-                                   nid, cfg->line_outs);
-                       cfg->line_out_pins[cfg->line_outs] = nid;
-                       cfg->line_outs++;
-                       spec->mic_switch = nid;
-                       add_spec_dacs(spec, dac);
-               }
+       nid = check_mic_out_switch(codec, &dac);
+       if (nid && dac) {
+               snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
+                           nid, cfg->line_outs);
+               cfg->line_out_pins[cfg->line_outs] = nid;
+               cfg->line_outs++;
+               spec->mic_switch = nid;
+               add_spec_dacs(spec, dac);
        }
 
        snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
@@ -3204,13 +3213,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
                        return err;
        }
 
-       for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) {
-               nid = cfg->input_pins[idx];
-               if (nid) {
-                       err = stac92xx_add_jack_mode_control(codec, nid, idx);
-                       if (err < 0)
-                               return err;
-               }
+       for (idx = 0; idx < cfg->num_inputs; idx++) {
+               if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
+                       break;
+               nid = cfg->inputs[idx].pin;
+               err = stac92xx_add_jack_mode_control(codec, nid, idx);
+               if (err < 0)
+                       return err;
        }
 
        return 0;
@@ -3256,12 +3265,9 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
        if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
                return -EINVAL;
 
-       for (i = 0; i < num_cons; i++) {
-               mono_mux->items[mono_mux->num_items].label =
-                                       stac92xx_mono_labels[i];
-               mono_mux->items[mono_mux->num_items].index = i;
-               mono_mux->num_items++;
-       }
+       for (i = 0; i < num_cons; i++)
+               snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i,
+                                     NULL);
 
        return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX,
                                "Mono Mux", spec->mono_nid);
@@ -3386,11 +3392,8 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec)
        if (!labels)
                labels = stac92xx_spdif_labels;
 
-       for (i = 0; i < num_cons; i++) {
-               spdif_mux->items[spdif_mux->num_items].label = labels[i];
-               spdif_mux->items[spdif_mux->num_items].index = i;
-               spdif_mux->num_items++;
-       }
+       for (i = 0; i < num_cons; i++)
+               snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL);
 
        return 0;
 }
@@ -3417,7 +3420,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 /* create a volume assigned to the given pin (only if supported) */
 /* return 1 if the volume control is created */
 static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
-                                  const char *label, int direction)
+                                  const char *label, int idx, int direction)
 {
        unsigned int caps, nums;
        char name[32];
@@ -3434,8 +3437,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
        if (!nums)
                return 0;
        snprintf(name, sizeof(name), "%s Capture Volume", label);
-       err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name,
-                                   HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
+       err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name,
+                                      HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
        if (err < 0)
                return err;
        return 1;
@@ -3448,27 +3451,14 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
        struct sigmatel_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux;
        struct hda_input_mux *dimux = &spec->private_dimux;
-       int err, i, active_mics;
+       int err, i;
        unsigned int def_conf;
 
-       dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];
-       dimux->items[dimux->num_items].index = 0;
-       dimux->num_items++;
-
-       active_mics = 0;
-       for (i = 0; i < spec->num_dmics; i++) {
-               /* check the validity: sometimes it's a dead vendor-spec node */
-               if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i]))
-                   != AC_WID_PIN)
-                       continue;
-               def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
-               if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
-                       active_mics++;
-       }
+       snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL);
 
        for (i = 0; i < spec->num_dmics; i++) {
                hda_nid_t nid;
-               int index;
+               int index, type_idx;
                const char *label;
 
                nid = spec->dmic_nids[i];
@@ -3482,28 +3472,23 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                if (index < 0)
                        continue;
 
-               if (active_mics == 1)
-                       label = "Digital Mic";
-               else
-                       label = stac92xx_dmic_labels[dimux->num_items];
+               label = hda_get_input_pin_label(codec, nid, 1);
+               snd_hda_add_imux_item(dimux, label, index, &type_idx);
 
-               err = create_elem_capture_vol(codec, nid, label, HDA_INPUT);
+               err = create_elem_capture_vol(codec, nid, label, type_idx,
+                                             HDA_INPUT);
                if (err < 0)
                        return err;
                if (!err) {
                        err = create_elem_capture_vol(codec, nid, label,
-                                                     HDA_OUTPUT);
+                                                     type_idx, HDA_OUTPUT);
                        if (err < 0)
                                return err;
                }
 
-               dimux->items[dimux->num_items].label = label;
-               dimux->items[dimux->num_items].index = index;
-               dimux->num_items++;
                if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) {
-                       imux->items[imux->num_items].label = label;
-                       imux->items[imux->num_items].index = index;
-                       imux->num_items++;
+                       snd_hda_add_imux_item(imux, label, index, NULL);
+                       spec->num_analog_muxes++;
                }
        }
 
@@ -3511,20 +3496,27 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
 }
 
 static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
-                        hda_nid_t *fixed, hda_nid_t *ext)
+                        hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
 {
        unsigned int cfg;
 
        if (!nid)
                return 0;
        cfg = snd_hda_codec_get_pincfg(codec, nid);
-       switch (get_defcfg_connect(cfg)) {
-       case AC_JACK_PORT_FIXED:
+       switch (snd_hda_get_input_pin_attr(cfg)) {
+       case INPUT_PIN_ATTR_INT:
                if (*fixed)
                        return 1; /* already occupied */
                *fixed = nid;
                break;
-       case AC_JACK_PORT_COMPLEX:
+       case INPUT_PIN_ATTR_UNUSED:
+               break;
+       case INPUT_PIN_ATTR_DOCK:
+               if (*dock)
+                       return 1; /* already occupied */
+               *dock = nid;
+               break;
+       default:
                if (*ext)
                        return 1; /* already occupied */
                *ext = nid;
@@ -3542,10 +3534,13 @@ static int set_mic_route(struct hda_codec *codec,
        int i;
 
        mic->pin = pin;
-       for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
-               if (pin == cfg->input_pins[i])
+       if (pin == 0)
+               return 0;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (pin == cfg->inputs[i].pin)
                        break;
-       if (i <= AUTO_PIN_FRONT_MIC) {
+       }
+       if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) {
                /* analog pin */
                i = get_connection_index(codec, spec->mux_nids[0], pin);
                if (i < 0)
@@ -3576,26 +3571,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       hda_nid_t fixed, ext;
+       hda_nid_t fixed, ext, dock;
        int i;
 
-       for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) {
-               if (cfg->input_pins[i])
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
                        return 0; /* must be exclusively mics */
        }
-       fixed = ext = 0;
-       for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++)
-               if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext))
+       fixed = ext = dock = 0;
+       for (i = 0; i < cfg->num_inputs; i++)
+               if (check_mic_pin(codec, cfg->inputs[i].pin,
+                   &fixed, &ext, &dock))
                        return 0;
        for (i = 0; i < spec->num_dmics; i++)
-               if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext))
+               if (check_mic_pin(codec, spec->dmic_nids[i],
+                   &fixed, &ext, &dock))
                        return 0;
-       if (!fixed || !ext)
-               return 0;
+       if (!fixed && !ext && !dock)
+               return 0; /* no input to switch */
        if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
                return 0; /* no unsol support */
        if (set_mic_route(codec, &spec->ext_mic, ext) ||
-           set_mic_route(codec, &spec->int_mic, fixed))
+           set_mic_route(codec, &spec->int_mic, fixed) ||
+           set_mic_route(codec, &spec->dock_mic, dock))
                return 0; /* something is wrong */
        return 1;
 }
@@ -3606,13 +3604,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
        struct sigmatel_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux;
        int i, j;
+       const char *label;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = cfg->input_pins[i];
-               int index, err;
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               int index, err, type_idx;
 
-               if (!nid)
-                       continue;
                index = -1;
                for (j = 0; j < spec->num_muxes; j++) {
                        index = get_connection_index(codec, spec->mux_nids[j],
@@ -3623,15 +3620,14 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
                if (index < 0)
                        continue;
 
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               snd_hda_add_imux_item(imux, label, index, &type_idx);
+
                err = create_elem_capture_vol(codec, nid,
-                                             auto_pin_cfg_labels[i],
+                                             label, type_idx,
                                              HDA_INPUT);
                if (err < 0)
                        return err;
-
-               imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-               imux->items[imux->num_items].index = index;
-               imux->num_items++;
        }
        spec->num_analog_muxes = imux->num_items;
 
@@ -4305,38 +4301,38 @@ static int stac92xx_init(struct hda_codec *codec)
                                          AC_VERB_SET_CONNECT_SEL, 0);
                if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
                        stac_issue_unsol_event(codec, spec->ext_mic.pin);
-       }
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = cfg->input_pins[i];
-               if (nid) {
-                       unsigned int pinctl, conf;
-                       if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
-                               /* for mic pins, force to initialize */
-                               pinctl = stac92xx_get_default_vref(codec, nid);
+               if (enable_pin_detect(codec, spec->dock_mic.pin,
+                   STAC_MIC_EVENT))
+                       stac_issue_unsol_event(codec, spec->dock_mic.pin);
+       }
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               int type = cfg->inputs[i].type;
+               unsigned int pinctl, conf;
+               if (type == AUTO_PIN_MIC) {
+                       /* for mic pins, force to initialize */
+                       pinctl = stac92xx_get_default_vref(codec, nid);
+                       pinctl |= AC_PINCTL_IN_EN;
+                       stac92xx_auto_set_pinctl(codec, nid, pinctl);
+               } else {
+                       pinctl = snd_hda_codec_read(codec, nid, 0,
+                                       AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+                       /* if PINCTL already set then skip */
+                       /* Also, if both INPUT and OUTPUT are set,
+                        * it must be a BIOS bug; need to override, too
+                        */
+                       if (!(pinctl & AC_PINCTL_IN_EN) ||
+                           (pinctl & AC_PINCTL_OUT_EN)) {
+                               pinctl &= ~AC_PINCTL_OUT_EN;
                                pinctl |= AC_PINCTL_IN_EN;
                                stac92xx_auto_set_pinctl(codec, nid, pinctl);
-                       } else {
-                               pinctl = snd_hda_codec_read(codec, nid, 0,
-                                       AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-                               /* if PINCTL already set then skip */
-                               /* Also, if both INPUT and OUTPUT are set,
-                                * it must be a BIOS bug; need to override, too
-                                */
-                               if (!(pinctl & AC_PINCTL_IN_EN) ||
-                                   (pinctl & AC_PINCTL_OUT_EN)) {
-                                       pinctl &= ~AC_PINCTL_OUT_EN;
-                                       pinctl |= AC_PINCTL_IN_EN;
-                                       stac92xx_auto_set_pinctl(codec, nid,
-                                                                pinctl);
-                               }
-                       }
-                       conf = snd_hda_codec_get_pincfg(codec, nid);
-                       if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
-                               if (enable_pin_detect(codec, nid,
-                                                     STAC_INSERT_EVENT))
-                                       stac_issue_unsol_event(codec, nid);
                        }
                }
+               conf = snd_hda_codec_get_pincfg(codec, nid);
+               if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
+                       if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT))
+                               stac_issue_unsol_event(codec, nid);
+               }
        }
        for (i = 0; i < spec->num_dmics; i++)
                stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
@@ -4383,11 +4379,9 @@ static int stac92xx_init(struct hda_codec *codec)
                        stac_issue_unsol_event(codec, nid);
        }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
        /* sync mute LED */
-       if (spec->gpio_led && codec->patch_ops.check_power_status)
-               codec->patch_ops.check_power_status(codec, 0x01);
-#endif 
+       if (spec->gpio_led)
+               hda_call_check_power_status(codec, 0x01);
        if (spec->dac_list)
                stac92xx_power_down(codec);
        return 0;
@@ -4688,6 +4682,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
        }
 }
 
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int cfg;
+
+       cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+       return get_defcfg_connect(cfg);
+}
+
+static int stac92xx_connected_ports(struct hda_codec *codec,
+                                        hda_nid_t *nids, int num_nids)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int idx, num;
+       unsigned int def_conf;
+
+       for (num = 0; num < num_nids; num++) {
+               for (idx = 0; idx < spec->num_pins; idx++)
+                       if (spec->pin_nids[idx] == nids[num])
+                               break;
+               if (idx >= spec->num_pins)
+                       break;
+               def_conf = stac_get_defcfg_connect(codec, idx);
+               if (def_conf == AC_JACK_PORT_NONE)
+                       break;
+       }
+       return num;
+}
+
 static void stac92xx_mic_detect(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -4695,6 +4719,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
 
        if (get_pin_presence(codec, spec->ext_mic.pin))
                mic = &spec->ext_mic;
+       else if (get_pin_presence(codec, spec->dock_mic.pin))
+               mic = &spec->dock_mic;
        else
                mic = &spec->int_mic;
        if (mic->dmux_idx >= 0)
@@ -4937,11 +4963,9 @@ static int stac92xx_resume(struct hda_codec *codec)
                        stac_issue_unsol_event(codec,
                                               spec->autocfg.line_out_pins[0]);
        }
-#ifdef CONFIG_SND_HDA_POWER_SAVE
        /* sync mute LED */
-       if (spec->gpio_led && codec->patch_ops.check_power_status)
-               codec->patch_ops.check_power_status(codec, 0x01);
-#endif 
+       if (spec->gpio_led)
+               hda_call_check_power_status(codec, 0x01);
        return 0;
 }
 
@@ -5313,11 +5337,16 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        if (spec == NULL)
                return -ENOMEM;
 
+       /* reset pin power-down; Windows may leave these bits after reboot */
+       snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0);
+       snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
        codec->no_trigger_sense = 1;
        codec->spec = spec;
        spec->linear_tone_beep = 1;
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
+       spec->dmic_nids = stac92hd83xxx_dmic_nids;
+       spec->dmux_nids = stac92hd83xxx_mux_nids;
        spec->mux_nids = stac92hd83xxx_mux_nids;
        spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids);
        spec->adc_nids = stac92hd83xxx_adc_nids;
@@ -5363,9 +5392,13 @@ again:
        case 0x111d76d4:
        case 0x111d7605:
        case 0x111d76d5:
+       case 0x111d76e7:
                if (spec->board_config == STAC_92HD83XXX_PWR_REF)
                        break;
                spec->num_pwrs = 0;
+               spec->num_dmics = stac92xx_connected_ports(codec,
+                               stac92hd83xxx_dmic_nids,
+                               STAC92HD83XXX_NUM_DMICS);
                break;
        }
 
@@ -5424,36 +5457,6 @@ again:
        return 0;
 }
 
-/* get the pin connection (fixed, none, etc) */
-static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
-{
-       struct sigmatel_spec *spec = codec->spec;
-       unsigned int cfg;
-
-       cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
-       return get_defcfg_connect(cfg);
-}
-
-static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
-                                        hda_nid_t *nids, int num_nids)
-{
-       struct sigmatel_spec *spec = codec->spec;
-       int idx, num;
-       unsigned int def_conf;
-
-       for (num = 0; num < num_nids; num++) {
-               for (idx = 0; idx < spec->num_pins; idx++)
-                       if (spec->pin_nids[idx] == nids[num])
-                               break;
-               if (idx >= spec->num_pins)
-                       break;
-               def_conf = stac_get_defcfg_connect(codec, idx);
-               if (def_conf == AC_JACK_PORT_NONE)
-                       break;
-       }
-       return num;
-}
-
 static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
                                          hda_nid_t dig0pin)
 {
@@ -5592,7 +5595,7 @@ again:
        case 0x111d76b5:
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
                break;
@@ -5624,7 +5627,7 @@ again:
                snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
                snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
                stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS - 1);
                break;
@@ -5638,7 +5641,7 @@ again:
        default:
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
                break;
@@ -6320,6 +6323,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
        { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
        { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx},
        {} /* terminator */
 };
 
index ae3acb2..d1c3f8d 100644 (file)
@@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = {
 
 
 /* add dynamic controls */
-static int via_add_control(struct via_spec *spec, int type, const char *name,
-                          unsigned long val)
+static int __via_add_control(struct via_spec *spec, int type, const char *name,
+                            int idx, unsigned long val)
 {
        struct snd_kcontrol_new *knew;
 
@@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
        return 0;
 }
 
+#define via_add_control(spec, type, name, val) \
+       __via_add_control(spec, type, name, 0, val)
+
 static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
                                                struct snd_kcontrol_new *tmpl)
 {
@@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec)
 
 /* create input playback/capture controls for the given pin */
 static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
-                               int idx, int mix_nid)
+                               int type_idx, int idx, int mix_nid)
 {
        char name[32];
        int err;
 
        sprintf(name, "%s Playback Volume", ctlname);
-       err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+       err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
        sprintf(name, "%s Playback Switch", ctlname);
-       err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name,
+       err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx,
                              HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
        if (err < 0)
                return err;
@@ -557,17 +560,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
 static void via_auto_init_analog_input(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        unsigned int ctl;
        int i;
 
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[i];
-               if (!nid)
-                       continue;
-
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
                if (spec->smart51_enabled && is_smart51_pins(spec, nid))
                        ctl = PIN_OUT;
-               else if (i <= AUTO_PIN_FRONT_MIC)
+               else if (i == AUTO_PIN_MIC)
                        ctl = PIN_VREF50;
                else
                        ctl = PIN_IN;
@@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
 }
 static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
 {
-       int res = 0;
-       int index;
-       for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) {
-               if (pin == spec->autocfg.input_pins[index]) {
-                       res = 1;
-                       break;
-               }
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
+       int i;
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               if (pin == cfg->inputs[i].pin)
+                       return cfg->inputs[i].type <= AUTO_PIN_LINE_IN;
        }
-       return res;
+       return 0;
 }
 
 static int via_smart51_info(struct snd_kcontrol *kcontrol,
@@ -1348,25 +1348,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct via_spec *spec = codec->spec;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        int on = 1;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[index[i]];
-               if (nid) {
-                       int ctl =
-                           snd_hda_codec_read(codec, nid, 0,
-                                              AC_VERB_GET_PIN_WIDGET_CONTROL,
-                                              0);
-                       if (i == AUTO_PIN_FRONT_MIC
-                           && spec->hp_independent_mode
-                           && spec->codec_type != VT1718S)
-                               continue; /* ignore FMic for independent HP */
-                       if (ctl & AC_PINCTL_IN_EN
-                           && !(ctl & AC_PINCTL_OUT_EN))
-                               on = 0;
-               }
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               int ctl = snd_hda_codec_read(codec, nid, 0,
+                                            AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+               if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
+                       continue;
+               if (cfg->inputs[i].type == AUTO_PIN_MIC &&
+                   spec->hp_independent_mode && spec->codec_type != VT1718S)
+                       continue; /* ignore FMic for independent HP */
+               if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
+                       on = 0;
        }
        *ucontrol->value.integer.value = on;
        return 0;
@@ -1377,36 +1373,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct via_spec *spec = codec->spec;
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        int out_in = *ucontrol->value.integer.value
                ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               hda_nid_t nid = spec->autocfg.input_pins[index[i]];
-               if (i == AUTO_PIN_FRONT_MIC
-                   && spec->hp_independent_mode
-                   && spec->codec_type != VT1718S)
+       for (i = 0; i < cfg->num_inputs; i++) {
+               hda_nid_t nid = cfg->inputs[i].pin;
+               unsigned int parm;
+
+               if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
+                       continue;
+               if (cfg->inputs[i].type == AUTO_PIN_MIC &&
+                   spec->hp_independent_mode && spec->codec_type != VT1718S)
                        continue; /* don't retask FMic for independent HP */
-               if (nid) {
-                       unsigned int parm = snd_hda_codec_read(
-                               codec, nid, 0,
-                               AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-                       parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
-                       parm |= out_in;
-                       snd_hda_codec_write(codec, nid, 0,
-                                           AC_VERB_SET_PIN_WIDGET_CONTROL,
-                                           parm);
-                       if (out_in == AC_PINCTL_OUT_EN) {
-                               mute_aa_path(codec, 1);
-                               notify_aa_path_ctls(codec);
-                       }
-                       if (spec->codec_type == VT1718S)
-                               snd_hda_codec_amp_stereo(
+
+               parm = snd_hda_codec_read(codec, nid, 0,
+                                         AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+               parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
+               parm |= out_in;
+               snd_hda_codec_write(codec, nid, 0,
+                                   AC_VERB_SET_PIN_WIDGET_CONTROL,
+                                   parm);
+               if (out_in == AC_PINCTL_OUT_EN) {
+                       mute_aa_path(codec, 1);
+                       notify_aa_path_ctls(codec);
+               }
+               if (spec->codec_type == VT1718S) {
+                       snd_hda_codec_amp_stereo(
                                        codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
                                        HDA_AMP_UNMUTE);
                }
-               if (i == AUTO_PIN_FRONT_MIC) {
+               if (cfg->inputs[i].type == AUTO_PIN_MIC) {
                        if (spec->codec_type == VT1708S
                            || spec->codec_type == VT1716S) {
                                /* input = index 1 (AOW3) */
@@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = {
 static int via_smart51_build(struct via_spec *spec)
 {
        struct snd_kcontrol_new *knew;
-       int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
+       const struct auto_pin_cfg *cfg = &spec->autocfg;
        hda_nid_t nid;
        int i;
 
@@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec)
        if (knew == NULL)
                return -ENOMEM;
 
-       for (i = 0; i < ARRAY_SIZE(index); i++) {
-               nid = spec->autocfg.input_pins[index[i]];
-               if (nid) {
+       for (i = 0; i < cfg->num_inputs; i++) {
+               nid = cfg->inputs[i].pin;
+               if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) {
                        knew = via_clone_control(spec, &via_smart51_mixer[1]);
                        if (knew == NULL)
                                return -ENOMEM;
                        knew->subdevice = nid;
+                       break;
                }
        }
 
@@ -2375,13 +2374,8 @@ static void create_hp_imux(struct via_spec *spec)
        static const char *texts[] = { "OFF", "ON", NULL};
 
        /* for hp mode select */
-       i = 0;
-       while (texts[i] != NULL) {
-               imux->items[imux->num_items].label =  texts[i];
-               imux->items[imux->num_items].index = i;
-               imux->num_items++;
-               i++;
-       }
+       for (i = 0; texts[i]; i++)
+               snd_hda_add_imux_item(imux, texts[i], i, NULL);
 
        spec->hp_mux = &spec->private_imux[1];
 }
@@ -2413,51 +2407,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
-                                               const struct auto_pin_cfg *cfg)
+static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
+                                           const struct auto_pin_cfg *cfg,
+                                           hda_nid_t cap_nid,
+                                           hda_nid_t pin_idxs[], int num_idxs)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
+       int i, err, idx, type, type_idx = 0;
 
        /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1d: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1e: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x21: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x24: /* CD */
-                       idx = 1;
+       for (idx = 0; idx < num_idxs; idx++) {
+               if (pin_idxs[idx] == 0xff) {
+                       snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL);
                        break;
                }
-               err = via_new_analog_input(spec, labels[i], idx, 0x17);
+       }
+
+       for (i = 0; i < cfg->num_inputs; i++) {
+               const char *label;
+               type = cfg->inputs[i].type;
+               for (idx = 0; idx < num_idxs; idx++)
+                       if (pin_idxs[idx] == cfg->inputs[i].pin)
+                               break;
+               if (idx >= num_idxs)
+                       continue;
+               if (i > 0 && type == cfg->inputs[i - 1].type)
+                       type_idx++;
+               else
+                       type_idx = 0;
+               label = hda_get_autocfg_input_label(codec, cfg, i);
+               err = via_new_analog_input(spec, label, type_idx, idx, cap_nid);
                if (err < 0)
                        return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
+               snd_hda_add_imux_item(imux, label, idx, NULL);
        }
        return 0;
 }
 
+/* create playback/capture controls for input pins */
+static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
+}
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static struct hda_amp_list vt1708_loopbacks[] = {
        { 0x17, HDA_INPUT, 1 },
@@ -2554,7 +2550,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
        err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
        /* add jack detect on/off control */
@@ -3021,49 +3017,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1d: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1e: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x21: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x23: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x18);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1709_parse_auto_config(struct hda_codec *codec)
@@ -3086,7 +3045,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
        err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -3588,49 +3547,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = idx;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1708B_parse_auto_config(struct hda_codec *codec)
@@ -3653,7 +3575,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
        err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4061,49 +3983,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 /* fill out digital output widgets; one for master and one for slave outputs */
@@ -4151,7 +4036,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
        err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4441,58 +4326,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
        imux = &spec->private_imux[1];
 
        /* for hp mode select */
-       i = 0;
-       while (texts[i] != NULL)        {
-               imux->items[imux->num_items].label =  texts[i];
-               imux->items[imux->num_items].index = i;
-               imux->num_items++;
-               i++;
-       }
+       for (i = 0; texts[i]; i++)
+               snd_hda_add_imux_item(imux, texts[i], i, NULL);
 
        spec->hp_mux = &spec->private_imux[1];
        return 0;
 }
 
 /* create playback/capture controls for input pins */
-static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 3;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x14: /* Mic */
-                       idx = 1;
-                       break;
-
-               case 0x15: /* Line In */
-                       idx = 2;
-                       break;
-
-               case 0x18: /* Front Mic */
-                       idx = 3;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x1A);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1702_parse_auto_config(struct hda_codec *codec)
@@ -4521,7 +4368,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
                                  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
                                  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
                                  (1 << AC_AMPCAP_MUTE_SHIFT));
-       err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -4872,49 +4719,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 1;
-                       break;
-
-               case 0x2a: /* Line In */
-                       idx = 2;
-                       break;
-
-               case 0x29: /* Front Mic */
-                       idx = 3;
-                       break;
-
-               case 0x2c: /* CD */
-                       idx = 0;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1718S_parse_auto_config(struct hda_codec *codec)
@@ -4938,7 +4748,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec)
        err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -5371,49 +5181,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
-       struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x1a: /* Mic */
-                       idx = 2;
-                       break;
-
-               case 0x1b: /* Line In */
-                       idx = 3;
-                       break;
-
-               case 0x1e: /* Front Mic */
-                       idx = 4;
-                       break;
-
-               case 0x1f: /* CD */
-                       idx = 1;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x16);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx-1;
-               imux->num_items++;
-       }
-       return 0;
+       static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
+       return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
+                                               ARRAY_SIZE(pin_idxs));
 }
 
 static int vt1716S_parse_auto_config(struct hda_codec *codec)
@@ -5436,7 +5209,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec)
        err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -5717,54 +5490,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 0;
-                       break;
-
-               case 0x2a: /* Line In */
-                       idx = 1;
-                       break;
-
-               case 0x29: /* Front Mic */
-                       idx = 2;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
+       static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
+       int err;
 
+       err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                              ARRAY_SIZE(pin_idxs));
+       if (err < 0)
+               return err;
        /* build volume/mute control of loopback */
-       err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21);
+       err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21);
        if (err < 0)
                return err;
 
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 3;
-       imux->num_items++;
-
        /* for digital mic select */
-       imux->items[imux->num_items].label = "Digital Mic";
-       imux->items[imux->num_items].index = 4;
-       imux->num_items++;
+       snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL);
 
        return 0;
 }
@@ -5792,7 +5536,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec)
        err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
@@ -6067,53 +5811,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec,
+static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec,
                                                const struct auto_pin_cfg *cfg)
 {
-       static char *labels[] = {
-               "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
-       };
+       struct via_spec *spec = codec->spec;
        struct hda_input_mux *imux = &spec->private_imux[0];
-       int i, err, idx = 0;
-
-       for (i = 0; i < AUTO_PIN_LAST; i++) {
-               if (!cfg->input_pins[i])
-                       continue;
-
-               switch (cfg->input_pins[i]) {
-               case 0x2b: /* Mic */
-                       idx = 0;
-                       break;
+       static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
+       int err;
 
-               case 0x2a: /* Line In */
-                       idx = 1;
-                       break;
+       err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
+                                              ARRAY_SIZE(pin_idxs));
+       if (err < 0)
+               return err;
 
-               case 0x29: /* Front Mic */
-                       idx = 2;
-                       break;
-               }
-               err = via_new_analog_input(spec, labels[i], idx, 0x21);
-               if (err < 0)
-                       return err;
-               imux->items[imux->num_items].label = labels[i];
-               imux->items[imux->num_items].index = idx;
-               imux->num_items++;
-       }
        /* build volume/mute control of loopback */
-       err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21);
+       err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21);
        if (err < 0)
                return err;
 
-       /* for internal loopback recording select */
-       imux->items[imux->num_items].label = "Stereo Mixer";
-       imux->items[imux->num_items].index = 5;
-       imux->num_items++;
-
        /* for digital mic select */
-       imux->items[imux->num_items].label = "Digital Mic";
-       imux->items[imux->num_items].index = 6;
-       imux->num_items++;
+       snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL);
 
        return 0;
 }
@@ -6141,7 +5858,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec)
        err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
        if (err < 0)
                return err;
-       err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg);
+       err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg);
        if (err < 0)
                return err;
 
index d216362..712c171 100644 (file)
@@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_DELTA1010E:
        case ICE1712_SUBDEVICE_DELTA1010LT:
        case ICE1712_SUBDEVICE_MEDIASTATION:
+       case ICE1712_SUBDEVICE_EDIROLDA2496:
                ice->num_total_dacs = 8;
                ice->num_total_adcs = 8;
                break;
@@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
                err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice);
                break;
        case ICE1712_SUBDEVICE_DELTA1010LT:
+       case ICE1712_SUBDEVICE_EDIROLDA2496:
                err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice);
                break;
        case ICE1712_SUBDEVICE_DELTA66:
@@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
        case ICE1712_SUBDEVICE_DELTA66:
        case ICE1712_SUBDEVICE_VX442:
        case ICE1712_SUBDEVICE_DELTA66E:
+       case ICE1712_SUBDEVICE_EDIROLDA2496:
                err = snd_ice1712_akm4xxx_build_controls(ice);
                if (err < 0)
                        return err;
@@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
                .chip_init = snd_ice1712_delta_init,
                .build_controls = snd_ice1712_delta_add_controls,
        },
+       {
+               .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496,
+               .name = "Edirol DA2496",
+               .model = "da2496",
+               .chip_init = snd_ice1712_delta_init,
+               .build_controls = snd_ice1712_delta_add_controls,
+       },
        { } /* terminator */
 };
index f7f14df..1a0ac6c 100644 (file)
@@ -34,7 +34,8 @@
                "{MidiMan M Audio,Delta 410},"\
                "{MidiMan M Audio,Audiophile 24/96},"\
                "{Digigram,VX442},"\
-               "{Lionstracs,Mediastation},"
+               "{Lionstracs,Mediastation},"\
+               "{Edirol,DA2496},"
 
 #define ICE1712_SUBDEVICE_DELTA1010    0x121430d6
 #define ICE1712_SUBDEVICE_DELTA1010E   0xff1430d6
@@ -47,6 +48,7 @@
 #define ICE1712_SUBDEVICE_DELTA1010LT  0x12143bd6
 #define ICE1712_SUBDEVICE_VX442                0x12143cd6
 #define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100
+#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
index 6bc3f91..cdb873f 100644 (file)
@@ -638,7 +638,7 @@ static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
  */
 static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
-       struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+       struct snd_ice1712 *ice = entry->private_data;
        char line[64];
        unsigned int reg, val;
        mutex_lock(&ice->gpio_mutex);
@@ -653,7 +653,7 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf
 
 static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
-       struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+       struct snd_ice1712 *ice = entry->private_data;
        int reg, val;
 
        mutex_lock(&ice->gpio_mutex);
@@ -676,7 +676,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
 
 static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
-       struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+       struct snd_ice1712 *ice = entry->private_data;
        int reg, val;
 
        mutex_lock(&ice->gpio_mutex);
index 2a8e5cd..e36ddb9 100644 (file)
@@ -654,7 +654,7 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
 static void stac9460_proc_regs_read(struct snd_info_entry *entry,
                struct snd_info_buffer *buffer)
 {
-       struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
+       struct snd_ice1712 *ice = entry->private_data;
        int reg, val;
        /* registers 0x0 - 0x14 */
        for (reg = 0; reg <= 0x15; reg++) {
index 6c0a11a..98a8eb3 100644 (file)
@@ -79,6 +79,7 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
        { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF },
+       { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
        { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
@@ -505,7 +506,8 @@ static const struct oxygen_model model_generic = {
                         PLAYBACK_2_TO_AC97_1 |
                         CAPTURE_0_FROM_I2S_1 |
                         CAPTURE_1_FROM_SPDIF |
-                        CAPTURE_2_FROM_AC97_1,
+                        CAPTURE_2_FROM_AC97_1 |
+                        AC97_CD_INPUT,
        .dac_channels = 8,
        .dac_volume_min = 0,
        .dac_volume_max = 255,
index a3409ed..7d5222c 100644 (file)
@@ -34,6 +34,7 @@
      /* CAPTURE_3_FROM_I2S_3           not implemented */
 #define MIDI_OUTPUT            0x0800
 #define MIDI_INPUT             0x1000
+#define AC97_CD_INPUT          0x2000
 
 enum {
        CONTROL_SPDIF_PCM,
index 7e93cf8..e5ebe56 100644 (file)
@@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip,
        }
 }
 
-static void pci_bridge_magic(void)
+static void configure_pcie_bridge(struct pci_dev *pci)
 {
-       struct pci_dev *pci = NULL;
+       enum { PEX811X, PI7C9X110 };
+       static const struct pci_device_id bridge_ids[] = {
+               { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
+               { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
+               { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
+               { }
+       };
+       struct pci_dev *bridge;
+       const struct pci_device_id *id;
        u32 tmp;
 
-       for (;;) {
-               /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */
-               pci = pci_get_device(0x12d8, 0xe110, pci);
-               if (!pci)
-                       break;
-               /*
-                * ... configure its secondary internal arbiter to park to
-                * the secondary port, instead of to the last master.
-                */
-               if (!pci_read_config_dword(pci, 0x40, &tmp)) {
-                       tmp |= 1;
-                       pci_write_config_dword(pci, 0x40, tmp);
-               }
-               /* Why?  Try asking C-Media. */
+       if (!pci->bus || !pci->bus->self)
+               return;
+       bridge = pci->bus->self;
+
+       id = pci_match_id(bridge_ids, bridge);
+       if (!id)
+               return;
+
+       switch (id->driver_data) {
+       case PEX811X:   /* PLX PEX8111/PEX8112 PCIe/PCI bridge */
+               pci_read_config_dword(bridge, 0x48, &tmp);
+               tmp |= 1;       /* enable blind prefetching */
+               tmp |= 1 << 11; /* enable beacon generation */
+               pci_write_config_dword(bridge, 0x48, tmp);
+
+               pci_write_config_dword(bridge, 0x84, 0x0c);
+               pci_read_config_dword(bridge, 0x88, &tmp);
+               tmp &= ~(7 << 27);
+               tmp |= 2 << 27; /* set prefetch size to 128 bytes */
+               pci_write_config_dword(bridge, 0x88, tmp);
+               break;
+
+       case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */
+               pci_read_config_dword(bridge, 0x40, &tmp);
+               tmp |= 1;       /* park the PCI arbiter to the sound chip */
+               pci_write_config_dword(bridge, 0x40, tmp);
+               break;
        }
 }
 
@@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
        snd_card_set_dev(card, &pci->dev);
        card->private_free = oxygen_card_free;
 
-       pci_bridge_magic();
+       configure_pcie_bridge(pci);
        oxygen_init(chip);
        chip->model.init(chip);
 
index f375b8a..2849b36 100644 (file)
@@ -708,7 +708,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
                .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \
        }
 
-static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
+static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0);
 static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
 static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
 
@@ -972,6 +972,9 @@ static int add_controls(struct oxygen *chip,
                if (!strcmp(template.name, "Stereo Upmixing") &&
                    chip->model.dac_channels == 2)
                        continue;
+               if (!strncmp(template.name, "CD Capture ", 11) &&
+                   !(chip->model.device_config & AC97_CD_INPUT))
+                       continue;
                if (!strcmp(template.name, "Master Playback Volume") &&
                    chip->model.dac_tlv) {
                        template.tlv.p = chip->model.dac_tlv;
index 9dff695..8146674 100644 (file)
@@ -56,8 +56,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
        .channels_max = 2,
        .buffer_bytes_max = BUFFER_BYTES_MAX,
        .period_bytes_min = PERIOD_BYTES_MIN,
-       .period_bytes_max = BUFFER_BYTES_MAX / 2,
-       .periods_min = 2,
+       .period_bytes_max = BUFFER_BYTES_MAX,
+       .periods_min = 1,
        .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
 };
 static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
@@ -82,8 +82,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
        .channels_max = 8,
        .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
        .period_bytes_min = PERIOD_BYTES_MIN,
-       .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2,
-       .periods_min = 2,
+       .period_bytes_max = BUFFER_BYTES_MAX_MULTICH,
+       .periods_min = 1,
        .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
 };
 static const struct snd_pcm_hardware oxygen_ac97_hardware = {
@@ -100,8 +100,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
        .channels_max = 2,
        .buffer_bytes_max = BUFFER_BYTES_MAX,
        .period_bytes_min = PERIOD_BYTES_MIN,
-       .period_bytes_max = BUFFER_BYTES_MAX / 2,
-       .periods_min = 2,
+       .period_bytes_max = BUFFER_BYTES_MAX,
+       .periods_min = 1,
        .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
 };
 
index 72de159..4dcd41b 100644 (file)
 /* OXYGEN_CHANNEL_* */
 
 #define OXYGEN_CODEC_VERSION           0xe4
-#define  OXYGEN_XCID_MASK              0x07
+#define  OXYGEN_CODEC_ID_MASK          0x07
 
 #define OXYGEN_REVISION                        0xe6
-#define  OXYGEN_REVISION_XPKGID_MASK   0x0007
+#define  OXYGEN_PACKAGE_ID_MASK                0x0007
+#define  OXYGEN_PACKAGE_ID_8786                0x0004
+#define  OXYGEN_PACKAGE_ID_8787                0x0006
+#define  OXYGEN_PACKAGE_ID_8788                0x0007
 #define  OXYGEN_REVISION_MASK          0xfff8
-#define  OXYGEN_REVISION_2             0x0008  /* bit flag */
-#define  OXYGEN_REVISION_8787          0x0014  /* 8 bits */
+#define  OXYGEN_REVISION_2             0x0008
 
 #define OXYGEN_OFFSIN_48K              0xe8
 #define OXYGEN_OFFSBASE_48K            0xe9
index 06c863e..469010a 100644 (file)
@@ -25,9 +25,9 @@
 #include "xonar.h"
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
-MODULE_DESCRIPTION("Asus AVx00 driver");
+MODULE_DESCRIPTION("Asus Virtuoso driver");
 MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}");
+MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -49,6 +49,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
        { OXYGEN_PCI_SUBID(0x1043, 0x834f) },
        { OXYGEN_PCI_SUBID(0x1043, 0x835c) },
        { OXYGEN_PCI_SUBID(0x1043, 0x835d) },
+       { OXYGEN_PCI_SUBID(0x1043, 0x835e) },
        { OXYGEN_PCI_SUBID(0x1043, 0x838e) },
        { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
        { }
index 7c4986b..aa27c31 100644 (file)
@@ -367,13 +367,6 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip,
 
 static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
 
-static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
-{
-       if (!strncmp(template->name, "CD Capture ", 11))
-               return 1; /* no CD input */
-       return 0;
-}
-
 static int xonar_d1_mixer_init(struct oxygen *chip)
 {
        int err;
@@ -391,7 +384,6 @@ static const struct oxygen_model model_xonar_d1 = {
        .longname = "Asus Virtuoso 100",
        .chip = "AV200",
        .init = xonar_d1_init,
-       .control_filter = xonar_d1_control_filter,
        .mixer_init = xonar_d1_mixer_init,
        .cleanup = xonar_d1_cleanup,
        .suspend = xonar_d1_suspend,
index ba18fb5..d491fd6 100644 (file)
  * GPIO 5 <- 0
  */
 
+/*
+ * Xonar HDAV1.3 Slim
+ * ------------------
+ *
+ * CMI8788:
+ *
+ * GPIO 1 -> enable output
+ *
+ * TXD -> HDMI controller
+ * RXD <- HDMI controller
+ */
+
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -362,7 +374,6 @@ static void xonar_st_init_common(struct oxygen *chip)
 {
        struct xonar_pcm179x *data = chip->model_data;
 
-       data->generic.anti_pop_delay = 100;
        data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE;
        data->dacs = chip->model.private_data ? 4 : 1;
        data->hp_gain_offset = 2*-18;
@@ -408,6 +419,7 @@ static void xonar_st_init(struct oxygen *chip)
 {
        struct xonar_pcm179x *data = chip->model_data;
 
+       data->generic.anti_pop_delay = 100;
        data->has_cs2000 = 1;
        data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1;
 
@@ -428,6 +440,7 @@ static void xonar_stx_init(struct oxygen *chip)
        struct xonar_pcm179x *data = chip->model_data;
 
        xonar_st_init_i2c(chip);
+       data->generic.anti_pop_delay = 800;
        data->generic.ext_power_reg = OXYGEN_GPI_DATA;
        data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
        data->generic.ext_power_bit = GPI_EXT_POWER;
@@ -915,13 +928,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
        return 0;
 }
 
-static int xonar_st_control_filter(struct snd_kcontrol_new *template)
-{
-       if (!strncmp(template->name, "CD Capture ", 11))
-               return 1; /* no CD input */
-       return 0;
-}
-
 static int add_pcm1796_controls(struct oxygen *chip)
 {
        int err;
@@ -991,7 +997,8 @@ static const struct oxygen_model model_xonar_d2 = {
                         CAPTURE_0_FROM_I2S_2 |
                         CAPTURE_1_FROM_SPDIF |
                         MIDI_OUTPUT |
-                        MIDI_INPUT,
+                        MIDI_INPUT |
+                        AC97_CD_INPUT,
        .dac_channels = 8,
        .dac_volume_min = 255 - 2*60,
        .dac_volume_max = 255,
@@ -1037,7 +1044,6 @@ static const struct oxygen_model model_xonar_st = {
        .longname = "Asus Virtuoso 100",
        .chip = "AV200",
        .init = xonar_st_init,
-       .control_filter = xonar_st_control_filter,
        .mixer_init = xonar_st_mixer_init,
        .cleanup = xonar_st_cleanup,
        .suspend = xonar_st_suspend,
@@ -1108,6 +1114,9 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
                chip->model.resume = xonar_stx_resume;
                chip->model.set_dac_params = set_pcm1796_params;
                break;
+       case 0x835e:
+               snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n");
+               return -ENODEV;
        default:
                return -EINVAL;
        }
index b82c1cf..200f760 100644 (file)
  * SPI 0 -> WM8766 (surround, center/LFE, back)
  * SPI 1 -> WM8776 (front, input)
  *
- * GPIO 4 <- headphone detect
- * GPIO 6 -> route input jack to input 1/2 (1/0)
- * GPIO 7 -> enable output to speakers
- * GPIO 8 -> enable output to speakers
+ * GPIO 4 <- headphone detect, 0 = plugged
+ * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
+ * GPIO 7 -> enable output to front L/R speaker channels
+ * GPIO 8 -> enable output to other speaker channels and front panel headphone
+ *
+ * WM8766:
+ *
+ * input 1 <- line
+ * input 2 <- mic
+ * input 3 <- front mic
+ * input 4 <- aux
  */
 
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <sound/control.h>
 #include <sound/core.h>
+#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/tlv.h>
@@ -44,7 +52,8 @@
 
 #define GPIO_DS_HP_DETECT      0x0010
 #define GPIO_DS_INPUT_ROUTE    0x0040
-#define GPIO_DS_OUTPUT_ENABLE  0x0180
+#define GPIO_DS_OUTPUT_FRONTLR 0x0080
+#define GPIO_DS_OUTPUT_ENABLE  0x0100
 
 #define LC_CONTROL_LIMITER     0x40000000
 #define LC_CONTROL_ALC         0x20000000
@@ -56,6 +65,7 @@ struct xonar_wm87x6 {
        struct snd_kcontrol *line_adcmux_control;
        struct snd_kcontrol *mic_adcmux_control;
        struct snd_kcontrol *lc_controls[13];
+       struct snd_jack *hp_jack;
 };
 
 static void wm8776_write(struct oxygen *chip,
@@ -97,8 +107,12 @@ static void wm8766_write(struct oxygen *chip,
                         (0 << OXYGEN_SPI_CODEC_SHIFT) |
                         OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
                         (reg << 9) | value);
-       if (reg < ARRAY_SIZE(data->wm8766_regs))
+       if (reg < ARRAY_SIZE(data->wm8766_regs)) {
+               if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
+                   (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
+                       value &= ~WM8766_UPDATE;
                data->wm8766_regs[reg] = value;
+       }
 }
 
 static void wm8766_write_cached(struct oxygen *chip,
@@ -107,12 +121,8 @@ static void wm8766_write_cached(struct oxygen *chip,
        struct xonar_wm87x6 *data = chip->model_data;
 
        if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
-           value != data->wm8766_regs[reg]) {
-               if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
-                   (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
-                       value &= ~WM8766_UPDATE;
+           value != data->wm8766_regs[reg])
                wm8766_write(chip, reg, value);
-       }
 }
 
 static void wm8776_registers_init(struct oxygen *chip)
@@ -141,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip)
 
 static void wm8766_registers_init(struct oxygen *chip)
 {
+       struct xonar_wm87x6 *data = chip->model_data;
+
        wm8766_write(chip, WM8766_RESET, 0);
+       wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
        wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
        wm8766_write(chip, WM8766_DAC_CTRL2,
                     WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
@@ -170,6 +183,40 @@ static void wm8776_init(struct oxygen *chip)
        wm8776_registers_init(chip);
 }
 
+static void wm8766_init(struct oxygen *chip)
+{
+       struct xonar_wm87x6 *data = chip->model_data;
+
+       data->wm8766_regs[WM8766_DAC_CTRL] =
+               WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
+       wm8766_registers_init(chip);
+}
+
+static void xonar_ds_handle_hp_jack(struct oxygen *chip)
+{
+       struct xonar_wm87x6 *data = chip->model_data;
+       bool hp_plugged;
+       unsigned int reg;
+
+       mutex_lock(&chip->mutex);
+
+       hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
+                      GPIO_DS_HP_DETECT);
+
+       oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+                             hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
+                             GPIO_DS_OUTPUT_FRONTLR);
+
+       reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
+       if (hp_plugged)
+               reg |= WM8766_MUTEALL;
+       wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
+
+       snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
+
+       mutex_unlock(&chip->mutex);
+}
+
 static void xonar_ds_init(struct oxygen *chip)
 {
        struct xonar_wm87x6 *data = chip->model_data;
@@ -178,16 +225,22 @@ static void xonar_ds_init(struct oxygen *chip)
        data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
 
        wm8776_init(chip);
-       wm8766_registers_init(chip);
+       wm8766_init(chip);
 
-       oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
-                             GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
+       oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+                         GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
+       oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
+                           GPIO_DS_HP_DETECT);
        oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
        oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
        chip->interrupt_mask |= OXYGEN_INT_GPIO;
 
        xonar_enable_output(chip);
 
+       snd_jack_new(chip->card, "Headphone",
+                    SND_JACK_HEADPHONE, &data->hp_jack);
+       xonar_ds_handle_hp_jack(chip);
+
        snd_component_add(chip->card, "WM8776");
        snd_component_add(chip->card, "WM8766");
 }
@@ -208,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip)
        wm8776_registers_init(chip);
        wm8766_registers_init(chip);
        xonar_enable_output(chip);
+       xonar_ds_handle_hp_jack(chip);
 }
 
 static void wm8776_adc_hardware_filter(unsigned int channel,
@@ -323,12 +377,27 @@ static void update_wm87x6_mute(struct oxygen *chip)
                            (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
 }
 
-static void xonar_ds_gpio_changed(struct oxygen *chip)
+static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
 {
-       u16 bits;
+       struct xonar_wm87x6 *data = chip->model_data;
+       unsigned int reg;
 
-       bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
-       snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
+       /*
+        * The WM8766 can mix left and right channels, but this setting
+        * applies to all three stereo pairs.
+        */
+       reg = data->wm8766_regs[WM8766_DAC_CTRL] &
+               ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
+       if (mixed)
+               reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
+       else
+               reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
+       wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
+}
+
+static void xonar_ds_gpio_changed(struct oxygen *chip)
+{
+       xonar_ds_handle_hp_jack(chip);
 }
 
 static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
@@ -896,7 +965,10 @@ static const struct snd_kcontrol_new ds_controls[] = {
                .put = wm8776_input_mux_put,
                .private_value = 1 << 1,
        },
-       WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0),
+       WM8776_BIT_SWITCH("Front Mic Capture Switch",
+                         WM8776_ADCMUX, 1 << 2, 0, 0),
+       WM8776_BIT_SWITCH("Aux Capture Switch",
+                         WM8776_ADCMUX, 1 << 3, 0, 0),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "ADC Filter Capture Enum",
@@ -956,13 +1028,6 @@ static const struct snd_kcontrol_new lc_controls[] = {
                                LC_CONTROL_ALC, wm8776_ngth_db_scale),
 };
 
-static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
-{
-       if (!strncmp(template->name, "CD Capture ", 11))
-               return 1; /* no CD input */
-       return 0;
-}
-
 static int xonar_ds_mixer_init(struct oxygen *chip)
 {
        struct xonar_wm87x6 *data = chip->model_data;
@@ -999,10 +1064,9 @@ static int xonar_ds_mixer_init(struct oxygen *chip)
 
 static const struct oxygen_model model_xonar_ds = {
        .shortname = "Xonar DS",
-       .longname = "Asus Virtuoso 200",
+       .longname = "Asus Virtuoso 66",
        .chip = "AV200",
        .init = xonar_ds_init,
-       .control_filter = xonar_ds_control_filter,
        .mixer_init = xonar_ds_mixer_init,
        .cleanup = xonar_ds_cleanup,
        .suspend = xonar_ds_suspend,
@@ -1013,6 +1077,7 @@ static const struct oxygen_model model_xonar_ds = {
        .set_adc_params = set_wm8776_adc_params,
        .update_dac_volume = update_wm87x6_volume,
        .update_dac_mute = update_wm87x6_mute,
+       .update_center_lfe_mix = update_wm8766_center_lfe_mix,
        .gpio_changed = xonar_ds_gpio_changed,
        .dac_tlv = wm87x6_dac_db_scale,
        .model_data_size = sizeof(struct xonar_wm87x6),
index d19dc05..d5f5b44 100644 (file)
@@ -1527,14 +1527,14 @@ snd_rme96_free(void *private_data)
 static void
 snd_rme96_free_spdif_pcm(struct snd_pcm *pcm)
 {
-       struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
+       struct rme96 *rme96 = pcm->private_data;
        rme96->spdif_pcm = NULL;
 }
 
 static void
 snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
 {
-       struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
+       struct rme96 *rme96 = pcm->private_data;
        rme96->adat_pcm = NULL;
 }
 
@@ -1661,7 +1661,7 @@ static void
 snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
        int n;
-       struct rme96 *rme96 = (struct rme96 *)entry->private_data;
+       struct rme96 *rme96 = entry->private_data;
        
        rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
 
@@ -2348,7 +2348,7 @@ snd_rme96_probe(struct pci_dev *pci,
        if (err < 0)
                return err;
        card->private_free = snd_rme96_card_free;
-       rme96 = (struct rme96 *)card->private_data;     
+       rme96 = card->private_data;
        rme96->card = card;
        rme96->pci = pci;
        snd_card_set_dev(card, &pci->dev);
index d6fa7bf..0b720cf 100644 (file)
@@ -3284,7 +3284,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
 static void
 snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
-       struct hdsp *hdsp = (struct hdsp *) entry->private_data;
+       struct hdsp *hdsp = entry->private_data;
        unsigned int status;
        unsigned int status2;
        char *pref_sync_ref;
@@ -4566,7 +4566,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm
 
 static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct hdsp *hdsp = (struct hdsp *)hw->private_data;
+       struct hdsp *hdsp = hw->private_data;
        void __user *argp = (void __user *)arg;
        int err;
 
@@ -5156,7 +5156,7 @@ static int snd_hdsp_free(struct hdsp *hdsp)
 
 static void snd_hdsp_card_free(struct snd_card *card)
 {
-       struct hdsp *hdsp = (struct hdsp *) card->private_data;
+       struct hdsp *hdsp = card->private_data;
 
        if (hdsp)
                snd_hdsp_free(hdsp);
@@ -5182,7 +5182,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
        if (err < 0)
                return err;
 
-       hdsp = (struct hdsp *) card->private_data;
+       hdsp = card->private_data;
        card->private_free = snd_hdsp_card_free;
        hdsp->dev = dev;
        hdsp->pci = pci;
index 20afdf9..961d982 100644 (file)
@@ -785,7 +785,7 @@ static int snapper_set_capture_source(struct pmac_tumbler *mix)
        if (! mix->i2c.client)
                return -ENODEV;
        if (mix->capture_source)
-               mix->acs = mix->acs |= 2;
+               mix->acs |= 2;
        else
                mix->acs &= ~2;
        return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
index dc5249f..d0e7532 100644 (file)
@@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
        runtime->dma_bytes = params_buffer_bytes(params);
 
-       prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
        prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
 
        prtd->dma_buffer = runtime->dma_addr;
@@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = 0xffffffff;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                pr_debug("at32-pcm:"
                                "Allocating PCM capture DMA buffer\n");
                ret = atmel_pcm_preallocate_dma_buffer(pcm,
@@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
 }
 
 #ifdef CONFIG_PM
-static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
+static int atmel_pcm_suspend(struct snd_soc_dai *dai)
 {
-       struct snd_pcm *pcm = dai_link->pcm;
-       struct snd_pcm_str *stream = &pcm->streams[0];
-       struct snd_pcm_substream *substream = stream->substream;
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime = dai->runtime;
        struct atmel_runtime_data *prtd;
        struct atmel_pcm_dma_params *params;
 
@@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
        return 0;
 }
 
-static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
+static int atmel_pcm_resume(struct snd_soc_dai *dai)
 {
-       struct snd_pcm *pcm = dai_link->pcm;
-       struct snd_pcm_str *stream = &pcm->streams[0];
-       struct snd_pcm_substream *substream = stream->substream;
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_pcm_runtime *runtime = dai->runtime;
        struct atmel_runtime_data *prtd;
        struct atmel_pcm_dma_params *params;
 
@@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
 #define atmel_pcm_resume       NULL
 #endif
 
-struct snd_soc_platform atmel_soc_platform = {
-       .name           = "atmel-audio",
-       .pcm_ops        = &atmel_pcm_ops,
+static struct snd_soc_platform_driver atmel_soc_platform = {
+       .ops            = &atmel_pcm_ops,
        .pcm_new        = atmel_pcm_new,
        .pcm_free       = atmel_pcm_free_dma_buffers,
        .suspend        = atmel_pcm_suspend,
        .resume         = atmel_pcm_resume,
 };
-EXPORT_SYMBOL_GPL(atmel_soc_platform);
 
-static int __init atmel_pcm_modinit(void)
+static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
+}
+
+static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver atmel_pcm_driver = {
+       .driver = {
+                       .name = "atmel-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = atmel_soc_platform_probe,
+       .remove = __devexit_p(atmel_soc_platform_remove),
+};
+
+static int __init snd_atmel_pcm_init(void)
 {
-       return snd_soc_register_platform(&atmel_soc_platform);
+       return platform_driver_register(&atmel_pcm_driver);
 }
-module_init(atmel_pcm_modinit);
+module_init(snd_atmel_pcm_init);
 
-static void __exit atmel_pcm_modexit(void)
+static void __exit snd_atmel_pcm_exit(void)
 {
-       snd_soc_unregister_platform(&atmel_soc_platform);
+       platform_driver_unregister(&atmel_pcm_driver);
 }
-module_exit(atmel_pcm_modexit);
+module_exit(snd_atmel_pcm_exit);
 
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("Atmel PCM module");
index ec9b282..2597329 100644 (file)
@@ -74,9 +74,6 @@ struct atmel_pcm_dma_params {
        void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
 };
 
-extern struct snd_soc_platform atmel_soc_platform;
-
-
 /*
  * SSC register access (since ssc_writel() / ssc_readl() require literal name)
  */
index c85844d..5d230ce 100644 (file)
@@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
 static int atmel_ssc_startup(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
        int dir_mask;
 
        pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
@@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
 static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir, dir_mask;
 
@@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       int id = rtd->dai->cpu_dai->id;
+       int id = dai->id;
        struct atmel_ssc_info *ssc_p = &ssc_info[id];
        struct atmel_pcm_dma_params *dma_params;
        int dir, channels, bits;
@@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
         * function.  It should not be used for other purposes
         * as it is common to all substreams.
         */
-       snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params);
+       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
 
        channels = params_channels(params);
 
@@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
        struct atmel_pcm_dma_params *dma_params;
        int dir;
 
@@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
 #  define atmel_ssc_resume     NULL
 #endif /* CONFIG_PM */
 
+static int atmel_ssc_probe(struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
+       int ret = 0;
+
+       snd_soc_dai_set_drvdata(dai, ssc_p);
+
+       /*
+        * Request SSC device
+        */
+       ssc_p->ssc = ssc_request(dai->id);
+       if (IS_ERR(ssc_p->ssc)) {
+               printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
+               ret = PTR_ERR(ssc_p->ssc);
+       }
+
+       return ret;
+}
+
+static int atmel_ssc_remove(struct snd_soc_dai *dai)
+{
+       struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
+
+       ssc_free(ssc_p->ssc);
+       return 0;
+}
 
 #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
 
@@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
        .set_clkdiv     = atmel_ssc_set_dai_clkdiv,
 };
 
-struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
-       {       .name = "atmel-ssc0",
-               .id = 0,
+static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
+       {
+               .name = "atmel-ssc-dai.0",
+               .probe = atmel_ssc_probe,
+               .remove = atmel_ssc_remove,
                .suspend = atmel_ssc_suspend,
                .resume = atmel_ssc_resume,
                .playback = {
@@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
                        .rates = ATMEL_SSC_RATES,
                        .formats = ATMEL_SSC_FORMATS,},
                .ops = &atmel_ssc_dai_ops,
-               .private_data = &ssc_info[0],
        },
 #if NUM_SSC_DEVICES == 3
-       {       .name = "atmel-ssc1",
-               .id = 1,
+       {
+               .name = "atmel-ssc-dai.1",
+               .probe = atmel_ssc_probe,
+               .remove = atmel_ssc_remove,
                .suspend = atmel_ssc_suspend,
                .resume = atmel_ssc_resume,
                .playback = {
@@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
                        .rates = ATMEL_SSC_RATES,
                        .formats = ATMEL_SSC_FORMATS,},
                .ops = &atmel_ssc_dai_ops,
-               .private_data = &ssc_info[1],
        },
-       {       .name = "atmel-ssc2",
-               .id = 2,
+       {
+               .name = "atmel-ssc-dai.2",
+               .probe = atmel_ssc_probe,
+               .remove = atmel_ssc_remove,
                .suspend = atmel_ssc_suspend,
                .resume = atmel_ssc_resume,
                .playback = {
@@ -756,23 +783,94 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
                        .rates = ATMEL_SSC_RATES,
                        .formats = ATMEL_SSC_FORMATS,},
                .ops = &atmel_ssc_dai_ops,
-               .private_data = &ssc_info[2],
        },
 #endif
 };
-EXPORT_SYMBOL_GPL(atmel_ssc_dai);
 
-static int __init atmel_ssc_modinit(void)
+static __devinit int asoc_ssc_probe(struct platform_device *pdev)
+{
+       BUG_ON(pdev->id < 0);
+       BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
+       return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
+}
+
+static int __devexit asoc_ssc_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver asoc_ssc_driver = {
+       .driver = {
+                       .name = "atmel-ssc-dai",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = asoc_ssc_probe,
+       .remove = __devexit_p(asoc_ssc_remove),
+};
+
+/**
+ * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
+ */
+int atmel_ssc_set_audio(int ssc_id)
+{
+       struct ssc_device *ssc;
+       static struct platform_device *dma_pdev;
+       struct platform_device *ssc_pdev;
+       int ret;
+
+       if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
+               return -EINVAL;
+
+       /* Allocate a dummy device for DMA if we don't have one already */
+       if (!dma_pdev) {
+               dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
+               if (!dma_pdev)
+                       return -ENOMEM;
+
+               ret = platform_device_add(dma_pdev);
+               if (ret < 0) {
+                       platform_device_put(dma_pdev);
+                       dma_pdev = NULL;
+                       return ret;
+               }
+       }
+
+       ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
+       if (!ssc_pdev) {
+               ssc_free(ssc);
+               return -ENOMEM;
+       }
+
+       /* If we can grab the SSC briefly to parent the DAI device off it */
+       ssc = ssc_request(ssc_id);
+       if (IS_ERR(ssc))
+               pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
+                       PTR_ERR(ssc));
+       else
+               ssc_pdev->dev.parent = &(ssc->pdev->dev);
+       ssc_free(ssc);
+
+       ret = platform_device_add(ssc_pdev);
+       if (ret < 0)
+               platform_device_put(ssc_pdev);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
+
+static int __init snd_atmel_ssc_init(void)
 {
-       return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+       return platform_driver_register(&asoc_ssc_driver);
 }
-module_init(atmel_ssc_modinit);
+module_init(snd_atmel_ssc_init);
 
-static void __exit atmel_ssc_modexit(void)
+static void __exit snd_atmel_ssc_exit(void)
 {
-       snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
+       platform_driver_unregister(&asoc_ssc_driver);
 }
-module_exit(atmel_ssc_modexit);
+module_exit(snd_atmel_ssc_exit);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
index 391135f..5d4f0f9 100644 (file)
@@ -116,6 +116,7 @@ struct atmel_ssc_info {
        struct atmel_pcm_dma_params *dma_params[2];
        struct atmel_ssc_state ssc_state;
 };
-extern struct snd_soc_dai atmel_ssc_dai[];
+
+int atmel_ssc_set_audio(int ssc);
 
 #endif /* _AT91_SSC_DAI_H */
index 9df4c68..5f4e59f 100644 (file)
@@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
        struct snd_pcm_hw_params *params,
        struct snd_soc_dai *cpu_dai)
 {
-       struct at32_ssc_info *ssc_p = cpu_dai->private_data;
+       struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssc_device *ssc = ssc_p->ssc;
        struct ssc_clock_data cd;
        unsigned int rate, width_bits, channels;
@@ -131,9 +131,9 @@ static int playpaq_wm8510_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 at32_ssc_info *ssc_p = cpu_dai->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssc_device *ssc = ssc_p->ssc;
        unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
        int ret;
@@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = {
 
 
 
-static int playpaq_wm8510_init(struct snd_soc_codec *codec)
+static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int i;
 
        /*
@@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
 
 
        /* Make CSB show PLL rate */
-       snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV,
+       snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
                                       WM8510_OPCLKDIV_1 | 4);
 
        return 0;
@@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link playpaq_wm8510_dai = {
        .name = "WM8510",
        .stream_name = "WM8510 PCM",
-       .cpu_dai = &at32_ssc_dai[0],
-       .codec_dai = &wm8510_dai,
+       .cpu_dai_name= "atmel-ssc-dai.0",
+       .platform_name = "atmel-pcm-audio",
+       .codec_name = "wm8510-codec.0-0x1a",
+       .codec_dai_name = "wm8510-hifi",
        .init = playpaq_wm8510_init,
        .ops = &playpaq_wm8510_ops,
 };
@@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
 
 static struct snd_soc_card snd_soc_playpaq = {
        .name = "LRS_PlayPaq_WM8510",
-       .platform = &at32_soc_platform,
        .dai_link = &playpaq_wm8510_dai,
        .num_links = 1,
 };
 
-
-
-static struct wm8510_setup_data playpaq_wm8510_setup = {
-       .i2c_bus = 0,
-       .i2c_address = 0x1a,
-};
-
-
-
-static struct snd_soc_device playpaq_wm8510_snd_devdata = {
-       .card = &snd_soc_playpaq,
-       .codec_dev = &soc_codec_dev_wm8510,
-       .codec_data = &playpaq_wm8510_setup,
-};
-
 static struct platform_device *playpaq_snd_device;
 
 
 static int __init playpaq_asoc_init(void)
 {
        int ret = 0;
-       struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
-       struct ssc_device *ssc = NULL;
-
-
-       /*
-        * Request SSC device
-        */
-       ssc = ssc_request(0);
-       if (IS_ERR(ssc)) {
-               ret = PTR_ERR(ssc);
-               goto err_ssc;
-       }
-       ssc_p->ssc = ssc;
-
 
        /*
         * Configure MCLK for WM8510
@@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void)
                goto err_device_alloc;
        }
 
-       platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata);
-       playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
+       platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
 
        ret = platform_device_add(playpaq_snd_device);
        if (ret) {
@@ -468,25 +440,12 @@ err_pll0:
                clk_put(_gclk0);
                _gclk0 = NULL;
        }
-err_gclk0:
-       ssc_free(ssc);
-err_ssc:
        return ret;
 }
 
 
 static void __exit playpaq_asoc_exit(void)
 {
-       struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
-       struct ssc_device *ssc;
-
-       if (ssc_p != NULL) {
-               ssc = ssc_p->ssc;
-               if (ssc != NULL)
-                       ssc_free(ssc);
-               ssc_p->ssc = NULL;
-       }
-
        if (_gclk0 != NULL) {
                clk_put(_gclk0);
                _gclk0 = NULL;
index e028744..293569d 100644 (file)
@@ -69,8 +69,8 @@ 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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* set codec DAI configuration */
@@ -136,16 +136,17 @@ static const struct snd_soc_dapm_route intercon[] = {
 /*
  * Logic for a wm8731 as connected on a at91sam9g20ek board.
  */
-static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
+static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_dai *codec_dai = &codec->dai[0];
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
        printk(KERN_DEBUG
                        "at91sam9g20ek_wm8731 "
                        ": at91sam9g20ek_wm8731_init() called\n");
 
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
                MCLK_RATE, SND_SOC_CLOCK_IN);
        if (ret < 0) {
                printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
@@ -179,37 +180,37 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link at91sam9g20ek_dai = {
        .name = "WM8731",
        .stream_name = "WM8731 PCM",
-       .cpu_dai = &atmel_ssc_dai[0],
-       .codec_dai = &wm8731_dai,
+       .cpu_dai_name = "atmel-ssc-dai.0",
+       .codec_dai_name = "wm8731-hifi",
        .init = at91sam9g20ek_wm8731_init,
+       .platform_name = "atmel-pcm-audio",
+       .codec_name = "wm8731-codec.0-001b",
        .ops = &at91sam9g20ek_ops,
 };
 
 static struct snd_soc_card snd_soc_at91sam9g20ek = {
        .name = "AT91SAMG20-EK",
-       .platform = &atmel_soc_platform,
        .dai_link = &at91sam9g20ek_dai,
        .num_links = 1,
        .set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct snd_soc_device at91sam9g20ek_snd_devdata = {
-       .card = &snd_soc_at91sam9g20ek,
-       .codec_dev = &soc_codec_dev_wm8731,
-};
-
 static struct platform_device *at91sam9g20ek_snd_device;
 
 static int __init at91sam9g20ek_init(void)
 {
-       struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
-       struct ssc_device *ssc = NULL;
        struct clk *pllb;
        int ret;
 
        if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
                return -ENODEV;
 
+       ret = atmel_ssc_set_audio(0);
+       if (ret != 0) {
+               pr_err("Failed to set SSC 0 for audio: %d\n", ret);
+               return ret;
+       }
+
        /*
         * Codec MCLK is supplied by PCK0 - set it up.
         */
@@ -235,18 +236,6 @@ static int __init at91sam9g20ek_init(void)
 
        clk_set_rate(mclk, MCLK_RATE);
 
-       /*
-        * Request SSC device
-        */
-       ssc = ssc_request(0);
-       if (IS_ERR(ssc)) {
-               printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
-               ret = PTR_ERR(ssc);
-               ssc = NULL;
-               goto err_ssc;
-       }
-       ssc_p->ssc = ssc;
-
        at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
        if (!at91sam9g20ek_snd_device) {
                printk(KERN_ERR "ASoC: Platform device allocation failed\n");
@@ -254,8 +243,7 @@ static int __init at91sam9g20ek_init(void)
        }
 
        platform_set_drvdata(at91sam9g20ek_snd_device,
-                       &at91sam9g20ek_snd_devdata);
-       at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
+                       &snd_soc_at91sam9g20ek);
 
        ret = platform_device_add(at91sam9g20ek_snd_device);
        if (ret) {
@@ -265,9 +253,6 @@ static int __init at91sam9g20ek_init(void)
 
        return ret;
 
-err_ssc:
-       ssc_free(ssc);
-       ssc_p->ssc = NULL;
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
@@ -277,16 +262,6 @@ err:
 
 static void __exit at91sam9g20ek_exit(void)
 {
-       struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
-       struct ssc_device *ssc;
-
-       if (ssc_p != NULL) {
-               ssc = ssc_p->ssc;
-               if (ssc != NULL)
-                       ssc_free(ssc);
-               ssc_p->ssc = NULL;
-       }
-
        platform_device_unregister(at91sam9g20ek_snd_device);
        at91sam9g20ek_snd_device = NULL;
        clk_put(mclk);
index 23349de..e3d2835 100644 (file)
@@ -46,8 +46,8 @@ static int afeb9260_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
@@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic Jack"},
 };
 
-static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
+static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* Add afeb9260 specific widgets */
        snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link afeb9260_dai = {
        .name = "TLV320AIC23",
        .stream_name = "AIC23",
-       .cpu_dai = &atmel_ssc_dai[0],
-       .codec_dai = &tlv320aic23_dai,
+       .cpu_dai_name = "atmel-ssc-dai.0",
+       .codec_dai_name = "tlv320aic23-hifi",
+       .platform_name = "atmel_pcm-audio",
+       .codec_name = "tlv320aic23-codec.0-0x1a",
        .init = afeb9260_tlv320aic23_init,
        .ops = &afeb9260_ops,
 };
@@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_machine_afeb9260 = {
        .name = "AFEB9260",
-       .platform = &atmel_soc_platform,
        .dai_link = &afeb9260_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device afeb9260_snd_devdata = {
-       .card = &snd_soc_machine_afeb9260,
-       .codec_dev = &soc_codec_dev_tlv320aic23,
-};
-
 static struct platform_device *afeb9260_snd_device;
 
 static int __init afeb9260_soc_init(void)
 {
        int err;
        struct device *dev;
-       struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data;
-       struct ssc_device *ssc = NULL;
 
        if (!(machine_is_afeb9260()))
                return -ENODEV;
 
-       ssc = ssc_request(0);
-       if (IS_ERR(ssc)) {
-               printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
-               err = PTR_ERR(ssc);
-               ssc = NULL;
-               goto err_ssc;
-       }
-       ssc_p->ssc = ssc;
 
        afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
        if (!afeb9260_snd_device) {
@@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata);
-       afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev;
+       platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);
        err = platform_device_add(afeb9260_snd_device);
        if (err)
                goto err1;
@@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void)
 err1:
        platform_device_del(afeb9260_snd_device);
        platform_device_put(afeb9260_snd_device);
-err_ssc:
        return err;
-
 }
 
 static void __exit afeb9260_soc_exit(void)
index cdf7be1..b62fcd3 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
 #include <asm/mach-db1x00/bcsr.h>
 
-#include "../codecs/ac97.h"
 #include "../codecs/wm8731.h"
 #include "psc.h"
 
 static struct snd_soc_dai_link db1200_ac97_dai = {
        .name           = "AC97",
        .stream_name    = "AC97 HiFi",
-       .cpu_dai        = &au1xpsc_ac97_dai,
-       .codec_dai      = &ac97_dai,
+       .codec_dai_name = "ac97-hifi",
+       .cpu_dai_name   = "au1xpsc_ac97.1",
+       .platform_name  = "au1xpsc-pcm.1",
+       .codec_name     = "ac97-codec.1",
 };
 
 static struct snd_soc_card db1200_ac97_machine = {
        .name           = "DB1200_AC97",
        .dai_link       = &db1200_ac97_dai,
        .num_links      = 1,
-       .platform       = &au1xpsc_soc_platform,
-};
-
-static struct snd_soc_device db1200_ac97_devdata = {
-       .card           = &db1200_ac97_machine,
-       .codec_dev      = &soc_codec_dev_ac97,
 };
 
 /*-------------------------  I2S PART  ---------------------------*/
@@ -49,12 +44,12 @@ static struct snd_soc_device db1200_ac97_devdata = {
 static int db1200_i2s_startup(struct snd_pcm_substream *substream)
 {
        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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* WM8731 has its own 12MHz crystal */
-       snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+       snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
                                12000000, SND_SOC_CLOCK_IN);
 
        /* codec is bitclock and lrclk master */
@@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = {
 static struct snd_soc_dai_link db1200_i2s_dai = {
        .name           = "WM8731",
        .stream_name    = "WM8731 PCM",
-       .cpu_dai        = &au1xpsc_i2s_dai,
-       .codec_dai      = &wm8731_dai,
+       .codec_dai_name = "wm8731-hifi",
+       .cpu_dai_name   = "au1xpsc_i2s.1",
+       .platform_name  = "au1xpsc-pcm.1",
+       .codec_name     = "wm8731-codec.0-001b",
        .ops            = &db1200_i2s_wm8731_ops,
 };
 
@@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = {
        .name           = "DB1200_I2S",
        .dai_link       = &db1200_i2s_dai,
        .num_links      = 1,
-       .platform       = &au1xpsc_soc_platform,
-};
-
-static struct snd_soc_device db1200_i2s_devdata = {
-       .card           = &db1200_i2s_machine,
-       .codec_dev      = &soc_codec_dev_wm8731,
 };
 
 /*-------------------------  COMMON PART  ---------------------------*/
@@ -106,18 +97,16 @@ static int __init db1200_audio_load(void)
        int ret;
 
        ret = -ENOMEM;
-       db1200_asoc_dev = platform_device_alloc("soc-audio", -1);
+       db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */
        if (!db1200_asoc_dev)
                goto out;
 
        /* DB1200 board setup set PSC1MUX to preferred audio device */
        if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
-               platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata);
+               platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
        else
-               platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata);
+               platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
 
-       db1200_ac97_devdata.dev = &db1200_asoc_dev->dev;
-       db1200_i2s_devdata.dev = &db1200_asoc_dev->dev;
        ret = platform_device_add(db1200_asoc_dev);
 
        if (ret) {
index 6d9f4c6..10fdd28 100644 (file)
@@ -10,9 +10,6 @@
  *
  * DMA glue for Au1x-PSC audio.
  *
- * NOTE: all of these drivers can only work with a SINGLE instance
- *      of a PSC. Multiple independent audio devices are impossible
- *      with ASoC v1.
  */
 
 
@@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata {
        int msbits;
 };
 
-/* instance data. There can be only one, MacLeod!!!! */
-static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
-
 /*
  * These settings are somewhat okay, at least on my machine audio plays
  * almost skip-free. Especially the 64kB buffer seems to help a LOT.
@@ -199,6 +193,14 @@ out:
        return 0;
 }
 
+static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss)
+{
+       struct snd_soc_pcm_runtime *rtd = ss->private_data;
+       struct au1xpsc_audio_dmadata *pcd =
+                               snd_soc_platform_get_drvdata(rtd->platform);
+       return &pcd[SUBSTREAM_TYPE(ss)];
+}
+
 static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params)
 {
@@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
                goto out;
 
        stype = SUBSTREAM_TYPE(substream);
-       pcd = au1xpsc_audio_pcmdma[stype];
+       pcd = to_dmadata(substream);
 
        DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
            "runtime->min_align %d\n",
@@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
 
 static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
 {
-       struct au1xpsc_audio_dmadata *pcd =
-                       au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
+       struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
 
        au1xxx_dbdma_reset(pcd->ddma_chan);
 
@@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
 
 static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan;
+       u32 c = to_dmadata(substream)->ddma_chan;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 static snd_pcm_uframes_t
 au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
 {
-       return bytes_to_frames(substream->runtime,
-               au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
+       return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos);
 }
 
 static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
@@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
 
 static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
 {
-       au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]);
+       au1x_pcm_dbdma_free(to_dmadata(substream));
        return 0;
 }
 
@@ -329,42 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card,
        return 0;
 }
 
-static int au1xpsc_pcm_probe(struct platform_device *pdev)
-{
-       if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
-               return -ENODEV;
-
-       return 0;
-}
-
-static int au1xpsc_pcm_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
 /* au1xpsc audio platform */
-struct snd_soc_platform au1xpsc_soc_platform = {
-       .name           = "au1xpsc-pcm-dbdma",
-       .probe          = au1xpsc_pcm_probe,
-       .remove         = au1xpsc_pcm_remove,
-       .pcm_ops        = &au1xpsc_pcm_ops,
+struct snd_soc_platform_driver au1xpsc_soc_platform = {
+       .ops            = &au1xpsc_pcm_ops,
        .pcm_new        = au1xpsc_pcm_new,
        .pcm_free       = au1xpsc_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
 
 static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
 {
+       struct au1xpsc_audio_dmadata *dmadata;
        struct resource *r;
        int ret;
 
-       if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX])
-               return -EBUSY;
-
-       /* TX DMA */
-       au1xpsc_audio_pcmdma[PCM_TX]
-               = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
-       if (!au1xpsc_audio_pcmdma[PCM_TX])
+       dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
+       if (!dmadata)
                return -ENOMEM;
 
        r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -372,47 +351,33 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
                ret = -ENODEV;
                goto out1;
        }
-       (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start;
+       dmadata[PCM_TX].ddma_id = r->start;
 
        /* RX DMA */
-       au1xpsc_audio_pcmdma[PCM_RX]
-               = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
-       if (!au1xpsc_audio_pcmdma[PCM_RX])
-               return -ENOMEM;
-
        r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
        if (!r) {
                ret = -ENODEV;
-               goto out2;
+               goto out1;
        }
-       (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
+       dmadata[PCM_RX].ddma_id = r->start;
+
+       platform_set_drvdata(pdev, dmadata);
 
-       ret = snd_soc_register_platform(&au1xpsc_soc_platform);
+       ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
        if (!ret)
                return ret;
 
-out2:
-       kfree(au1xpsc_audio_pcmdma[PCM_RX]);
-       au1xpsc_audio_pcmdma[PCM_RX] = NULL;
 out1:
-       kfree(au1xpsc_audio_pcmdma[PCM_TX]);
-       au1xpsc_audio_pcmdma[PCM_TX] = NULL;
+       kfree(dmadata);
        return ret;
 }
 
 static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
 {
-       int i;
+       struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev);
 
-       snd_soc_unregister_platform(&au1xpsc_soc_platform);
-
-       for (i = 0; i < 2; i++) {
-               if (au1xpsc_audio_pcmdma[i]) {
-                       au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
-                       kfree(au1xpsc_audio_pcmdma[i]);
-                       au1xpsc_audio_pcmdma[i] = NULL;
-               }
-       }
+       snd_soc_unregister_platform(&pdev->dev);
+       kfree(dmadata);
 
        return 0;
 }
@@ -428,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = {
 
 static int __init au1xpsc_audio_dbdma_load(void)
 {
-       au1xpsc_audio_pcmdma[PCM_TX] = NULL;
-       au1xpsc_audio_pcmdma[PCM_RX] = NULL;
        return platform_driver_register(&au1xpsc_pcm_driver);
 }
 
@@ -467,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
        res[1].start = res[1].end = id[1];
        res[0].flags = res[1].flags = IORESOURCE_DMA;
 
-       pd = platform_device_alloc("au1xpsc-pcm", -1);
+       pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
        if (!pd)
                goto out;
 
index d14a5a9..d0db66f 100644 (file)
@@ -10,9 +10,6 @@
  *
  * Au1xxx-PSC AC97 glue.
  *
- * NOTE: all of these drivers can only work with a SINGLE instance
- *      of a PSC. Multiple independent audio devices are impossible
- *      with ASoC v1.
  */
 
 #include <linux/init.h>
 /* instance data. There can be only one, MacLeod!!!! */
 static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
 
+#if 0
+
+/* this could theoretically work, but ac97->bus->card->private_data can be NULL
+ * when snd_ac97_mixer() is called; I don't know if the rest further down the
+ * chain are always valid either.
+ */
+static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)
+{
+       struct snd_soc_card *c = x->bus->card->private_data;
+       return snd_soc_dai_get_drvdata(c->rtd->cpu_dai);
+}
+
+#else
+
+#define ac97_to_pscdata(x)     au1xpsc_ac97_workdata
+
+#endif
+
 /* AC97 controller reads codec register */
 static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
                                        unsigned short reg)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
        unsigned short retry, tmo;
        unsigned long data;
 
@@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
 static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
                                unsigned short val)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
        unsigned int tmo, retry;
 
        au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
@@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 /* AC97 controller asserts a warm reset */
 static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
 
        au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
        au_sync();
@@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
 
 static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
        int i;
 
        /* disable PSC during cold reset */
@@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
        unsigned long r, ro, stat;
        int chans, t, stype = SUBSTREAM_TYPE(substream);
 
@@ -283,8 +293,7 @@ out:
 static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
-       /* FIXME */
-       struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
        int ret, stype = SUBSTREAM_TYPE(substream);
 
        ret = 0;
@@ -315,27 +324,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
        return ret;
 }
 
-static int au1xpsc_ac97_probe(struct platform_device *pdev,
-                             struct snd_soc_dai *dai)
+static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
 {
        return au1xpsc_ac97_workdata ? 0 : -ENODEV;
 }
 
-static void au1xpsc_ac97_remove(struct platform_device *pdev,
-                               struct snd_soc_dai *dai)
-{
-}
-
 static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
        .trigger        = au1xpsc_ac97_trigger,
        .hw_params      = au1xpsc_ac97_hw_params,
 };
 
-struct snd_soc_dai au1xpsc_ac97_dai = {
-       .name                   = "au1xpsc_ac97",
+static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
        .ac97_control           = 1,
        .probe                  = au1xpsc_ac97_probe,
-       .remove                 = au1xpsc_ac97_remove,
        .playback = {
                .rates          = AC97_RATES,
                .formats        = AC97_FMTS,
@@ -350,7 +351,6 @@ struct snd_soc_dai au1xpsc_ac97_dai = {
        },
        .ops = &au1xpsc_ac97_dai_ops,
 };
-EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
 
 static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
 {
@@ -359,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
        unsigned long sel;
        struct au1xpsc_audio_data *wd;
 
-       if (au1xpsc_ac97_workdata)
-               return -EBUSY;
-
        wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
        if (!wd)
                return -ENOMEM;
@@ -395,18 +392,24 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
        au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
        au_sync();
 
-       ret = snd_soc_register_dai(&au1xpsc_ac97_dai);
+       /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
+       memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
+              sizeof(struct snd_soc_dai_driver));
+       wd->dai_drv.name = dev_name(&pdev->dev);
+
+       platform_set_drvdata(pdev, wd);
+
+       ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
        if (ret)
                goto out1;
 
        wd->dmapd = au1xpsc_pcm_add(pdev);
        if (wd->dmapd) {
-               platform_set_drvdata(pdev, wd);
-               au1xpsc_ac97_workdata = wd;     /* MDEV */
+               au1xpsc_ac97_workdata = wd;
                return 0;
        }
 
-       snd_soc_unregister_dai(&au1xpsc_ac97_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 out1:
        release_mem_region(r->start, resource_size(r));
 out0:
@@ -422,7 +425,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
        if (wd->dmapd)
                au1xpsc_pcm_destroy(wd->dmapd);
 
-       snd_soc_unregister_dai(&au1xpsc_ac97_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
        /* disable PSC completely */
        au_writel(0, AC97_CFG(wd));
index 6083fe7..fca0912 100644 (file)
@@ -10,9 +10,6 @@
  *
  * Au1xxx-PSC I2S glue.
  *
- * NOTE: all of these drivers can only work with a SINGLE instance
- *      of a PSC. Multiple independent audio devices are impossible
- *      with ASoC v1.
  * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
  */
 
        ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
 
 
-/* instance data. There can be only one, MacLeod!!!! */
-static struct au1xpsc_audio_data *au1xpsc_i2s_workdata;
-
 static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                               unsigned int fmt)
 {
-       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned long ct;
        int ret;
 
@@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
-       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
 
        int cfgbits;
        unsigned long stat;
@@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
 static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
-       struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
+       struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
        int ret, stype = SUBSTREAM_TYPE(substream);
 
        switch (cmd) {
@@ -263,27 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        return ret;
 }
 
-static int au1xpsc_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
-{
-       return  au1xpsc_i2s_workdata ? 0 : -ENODEV;
-}
-
-static void au1xpsc_i2s_remove(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
-{
-}
-
 static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
        .trigger        = au1xpsc_i2s_trigger,
        .hw_params      = au1xpsc_i2s_hw_params,
        .set_fmt        = au1xpsc_i2s_set_fmt,
 };
 
-struct snd_soc_dai au1xpsc_i2s_dai = {
-       .name                   = "au1xpsc_i2s",
-       .probe                  = au1xpsc_i2s_probe,
-       .remove                 = au1xpsc_i2s_remove,
+static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
        .playback = {
                .rates          = AU1XPSC_I2S_RATES,
                .formats        = AU1XPSC_I2S_FMTS,
@@ -298,7 +278,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
        },
        .ops = &au1xpsc_i2s_dai_ops,
 };
-EXPORT_SYMBOL(au1xpsc_i2s_dai);
 
 static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
@@ -307,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
        int ret;
        struct au1xpsc_audio_data *wd;
 
-       if (au1xpsc_i2s_workdata)
-               return -EBUSY;
-
        wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
        if (!wd)
                return -ENOMEM;
@@ -346,19 +322,23 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
         * time out.
         */
 
-       ret = snd_soc_register_dai(&au1xpsc_i2s_dai);
+       /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */
+       memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template,
+              sizeof(struct snd_soc_dai_driver));
+       wd->dai_drv.name = dev_name(&pdev->dev);
+
+       platform_set_drvdata(pdev, wd);
+
+       ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
        if (ret)
                goto out1;
 
        /* finally add the DMA device for this PSC */
        wd->dmapd = au1xpsc_pcm_add(pdev);
-       if (wd->dmapd) {
-               platform_set_drvdata(pdev, wd);
-               au1xpsc_i2s_workdata = wd;
+       if (wd->dmapd)
                return 0;
-       }
 
-       snd_soc_unregister_dai(&au1xpsc_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 out1:
        release_mem_region(r->start, resource_size(r));
 out0:
@@ -374,7 +354,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
        if (wd->dmapd)
                au1xpsc_pcm_destroy(wd->dmapd);
 
-       snd_soc_unregister_dai(&au1xpsc_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
        au_writel(0, I2S_CFG(wd));
        au_sync();
@@ -385,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
        release_mem_region(r->start, resource_size(r));
        kfree(wd);
 
-       au1xpsc_i2s_workdata = NULL;    /* MDEV */
-
        return 0;
 }
 
@@ -446,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = {
 
 static int __init au1xpsc_i2s_load(void)
 {
-       au1xpsc_i2s_workdata = NULL;
        return platform_driver_register(&au1xpsc_i2s_driver);
 }
 
index 093775d..b30eadd 100644 (file)
@@ -8,19 +8,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * NOTE: all of these drivers can only work with a SINGLE instance
- *      of a PSC. Multiple independent audio devices are impossible
- *      with ASoC v1.
  */
 
 #ifndef _AU1X_PCM_H
 #define _AU1X_PCM_H
 
-extern struct snd_soc_dai au1xpsc_ac97_dai;
-extern struct snd_soc_dai au1xpsc_i2s_dai;
-extern struct snd_soc_platform au1xpsc_soc_platform;
-extern struct snd_ac97_bus_ops soc_ac97_ops;
-
 /* DBDMA helpers */
 extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
 extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
@@ -31,6 +23,8 @@ struct au1xpsc_audio_data {
        unsigned long cfg;
        unsigned long rate;
 
+       struct snd_soc_dai_driver dai_drv;
+
        unsigned long pm[2];
        struct mutex lock;
        struct platform_device *dmapd;
index 5e7aacf..5a2fd8a 100644 (file)
@@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
        return ret;
 }
 
-struct snd_soc_platform bf5xx_ac97_soc_platform = {
-       .name           = "bf5xx-audio",
-       .pcm_ops        = &bf5xx_pcm_ac97_ops,
+static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
+       .ops                    = &bf5xx_pcm_ac97_ops,
        .pcm_new        = bf5xx_pcm_ac97_new,
        .pcm_free       = bf5xx_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
 
-static int __init bfin_ac97_init(void)
+static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
 }
-module_init(bfin_ac97_init);
 
-static void __exit bfin_ac97_exit(void)
+static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver bf5xx_pcm_driver = {
+       .driver = {
+                       .name = "bf5xx-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = bf5xx_soc_platform_probe,
+       .remove = __devexit_p(bf5xx_soc_platform_remove),
+};
+
+static int __init snd_bf5xx_pcm_init(void)
+{
+       return platform_driver_register(&bf5xx_pcm_driver);
+}
+module_init(snd_bf5xx_pcm_init);
+
+static void __exit snd_bf5xx_pcm_exit(void)
+{
+       platform_driver_unregister(&bf5xx_pcm_driver);
 }
-module_exit(bfin_ac97_exit);
+module_exit(snd_bf5xx_pcm_exit);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
index 350125a..d324d58 100644 (file)
@@ -23,7 +23,4 @@ struct bf5xx_gpio {
        u32 frm;
 };
 
-/* platform data */
-extern struct snd_soc_platform bf5xx_ac97_soc_platform;
-
 #endif
index c0eba51..c5f856e 100644 (file)
@@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
 #ifdef CONFIG_PM
 static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
 {
-       struct sport_device *sport = dai->private_data;
+       struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
        if (!dai->active)
@@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
 static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
 {
        int ret;
-       struct sport_device *sport = dai->private_data;
+       struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
        if (!dai->active)
@@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
 #define bf5xx_ac97_resume      NULL
 #endif
 
-static int bf5xx_ac97_probe(struct platform_device *pdev,
-                           struct snd_soc_dai *dai)
+static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
 {
        int ret = 0;
        cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
@@ -379,8 +378,7 @@ peripheral_err:
        return ret;
 }
 
-static void bf5xx_ac97_remove(struct platform_device *pdev,
-                             struct snd_soc_dai *dai)
+static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
 {
        free_page((unsigned long)cmd_count);
        cmd_count = NULL;
@@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
 #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
        gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
 #endif
+       return 0;
 }
 
-struct snd_soc_dai bfin_ac97_dai = {
-       .name = "bf5xx-ac97",
-       .id = 0,
+struct snd_soc_dai_driver bfin_ac97_dai = {
        .ac97_control = 1,
        .probe = bf5xx_ac97_probe,
        .remove = bf5xx_ac97_remove,
@@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = {
 };
 EXPORT_SYMBOL_GPL(bfin_ac97_dai);
 
+static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
+}
+
+static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver asoc_bfin_ac97_driver = {
+       .driver = {
+                       .name = "bfin-ac97",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = asoc_bfin_ac97_probe,
+       .remove = __devexit_p(asoc_bfin_ac97_remove),
+};
+
 static int __init bfin_ac97_init(void)
 {
-       return snd_soc_register_dai(&bfin_ac97_dai);
+       return platform_driver_register(&asoc_bfin_ac97_driver);
 }
 module_init(bfin_ac97_init);
 
 static void __exit bfin_ac97_exit(void)
 {
-       snd_soc_unregister_dai(&bfin_ac97_dai);
+       platform_driver_unregister(&asoc_bfin_ac97_driver);
 }
 module_exit(bfin_ac97_exit);
 
+
 MODULE_AUTHOR("Roy Huang");
 MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
 MODULE_LICENSE("GPL");
index a1f97dd..15c635e 100644 (file)
@@ -50,8 +50,6 @@ struct ac97_frame {
 #define TAG_PCM_SR             0x0080
 #define TAG_PCM_LFE            0x0040
 
-extern struct snd_soc_dai bfin_ac97_dai;
-
 void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
                size_t count, unsigned int chan_mask);
 
index 0f45a3f..2394bff 100644 (file)
@@ -40,9 +40,9 @@ 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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
-       cpu_dai->private_data = sport_handle;
+       snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
        return 0;
 }
 
@@ -50,8 +50,8 @@ 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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
        int ret = 0;
        /* set cpu DAI configuration */
@@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
 static struct snd_soc_dai_link bf5xx_ad1836_dai = {
        .name = "ad1836",
        .stream_name = "AD1836",
-       .cpu_dai = &bf5xx_tdm_dai,
-       .codec_dai = &ad1836_dai,
+       .cpu_dai_name = "bf5xx-tdm",
+       .codec_dai_name = "ad1836-hifi",
+       .platform_name = "bf5xx-tdm-pcm-audio",
+       .codec_name = "ad1836-codec.0",
        .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)
@@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void)
        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;
+       platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836);
        ret = platform_device_add(bfxx_ad1836_snd_device);
 
        if (ret)
index b8c9060..e4a6253 100644 (file)
@@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x;
 static int bf5xx_ad193x_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
-       cpu_dai->private_data = sport_handle;
+       snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
        return 0;
 }
 
@@ -59,8 +59,8 @@ static int bf5xx_ad193x_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
        int ret = 0;
        /* set cpu DAI configuration */
@@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = {
 static struct snd_soc_dai_link bf5xx_ad193x_dai = {
        .name = "ad193x",
        .stream_name = "AD193X",
-       .cpu_dai = &bf5xx_tdm_dai,
-       .codec_dai = &ad193x_dai,
+       .cpu_dai_name = "bf5xx-tdm",
+       .codec_dai_name ="ad193x-hifi",
+       .platform_name = "bf5xx-tdm-pcm-audio",
+       .codec_name = "ad193x-codec.5",
        .ops = &bf5xx_ad193x_ops,
 };
 
 static struct snd_soc_card bf5xx_ad193x = {
        .name = "bf5xx_ad193x",
-       .platform = &bf5xx_tdm_soc_platform,
        .dai_link = &bf5xx_ad193x_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
-       .card = &bf5xx_ad193x,
-       .codec_dev = &soc_codec_dev_ad193x,
-};
-
 static struct platform_device *bfxx_ad193x_snd_device;
 
 static int __init bf5xx_ad193x_init(void)
@@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void)
        if (!bfxx_ad193x_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata);
-       bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
+       platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x);
        ret = platform_device_add(bfxx_ad193x_snd_device);
 
        if (ret)
index 92f7c32..d57c9c9 100644 (file)
@@ -56,10 +56,10 @@ static struct snd_soc_card bf5xx_board;
 static int bf5xx_board_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        pr_debug("%s enter\n", __func__);
-       cpu_dai->private_data = sport_handle;
+       snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
        return 0;
 }
 
@@ -70,23 +70,19 @@ static struct snd_soc_ops bf5xx_board_ops = {
 static struct snd_soc_dai_link bf5xx_board_dai = {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &bfin_ac97_dai,
-       .codec_dai = &ad1980_dai,
+       .cpu_dai_name = "bfin-ac97",
+       .codec_dai_name = "ad1980-hifi",
+       .platform_name = "bfin-pcm-audio",
+       .codec_name = "ad1980-codec",
        .ops = &bf5xx_board_ops,
 };
 
 static struct snd_soc_card bf5xx_board = {
        .name = "bf5xx-board",
-       .platform = &bf5xx_ac97_soc_platform,
        .dai_link = &bf5xx_board_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device bf5xx_board_snd_devdata = {
-       .card = &bf5xx_board,
-       .codec_dev = &soc_codec_dev_ad1980,
-};
-
 static struct platform_device *bf5xx_board_snd_device;
 
 static int __init bf5xx_board_init(void)
@@ -97,8 +93,7 @@ static int __init bf5xx_board_init(void)
        if (!bf5xx_board_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata);
-       bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev;
+       platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board);
        ret = platform_device_add(bf5xx_board_snd_device);
 
        if (ret)
index 9825b71..900ced5 100644 (file)
@@ -47,7 +47,6 @@
 #include "../codecs/ad73311.h"
 #include "bf5xx-sport.h"
 #include "bf5xx-i2s-pcm.h"
-#include "bf5xx-i2s.h"
 
 #if CONFIG_SND_BF5XX_SPORT_NUM == 0
 #define bfin_write_SPORT_TCR1  bfin_write_SPORT0_TCR1
@@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev)
 static int bf5xx_ad73311_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        pr_debug("%s enter\n", __func__);
-       cpu_dai->private_data = sport_handle;
+       snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
        return 0;
 }
 
@@ -161,7 +160,7 @@ static int bf5xx_ad73311_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 *cpu_dai = rtd->cpu_dai;
        int ret = 0;
 
        pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
@@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = {
 static struct snd_soc_dai_link bf5xx_ad73311_dai = {
        .name = "ad73311",
        .stream_name = "AD73311",
-       .cpu_dai = &bf5xx_i2s_dai,
-       .codec_dai = &ad73311_dai,
+       .cpu_dai_name = "bf5xx-i2s",
+       .codec_dai_name = "ad73311-hifi",
+       .platform_name = "bfin-pcm-audio",
+       .codec_name = "ad73311-codec",
        .ops = &bf5xx_ad73311_ops,
 };
 
 static struct snd_soc_card bf5xx_ad73311 = {
        .name = "bf5xx_ad73311",
-       .platform = &bf5xx_i2s_soc_platform,
        .probe = bf5xx_probe,
        .dai_link = &bf5xx_ad73311_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
-       .card = &bf5xx_ad73311,
-       .codec_dev = &soc_codec_dev_ad73311,
-};
-
 static struct platform_device *bf5xx_ad73311_snd_device;
 
 static int __init bf5xx_ad73311_init(void)
@@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void)
        if (!bf5xx_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;
+       platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311);
        ret = platform_device_add(bf5xx_ad73311_snd_device);
 
        if (ret)
index 1d2a1ad..890a0dc 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/dma.h>
 
 #include "bf5xx-i2s-pcm.h"
-#include "bf5xx-i2s.h"
 #include "bf5xx-sport.h"
 
 static void bf5xx_dma_irq(void *data)
@@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
        return ret;
 }
 
-struct snd_soc_platform bf5xx_i2s_soc_platform = {
-       .name           = "bf5xx-audio",
-       .pcm_ops        = &bf5xx_pcm_i2s_ops,
+static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
+       .ops            = &bf5xx_pcm_i2s_ops,
        .pcm_new        = bf5xx_pcm_i2s_new,
        .pcm_free       = bf5xx_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
 
-static int __init bfin_i2s_init(void)
+static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
 }
-module_init(bfin_i2s_init);
 
-static void __exit bfin_i2s_exit(void)
+static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver bfin_i2s_pcm_driver = {
+       .driver = {
+                       .name = "bfin-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = bfin_i2s_soc_platform_probe,
+       .remove = __devexit_p(bfin_i2s_soc_platform_remove),
+};
+
+static int __init snd_bfin_i2s_pcm_init(void)
+{
+       return platform_driver_register(&bfin_i2s_pcm_driver);
+}
+module_init(snd_bfin_i2s_pcm_init);
+
+static void __exit snd_bfin_i2s_pcm_exit(void)
+{
+       platform_driver_unregister(&bfin_i2s_pcm_driver);
 }
-module_exit(bfin_i2s_exit);
+module_exit(snd_bfin_i2s_pcm_exit);
 
 MODULE_AUTHOR("Cliff Cai");
 MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
index 4d4609a..0c2c5a6 100644 (file)
@@ -23,7 +23,4 @@ struct bf5xx_gpio {
        u32 frm;
 };
 
-/* platform data */
-extern struct snd_soc_platform bf5xx_i2s_soc_platform;
-
 #endif
index 3e6ada0..d453b1e 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/gpio.h>
 
 #include "bf5xx-sport.h"
-#include "bf5xx-i2s.h"
 
 struct bf5xx_i2s_port {
        u16 tcr1;
@@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
                bf5xx_i2s.configured = 0;
 }
 
-static int bf5xx_i2s_probe(struct platform_device *pdev,
-                          struct snd_soc_dai *dai)
+static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
 {
        pr_debug("%s enter\n", __func__);
        if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
@@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
        return 0;
 }
 
-static void bf5xx_i2s_remove(struct platform_device *pdev,
-                       struct snd_soc_dai *dai)
+static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
 {
        pr_debug("%s enter\n", __func__);
        peripheral_free_list(&sport_req[sport_num][0]);
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
 
-       if (dai->capture.active)
+       if (dai->capture_active)
                sport_rx_stop(sport_handle);
-       if (dai->playback.active)
+       if (dai->playback_active)
                sport_tx_stop(sport_handle);
        return 0;
 }
@@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
        .set_fmt        = bf5xx_i2s_set_dai_fmt,
 };
 
-struct snd_soc_dai bf5xx_i2s_dai = {
-       .name = "bf5xx-i2s",
-       .id = 0,
+static struct snd_soc_dai_driver bf5xx_i2s_dai = {
        .probe = bf5xx_i2s_probe,
        .remove = bf5xx_i2s_remove,
        .suspend = bf5xx_i2s_suspend,
@@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = {
                .formats = BF5XX_I2S_FORMATS,},
        .ops = &bf5xx_i2s_dai_ops,
 };
-EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
+
+static int bfin_i2s_drv_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
+}
+
+static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver bfin_i2s_driver = {
+       .probe = bfin_i2s_drv_probe,
+       .remove = __devexit_p(bfin_i2s_drv_remove),
+
+       .driver = {
+               .name = "bf5xx-i2s",
+               .owner = THIS_MODULE,
+       },
+};
 
 static int __init bfin_i2s_init(void)
 {
-       return snd_soc_register_dai(&bf5xx_i2s_dai);
+       return platform_driver_register(&bfin_i2s_driver);
 }
-module_init(bfin_i2s_init);
 
 static void __exit bfin_i2s_exit(void)
 {
-       snd_soc_unregister_dai(&bf5xx_i2s_dai);
+       platform_driver_unregister(&bfin_i2s_driver);
 }
+
+module_init(bfin_i2s_init);
 module_exit(bfin_i2s_exit);
 
 /* Module information */
diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h
deleted file mode 100644 (file)
index 264ecdc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * sound/soc/blackfin/bf5xx-i2s.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_I2S_H
-#define _BF5XX_I2S_H
-
-extern struct snd_soc_dai bf5xx_i2s_dai;
-
-#endif
index 3a00fa4..36f2769 100644 (file)
 #include "../codecs/ssm2602.h"
 #include "bf5xx-sport.h"
 #include "bf5xx-i2s-pcm.h"
-#include "bf5xx-i2s.h"
 
 static struct snd_soc_card bf5xx_ssm2602;
 
 static int bf5xx_ssm2602_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        pr_debug("%s enter\n", __func__);
-       cpu_dai->private_data = sport_handle;
+       snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
        return 0;
 }
 
@@ -60,8 +59,8 @@ static int bf5xx_ssm2602_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
 static struct snd_soc_dai_link bf5xx_ssm2602_dai = {
        .name = "ssm2602",
        .stream_name = "SSM2602",
-       .cpu_dai = &bf5xx_i2s_dai,
-       .codec_dai = &ssm2602_dai,
+       .cpu_dai_name = "bf5xx-i2s",
+       .codec_dai_name = "ssm2602-hifi",
+       .platform_name = "bf5xx-pcm-audio",
+       .codec_name = "ssm2602-codec.0-0x1b",
        .ops = &bf5xx_ssm2602_ops,
 };
 
-/*
- * SSM2602 2 wire address is determined by CSB
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
-
-static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
-       .i2c_bus = 0,
-       .i2c_address = 0x1b,
-};
-
 static struct snd_soc_card bf5xx_ssm2602 = {
        .name = "bf5xx_ssm2602",
-       .platform = &bf5xx_i2s_soc_platform,
        .dai_link = &bf5xx_ssm2602_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
-       .card = &bf5xx_ssm2602,
-       .codec_dev = &soc_codec_dev_ssm2602,
-       .codec_data = &bf5xx_ssm2602_setup,
-};
-
 static struct platform_device *bf5xx_ssm2602_snd_device;
 
 static int __init bf5xx_ssm2602_init(void)
@@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void)
        if (!bf5xx_ssm2602_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(bf5xx_ssm2602_snd_device,
-                               &bf5xx_ssm2602_snd_devdata);
-       bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
+       platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602);
        ret = platform_device_add(bf5xx_ssm2602_snd_device);
 
        if (ret)
index 6bac1ac..74cf759 100644 (file)
@@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -307,25 +307,44 @@ out:
        return ret;
 }
 
-struct snd_soc_platform bf5xx_tdm_soc_platform = {
-       .name           = "bf5xx-audio",
-       .pcm_ops        = &bf5xx_pcm_tdm_ops,
+static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
+       .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)
+static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
 }
-module_init(bfin_pcm_tdm_init);
 
-static void __exit bfin_pcm_tdm_exit(void)
+static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver bfin_tdm_driver = {
+       .driver = {
+                       .name = "bf5xx-tdm-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = bf5xx_soc_platform_probe,
+       .remove = __devexit_p(bf5xx_soc_platform_remove),
+};
+
+static int __init snd_bfin_tdm_init(void)
+{
+       return platform_driver_register(&bfin_tdm_driver);
+}
+module_init(snd_bfin_tdm_init);
+
+static void __exit snd_bfin_tdm_exit(void)
+{
+       platform_driver_unregister(&bfin_tdm_driver);
 }
-module_exit(bfin_pcm_tdm_exit);
+module_exit(snd_bfin_tdm_exit);
 
 MODULE_AUTHOR("Barry Song");
 MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
index ddc5047..7f8cc01 100644 (file)
@@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params {
        char *name;                     /* stream identifier */
 };
 
-/* platform data */
-extern struct snd_soc_platform bf5xx_tdm_soc_platform;
-
 #endif
index 24c1426..1251239 100644 (file)
@@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
 
        if (!dai->active)
                return 0;
-       if (dai->capture.active)
+       if (dai->capture_active)
                sport_rx_stop(sport);
-       if (dai->playback.active)
+       if (dai->playback_active)
                sport_tx_stop(sport);
        return 0;
 }
@@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
 static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
 {
        int ret;
-       struct sport_device *sport = dai->private_data;
+       struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
 
        if (!dai->active)
                return 0;
@@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
        .set_channel_map   = bf5xx_tdm_set_channel_map,
 };
 
-struct snd_soc_dai bf5xx_tdm_dai = {
-       .name = "bf5xx-tdm",
-       .id = 0,
+static struct snd_soc_dai_driver bf5xx_tdm_dai = {
        .suspend = bf5xx_tdm_suspend,
        .resume = bf5xx_tdm_resume,
        .playback = {
@@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = {
                .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)
 {
@@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
                goto sport_config_err;
        }
 
-       ret = snd_soc_register_dai(&bf5xx_tdm_dai);
+       ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
        if (ret) {
                pr_err("Failed to register DAI: %d\n", ret);
                goto sport_config_err;
@@ -337,7 +334,7 @@ sport_config_err:
 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);
+       snd_soc_unregister_dai(&pdev->dev);
 
        return 0;
 }
index 04189a1..e986a3e 100644 (file)
@@ -20,6 +20,4 @@ struct bf5xx_tdm_port {
        int configured;
 };
 
-extern struct snd_soc_dai bf5xx_tdm_dai;
-
 #endif
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
new file mode 100644 (file)
index 0000000..01d19e9
--- /dev/null
@@ -0,0 +1,1486 @@
+/*
+ * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/88pm860x.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/initval.h>
+#include <sound/jack.h>
+
+#include "88pm860x-codec.h"
+
+#define MAX_NAME_LEN           20
+#define REG_CACHE_SIZE         0x40
+#define REG_CACHE_BASE         0xb0
+
+/* Status Register 1 (0x01) */
+#define REG_STATUS_1           0x01
+#define MIC_STATUS             (1 << 7)
+#define HOOK_STATUS            (1 << 6)
+#define HEADSET_STATUS         (1 << 5)
+
+/* Mic Detection Register (0x37) */
+#define REG_MIC_DET            0x37
+#define CONTINUOUS_POLLING     (3 << 1)
+#define EN_MIC_DET             (1 << 0)
+#define MICDET_MASK            0x07
+
+/* Headset Detection Register (0x38) */
+#define REG_HS_DET             0x38
+#define EN_HS_DET              (1 << 0)
+
+/* Misc2 Register (0x42) */
+#define REG_MISC2              0x42
+#define AUDIO_PLL              (1 << 5)
+#define AUDIO_SECTION_RESET    (1 << 4)
+#define AUDIO_SECTION_ON       (1 << 3)
+
+/* PCM Interface Register 2 (0xb1) */
+#define PCM_INF2_BCLK          (1 << 6)        /* Bit clock polarity */
+#define PCM_INF2_FS            (1 << 5)        /* Frame Sync polarity */
+#define PCM_INF2_MASTER                (1 << 4)        /* Master / Slave */
+#define PCM_INF2_18WL          (1 << 3)        /* 18 / 16 bits */
+#define PCM_GENERAL_I2S                0
+#define PCM_EXACT_I2S          1
+#define PCM_LEFT_I2S           2
+#define PCM_RIGHT_I2S          3
+#define PCM_SHORT_FS           4
+#define PCM_LONG_FS            5
+#define PCM_MODE_MASK          7
+
+/* I2S Interface Register 4 (0xbe) */
+#define I2S_EQU_BYP            (1 << 6)
+
+/* DAC Offset Register (0xcb) */
+#define DAC_MUTE               (1 << 7)
+#define MUTE_LEFT              (1 << 6)
+#define MUTE_RIGHT             (1 << 2)
+
+/* ADC Analog Register 1 (0xd0) */
+#define REG_ADC_ANA_1          0xd0
+#define MIC1BIAS_MASK          0x60
+
+/* Earpiece/Speaker Control Register 2 (0xda) */
+#define REG_EAR2               0xda
+#define RSYNC_CHANGE           (1 << 2)
+
+/* Audio Supplies Register 2 (0xdc) */
+#define REG_SUPPLIES2          0xdc
+#define LDO15_READY            (1 << 4)
+#define LDO15_EN               (1 << 3)
+#define CPUMP_READY            (1 << 2)
+#define CPUMP_EN               (1 << 1)
+#define AUDIO_EN               (1 << 0)
+#define SUPPLY_MASK            (LDO15_EN | CPUMP_EN | AUDIO_EN)
+
+/* Audio Enable Register 1 (0xdd) */
+#define ADC_MOD_RIGHT          (1 << 1)
+#define ADC_MOD_LEFT           (1 << 0)
+
+/* Audio Enable Register 2 (0xde) */
+#define ADC_LEFT               (1 << 5)
+#define ADC_RIGHT              (1 << 4)
+
+/* DAC Enable Register 2 (0xe1) */
+#define DAC_LEFT               (1 << 5)
+#define DAC_RIGHT              (1 << 4)
+#define MODULATOR              (1 << 3)
+
+/* Shorts Register (0xeb) */
+#define REG_SHORTS             0xeb
+#define CLR_SHORT_LO2          (1 << 7)
+#define SHORT_LO2              (1 << 6)
+#define CLR_SHORT_LO1          (1 << 5)
+#define SHORT_LO1              (1 << 4)
+#define CLR_SHORT_HS2          (1 << 3)
+#define SHORT_HS2              (1 << 2)
+#define CLR_SHORT_HS1          (1 << 1)
+#define SHORT_HS1              (1 << 0)
+
+/*
+ * This widget should be just after DAC & PGA in DAPM power-on sequence and
+ * before DAC & PGA in DAPM power-off sequence.
+ */
+#define PM860X_DAPM_OUTPUT(wname, wevent)      \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = 0, .invert = 0, .kcontrols = NULL, \
+       .num_kcontrols = 0, .event = wevent, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, }
+
+struct pm860x_det {
+       struct snd_soc_jack     *hp_jack;
+       struct snd_soc_jack     *mic_jack;
+       int                     hp_det;
+       int                     mic_det;
+       int                     hook_det;
+       int                     hs_shrt;
+       int                     lo_shrt;
+};
+
+struct pm860x_priv {
+       unsigned int            sysclk;
+       unsigned int            pcmclk;
+       unsigned int            dir;
+       unsigned int            filter;
+       struct snd_soc_codec    *codec;
+       struct i2c_client       *i2c;
+       struct pm860x_chip      *chip;
+       struct pm860x_det       det;
+
+       int                     irq[4];
+       unsigned char           name[4][MAX_NAME_LEN];
+       unsigned char           reg_cache[REG_CACHE_SIZE];
+};
+
+/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
+static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1);
+
+/* -9dB to 0db in 3dB steps */
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0);
+
+/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */
+static const unsigned int mic_tlv[] = {
+       TLV_DB_RANGE_HEAD(5),
+       0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0),
+       3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0),
+       4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0),
+};
+
+/* {0, 0, 0, -6, 0, 6, 12, 18}dB */
+static const unsigned int aux_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 2, TLV_DB_SCALE_ITEM(0, 0, 0),
+       3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0),
+};
+
+/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */
+static const unsigned int out_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1),
+       4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0),
+       5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0),
+       6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0),
+};
+
+static const unsigned int st_tlv[] = {
+       TLV_DB_RANGE_HEAD(8),
+       0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0),
+       2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0),
+       4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0),
+       6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0),
+       8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0),
+       10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0),
+       14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0),
+       18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0),
+};
+
+/* Sidetone Gain = M * 2^(-5-N) */
+struct st_gain {
+       unsigned int    db;
+       unsigned int    m;
+       unsigned int    n;
+};
+
+static struct st_gain st_table[] = {
+       {-12041,  1, 15}, {-11439,  1, 14}, {-11087,  3, 15}, {-10837,  1, 13},
+       {-10643,  5, 15}, {-10485,  3, 14}, {-10351,  7, 15}, {-10235,  1, 12},
+       {-10133,  9, 15}, {-10041,  5, 14}, { -9958, 11, 15}, { -9883,  3, 13},
+       { -9813, 13, 15}, { -9749,  7, 14}, { -9689, 15, 15}, { -9633,  1, 11},
+       { -9580, 17, 15}, { -9531,  9, 14}, { -9484, 19, 15}, { -9439,  5, 13},
+       { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281,  3, 12},
+       { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147,  7, 13},
+       { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031,  1, 10},
+       { -8978, 17, 14}, { -8929,  9, 13}, { -8882, 19, 14}, { -8837,  5, 12},
+       { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679,  3, 11},
+       { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545,  7, 12},
+       { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429,  1,  9},
+       { -8376, 17, 13}, { -8327,  9, 12}, { -8280, 19, 13}, { -8235,  5, 11},
+       { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077,  3, 10},
+       { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943,  7, 11},
+       { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827,  1,  8},
+       { -7774, 17, 12}, { -7724,  9, 11}, { -7678, 19, 12}, { -7633,  5, 10},
+       { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475,  3,  9},
+       { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341,  7, 10},
+       { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225,  1,  7},
+       { -7172, 17, 11}, { -7122,  9, 10}, { -7075, 19, 11}, { -7031,  5,  9},
+       { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873,  3,  8},
+       { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739,  7,  9},
+       { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623,  1,  6},
+       { -6570, 17, 10}, { -6520,  9,  9}, { -6473, 19, 10}, { -6429,  5,  8},
+       { -6386, 21, 10}, { -6346, 11,  9}, { -6307, 23, 10}, { -6270,  3,  7},
+       { -6235, 25, 10}, { -6201, 13,  9}, { -6168, 27, 10}, { -6137,  7,  8},
+       { -6106, 29, 10}, { -6077, 15,  9}, { -6048, 31, 10}, { -6021,  1,  5},
+       { -5968, 17,  9}, { -5918,  9,  8}, { -5871, 19,  9}, { -5827,  5,  7},
+       { -5784, 21,  9}, { -5744, 11,  8}, { -5705, 23,  9}, { -5668,  3,  6},
+       { -5633, 25,  9}, { -5599, 13,  8}, { -5566, 27,  9}, { -5535,  7,  7},
+       { -5504, 29,  9}, { -5475, 15,  8}, { -5446, 31,  9}, { -5419,  1,  4},
+       { -5366, 17,  8}, { -5316,  9,  7}, { -5269, 19,  8}, { -5225,  5,  6},
+       { -5182, 21,  8}, { -5142, 11,  7}, { -5103, 23,  8}, { -5066,  3,  5},
+       { -5031, 25,  8}, { -4997, 13,  7}, { -4964, 27,  8}, { -4932,  7,  6},
+       { -4902, 29,  8}, { -4873, 15,  7}, { -4844, 31,  8}, { -4816,  1,  3},
+       { -4764, 17,  7}, { -4714,  9,  6}, { -4667, 19,  7}, { -4623,  5,  5},
+       { -4580, 21,  7}, { -4540, 11,  6}, { -4501, 23,  7}, { -4464,  3,  4},
+       { -4429, 25,  7}, { -4395, 13,  6}, { -4362, 27,  7}, { -4330,  7,  5},
+       { -4300, 29,  7}, { -4270, 15,  6}, { -4242, 31,  7}, { -4214,  1,  2},
+       { -4162, 17,  6}, { -4112,  9,  5}, { -4065, 19,  6}, { -4021,  5,  4},
+       { -3978, 21,  6}, { -3938, 11,  5}, { -3899, 23,  6}, { -3862,  3,  3},
+       { -3827, 25,  6}, { -3793, 13,  5}, { -3760, 27,  6}, { -3728,  7,  4},
+       { -3698, 29,  6}, { -3668, 15,  5}, { -3640, 31,  6}, { -3612,  1,  1},
+       { -3560, 17,  5}, { -3510,  9,  4}, { -3463, 19,  5}, { -3419,  5,  3},
+       { -3376, 21,  5}, { -3336, 11,  4}, { -3297, 23,  5}, { -3260,  3,  2},
+       { -3225, 25,  5}, { -3191, 13,  4}, { -3158, 27,  5}, { -3126,  7,  3},
+       { -3096, 29,  5}, { -3066, 15,  4}, { -3038, 31,  5}, { -3010,  1,  0},
+       { -2958, 17,  4}, { -2908,  9,  3}, { -2861, 19,  4}, { -2816,  5,  2},
+       { -2774, 21,  4}, { -2734, 11,  3}, { -2695, 23,  4}, { -2658,  3,  1},
+       { -2623, 25,  4}, { -2589, 13,  3}, { -2556, 27,  4}, { -2524,  7,  2},
+       { -2494, 29,  4}, { -2464, 15,  3}, { -2436, 31,  4}, { -2408,  2,  0},
+       { -2356, 17,  3}, { -2306,  9,  2}, { -2259, 19,  3}, { -2214,  5,  1},
+       { -2172, 21,  3}, { -2132, 11,  2}, { -2093, 23,  3}, { -2056,  3,  0},
+       { -2021, 25,  3}, { -1987, 13,  2}, { -1954, 27,  3}, { -1922,  7,  1},
+       { -1892, 29,  3}, { -1862, 15,  2}, { -1834, 31,  3}, { -1806,  4,  0},
+       { -1754, 17,  2}, { -1704,  9,  1}, { -1657, 19,  2}, { -1612,  5,  0},
+       { -1570, 21,  2}, { -1530, 11,  1}, { -1491, 23,  2}, { -1454,  6,  0},
+       { -1419, 25,  2}, { -1384, 13,  1}, { -1352, 27,  2}, { -1320,  7,  0},
+       { -1290, 29,  2}, { -1260, 15,  1}, { -1232, 31,  2}, { -1204,  8,  0},
+       { -1151, 17,  1}, { -1102,  9,  0}, { -1055, 19,  1}, { -1010, 10,  0},
+       {  -968, 21,  1}, {  -928, 11,  0}, {  -889, 23,  1}, {  -852, 12,  0},
+       {  -816, 25,  1}, {  -782, 13,  0}, {  -750, 27,  1}, {  -718, 14,  0},
+       {  -688, 29,  1}, {  -658, 15,  0}, {  -630, 31,  1}, {  -602, 16,  0},
+       {  -549, 17,  0}, {  -500, 18,  0}, {  -453, 19,  0}, {  -408, 20,  0},
+       {  -366, 21,  0}, {  -325, 22,  0}, {  -287, 23,  0}, {  -250, 24,  0},
+       {  -214, 25,  0}, {  -180, 26,  0}, {  -148, 27,  0}, {  -116, 28,  0},
+       {   -86, 29,  0}, {   -56, 30,  0}, {   -28, 31,  0}, {     0,  0,  0},
+};
+
+static int pm860x_volatile(unsigned int reg)
+{
+       BUG_ON(reg >= REG_CACHE_SIZE);
+
+       switch (reg) {
+       case PM860X_AUDIO_SUPPLIES_2:
+               return 1;
+       }
+
+       return 0;
+}
+
+static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
+                                         unsigned int reg)
+{
+       unsigned char *cache = codec->reg_cache;
+
+       BUG_ON(reg >= REG_CACHE_SIZE);
+
+       if (pm860x_volatile(reg))
+               return cache[reg];
+
+       reg += REG_CACHE_BASE;
+
+       return pm860x_reg_read(codec->control_data, reg);
+}
+
+static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
+                                 unsigned int reg, unsigned int value)
+{
+       unsigned char *cache = codec->reg_cache;
+
+       BUG_ON(reg >= REG_CACHE_SIZE);
+
+       if (!pm860x_volatile(reg))
+               cache[reg] = (unsigned char)value;
+
+       reg += REG_CACHE_BASE;
+
+       return pm860x_reg_write(codec->control_data, reg, value);
+}
+
+static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       int val[2], val2[2], i;
+
+       val[0] = snd_soc_read(codec, reg) & 0x3f;
+       val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf;
+       val2[0] = snd_soc_read(codec, reg2) & 0x3f;
+       val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf;
+
+       for (i = 0; i < ARRAY_SIZE(st_table); i++) {
+               if ((st_table[i].m == val[0]) && (st_table[i].n == val[1]))
+                       ucontrol->value.integer.value[0] = i;
+               if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1]))
+                       ucontrol->value.integer.value[1] = i;
+       }
+       return 0;
+}
+
+static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       int err;
+       unsigned int val, val2;
+
+       val = ucontrol->value.integer.value[0];
+       val2 = ucontrol->value.integer.value[1];
+
+       err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
+       if (err < 0)
+               return err;
+       err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0,
+                                 st_table[val].n << 4);
+       if (err < 0)
+               return err;
+
+       err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m);
+       if (err < 0)
+               return err;
+       err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f,
+                                 st_table[val2].n);
+       return err;
+}
+
+static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       unsigned int shift = mc->shift;
+       int max = mc->max, val, val2;
+       unsigned int mask = (1 << fls(max)) - 1;
+
+       val = snd_soc_read(codec, reg) >> shift;
+       val2 = snd_soc_read(codec, reg2) >> shift;
+       ucontrol->value.integer.value[0] = (max - val) & mask;
+       ucontrol->value.integer.value[1] = (max - val2) & mask;
+
+       return 0;
+}
+
+static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       unsigned int shift = mc->shift;
+       int max = mc->max;
+       unsigned int mask = (1 << fls(max)) - 1;
+       int err;
+       unsigned int val, val2, val_mask;
+
+       val_mask = mask << shift;
+       val = ((max - ucontrol->value.integer.value[0]) & mask);
+       val2 = ((max - ucontrol->value.integer.value[1]) & mask);
+
+       val = val << shift;
+       val2 = val2 << shift;
+
+       err = snd_soc_update_bits(codec, reg, val_mask, val);
+       if (err < 0)
+               return err;
+
+       err = snd_soc_update_bits(codec, reg2, val_mask, val2);
+       return err;
+}
+
+/* DAPM Widget Events */
+/*
+ * A lot registers are belong to RSYNC domain. It requires enabling RSYNC bit
+ * after updating these registers. Otherwise, these updated registers won't
+ * be effective.
+ */
+static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
+                             struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       /*
+        * In order to avoid current on the load, mute power-on and power-off
+        * should be transients.
+        * Unmute by DAC_MUTE. It should be unmuted when DAPM sequence is
+        * finished.
+        */
+       snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0);
+       snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+                           RSYNC_CHANGE, RSYNC_CHANGE);
+       return 0;
+}
+
+static int pm860x_dac_event(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       unsigned int dac = 0;
+       int data;
+
+       if (!strcmp(w->name, "Left DAC"))
+               dac = DAC_LEFT;
+       if (!strcmp(w->name, "Right DAC"))
+               dac = DAC_RIGHT;
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               if (dac) {
+                       /* Auto mute in power-on sequence. */
+                       dac |= MODULATOR;
+                       snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+                                           DAC_MUTE, DAC_MUTE);
+                       snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+                                           RSYNC_CHANGE, RSYNC_CHANGE);
+                       /* update dac */
+                       snd_soc_update_bits(codec, PM860X_DAC_EN_2,
+                                           dac, dac);
+               }
+               break;
+       case SND_SOC_DAPM_PRE_PMD:
+               if (dac) {
+                       /* Auto mute in power-off sequence. */
+                       snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
+                                           DAC_MUTE, DAC_MUTE);
+                       snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+                                           RSYNC_CHANGE, RSYNC_CHANGE);
+                       /* update dac */
+                       data = snd_soc_read(codec, PM860X_DAC_EN_2);
+                       data &= ~dac;
+                       if (!(data & (DAC_LEFT | DAC_RIGHT)))
+                               data &= ~MODULATOR;
+                       snd_soc_write(codec, PM860X_DAC_EN_2, data);
+               }
+               break;
+       }
+       return 0;
+}
+
+static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
+
+static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
+
+static const struct soc_enum pm860x_hs1_opamp_enum =
+       SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs2_opamp_enum =
+       SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_hs1_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_hs2_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo1_opamp_enum =
+       SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo2_opamp_enum =
+       SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
+
+static const struct soc_enum pm860x_lo1_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_lo2_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_ear_pa_enum =
+       SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
+
+static const struct soc_enum pm860x_spk_ear_opamp_enum =
+       SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
+
+static const struct snd_kcontrol_new pm860x_snd_controls[] = {
+       SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
+                       PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv),
+       SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0,
+                       aux_tlv),
+       SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0,
+                       mic_tlv),
+       SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0,
+                       mic_tlv),
+       SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN,
+                            PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1,
+                            0, snd_soc_get_volsw_2r_st,
+                            snd_soc_put_volsw_2r_st, st_tlv),
+       SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1,
+                       0, 7, 0, out_tlv),
+       SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL,
+                        PM860X_LO2_CTRL, 0, 7, 0, out_tlv),
+       SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL,
+                        PM860X_HS2_CTRL, 0, 7, 0, out_tlv),
+       SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume",
+                            PM860X_HIFIL_GAIN_LEFT,
+                            PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0,
+                            snd_soc_get_volsw_2r_out,
+                            snd_soc_put_volsw_2r_out, dpga_tlv),
+       SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume",
+                            PM860X_HIFIR_GAIN_LEFT,
+                            PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0,
+                            snd_soc_get_volsw_2r_out,
+                            snd_soc_put_volsw_2r_out, dpga_tlv),
+       SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT,
+                            PM860X_LOFI_GAIN_RIGHT, 0, 63, 0,
+                            snd_soc_get_volsw_2r_out,
+                            snd_soc_put_volsw_2r_out, dpga_tlv),
+       SOC_ENUM("Headset1 Operational Amplifier Current",
+                pm860x_hs1_opamp_enum),
+       SOC_ENUM("Headset2 Operational Amplifier Current",
+                pm860x_hs2_opamp_enum),
+       SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum),
+       SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum),
+       SOC_ENUM("Lineout1 Operational Amplifier Current",
+                pm860x_lo1_opamp_enum),
+       SOC_ENUM("Lineout2 Operational Amplifier Current",
+                pm860x_lo2_opamp_enum),
+       SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum),
+       SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum),
+       SOC_ENUM("Speaker Operational Amplifier Current",
+                pm860x_spk_ear_opamp_enum),
+       SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum),
+       SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum),
+};
+
+/*
+ * DAPM Controls
+ */
+
+/* PCM Switch / PCM Interface */
+static const struct snd_kcontrol_new pcm_switch_controls =
+       SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
+
+/* AUX1 Switch */
+static const struct snd_kcontrol_new aux1_switch_controls =
+       SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
+
+/* AUX2 Switch */
+static const struct snd_kcontrol_new aux2_switch_controls =
+       SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0);
+
+/* Left Ex. PA Switch */
+static const struct snd_kcontrol_new lepa_switch_controls =
+       SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0);
+
+/* Right Ex. PA Switch */
+static const struct snd_kcontrol_new repa_switch_controls =
+       SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
+
+/* PCM Mux / Mux7 */
+static const char *aif1_text[] = {
+       "PCM L", "PCM R",
+};
+
+static const struct soc_enum aif1_enum =
+       SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
+
+static const struct snd_kcontrol_new aif1_mux =
+       SOC_DAPM_ENUM("PCM Mux", aif1_enum);
+
+/* I2S Mux / Mux9 */
+static const char *i2s_din_text[] = {
+       "DIN", "DIN1",
+};
+
+static const struct soc_enum i2s_din_enum =
+       SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
+
+static const struct snd_kcontrol_new i2s_din_mux =
+       SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
+
+/* I2S Mic Mux / Mux8 */
+static const char *i2s_mic_text[] = {
+       "Ex PA", "ADC",
+};
+
+static const struct soc_enum i2s_mic_enum =
+       SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
+
+static const struct snd_kcontrol_new i2s_mic_mux =
+       SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
+
+/* ADCL Mux / Mux2 */
+static const char *adcl_text[] = {
+       "ADCR", "ADCL",
+};
+
+static const struct soc_enum adcl_enum =
+       SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
+
+static const struct snd_kcontrol_new adcl_mux =
+       SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
+
+/* ADCR Mux / Mux3 */
+static const char *adcr_text[] = {
+       "ADCL", "ADCR",
+};
+
+static const struct soc_enum adcr_enum =
+       SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
+
+static const struct snd_kcontrol_new adcr_mux =
+       SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
+
+/* ADCR EC Mux / Mux6 */
+static const char *adcr_ec_text[] = {
+       "ADCR", "EC",
+};
+
+static const struct soc_enum adcr_ec_enum =
+       SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
+
+static const struct snd_kcontrol_new adcr_ec_mux =
+       SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
+
+/* EC Mux / Mux4 */
+static const char *ec_text[] = {
+       "Left", "Right", "Left + Right",
+};
+
+static const struct soc_enum ec_enum =
+       SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
+
+static const struct snd_kcontrol_new ec_mux =
+       SOC_DAPM_ENUM("EC Mux", ec_enum);
+
+static const char *dac_text[] = {
+       "No input", "Right", "Left", "No input",
+};
+
+/* DAC Headset 1 Mux / Mux10 */
+static const struct soc_enum dac_hs1_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs1_mux =
+       SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
+
+/* DAC Headset 2 Mux / Mux11 */
+static const struct soc_enum dac_hs2_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_hs2_mux =
+       SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
+
+/* DAC Lineout 1 Mux / Mux12 */
+static const struct soc_enum dac_lo1_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo1_mux =
+       SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
+
+/* DAC Lineout 2 Mux / Mux13 */
+static const struct soc_enum dac_lo2_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_lo2_mux =
+       SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
+
+/* DAC Spearker Earphone Mux / Mux14 */
+static const struct soc_enum dac_spk_ear_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
+
+static const struct snd_kcontrol_new dac_spk_ear_mux =
+       SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
+
+/* Headset 1 Mux / Mux15 */
+static const char *in_text[] = {
+       "Digital", "Analog",
+};
+
+static const struct soc_enum hs1_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
+
+static const struct snd_kcontrol_new hs1_mux =
+       SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
+
+/* Headset 2 Mux / Mux16 */
+static const struct soc_enum hs2_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
+
+static const struct snd_kcontrol_new hs2_mux =
+       SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
+
+/* Lineout 1 Mux / Mux17 */
+static const struct soc_enum lo1_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
+
+static const struct snd_kcontrol_new lo1_mux =
+       SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
+
+/* Lineout 2 Mux / Mux18 */
+static const struct soc_enum lo2_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
+
+static const struct snd_kcontrol_new lo2_mux =
+       SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
+
+/* Speaker Earpiece Demux */
+static const char *spk_text[] = {
+       "Earpiece", "Speaker",
+};
+
+static const struct soc_enum spk_enum =
+       SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
+
+static const struct snd_kcontrol_new spk_demux =
+       SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
+
+/* MIC Mux / Mux1 */
+static const char *mic_text[] = {
+       "Mic 1", "Mic 2",
+};
+
+static const struct soc_enum mic_enum =
+       SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
+
+static const struct snd_kcontrol_new mic_mux =
+       SOC_DAPM_ENUM("MIC Mux", mic_enum);
+
+static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
+       SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0,
+                           PM860X_ADC_EN_2, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0,
+                            PM860X_PCM_IFACE_3, 1, 1),
+
+
+       SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
+                           PM860X_DAC_EN_2, 0, 0),
+       SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
+                           PM860X_DAC_EN_2, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
+                            PM860X_I2S_IFACE_3, 5, 1),
+       SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
+       SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
+       SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
+       SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux),
+       SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux),
+       SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0,
+                           &lepa_switch_controls),
+       SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0,
+                           &repa_switch_controls),
+
+       SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Left ADC MOD", PM860X_ADC_EN_1,
+                        0, 1, 1, 0),
+       SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Right ADC MOD", PM860X_ADC_EN_1,
+                        1, 1, 1, 0),
+       SND_SOC_DAPM_ADC("Left ADC", NULL, PM860X_ADC_EN_2, 5, 0),
+       SND_SOC_DAPM_ADC("Right ADC", NULL, PM860X_ADC_EN_2, 4, 0),
+
+       SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0,
+                           &aux1_switch_controls),
+       SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0,
+                           &aux2_switch_controls),
+
+       SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux),
+       SND_SOC_DAPM_MICBIAS("Mic1 Bias", PM860X_ADC_ANA_1, 2, 0),
+       SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0),
+       SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0),
+
+       SND_SOC_DAPM_INPUT("AUX1"),
+       SND_SOC_DAPM_INPUT("AUX2"),
+       SND_SOC_DAPM_INPUT("MIC1P"),
+       SND_SOC_DAPM_INPUT("MIC1N"),
+       SND_SOC_DAPM_INPUT("MIC2P"),
+       SND_SOC_DAPM_INPUT("MIC2N"),
+       SND_SOC_DAPM_INPUT("MIC3P"),
+       SND_SOC_DAPM_INPUT("MIC3N"),
+
+       SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0,
+                          pm860x_dac_event,
+                          SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+       SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0,
+                          pm860x_dac_event,
+                          SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+       SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux),
+       SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux),
+       SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux),
+       SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux),
+       SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux),
+       SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux),
+       SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux),
+       SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux),
+       SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux),
+       SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux),
+       SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0,
+                        &spk_demux),
+
+
+       SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("HS1"),
+       SND_SOC_DAPM_OUTPUT("HS2"),
+       SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+       SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+       SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("EARP"),
+       SND_SOC_DAPM_OUTPUT("EARN"),
+       SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("LSP"),
+       SND_SOC_DAPM_OUTPUT("LSN"),
+       SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2,
+                        0, SUPPLY_MASK, SUPPLY_MASK, 0),
+
+       PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* supply */
+       {"Left DAC", NULL, "VCODEC"},
+       {"Right DAC", NULL, "VCODEC"},
+       {"Left ADC", NULL, "VCODEC"},
+       {"Right ADC", NULL, "VCODEC"},
+       {"Left ADC", NULL, "Left ADC MOD"},
+       {"Right ADC", NULL, "Right ADC MOD"},
+
+       /* PCM/AIF1 Inputs */
+       {"PCM SDO", NULL, "ADC Left Mux"},
+       {"PCM SDO", NULL, "ADCR EC Mux"},
+
+       /* PCM/AFI2 Outputs */
+       {"Lofi PGA", NULL, "PCM SDI"},
+       {"Lofi PGA", NULL, "Sidetone PGA"},
+       {"Left DAC", NULL, "Lofi PGA"},
+       {"Right DAC", NULL, "Lofi PGA"},
+
+       /* I2S/AIF2 Inputs */
+       {"MIC Mux", "Mic 1", "MIC1P"},
+       {"MIC Mux", "Mic 1", "MIC1N"},
+       {"MIC Mux", "Mic 2", "MIC2P"},
+       {"MIC Mux", "Mic 2", "MIC2N"},
+       {"MIC1 Volume", NULL, "MIC Mux"},
+       {"MIC3 Volume", NULL, "MIC3P"},
+       {"MIC3 Volume", NULL, "MIC3N"},
+       {"Left ADC", NULL, "MIC1 Volume"},
+       {"Right ADC", NULL, "MIC3 Volume"},
+       {"ADC Left Mux", "ADCR", "Right ADC"},
+       {"ADC Left Mux", "ADCL", "Left ADC"},
+       {"ADC Right Mux", "ADCL", "Left ADC"},
+       {"ADC Right Mux", "ADCR", "Right ADC"},
+       {"Left EPA", "Switch", "Left DAC"},
+       {"Right EPA", "Switch", "Right DAC"},
+       {"EC Mux", "Left", "Left DAC"},
+       {"EC Mux", "Right", "Right DAC"},
+       {"EC Mux", "Left + Right", "Left DAC"},
+       {"EC Mux", "Left + Right", "Right DAC"},
+       {"ADCR EC Mux", "ADCR", "ADC Right Mux"},
+       {"ADCR EC Mux", "EC", "EC Mux"},
+       {"I2S Mic Mux", "Ex PA", "Left EPA"},
+       {"I2S Mic Mux", "Ex PA", "Right EPA"},
+       {"I2S Mic Mux", "ADC", "ADC Left Mux"},
+       {"I2S Mic Mux", "ADC", "ADCR EC Mux"},
+       {"I2S DOUT", NULL, "I2S Mic Mux"},
+
+       /* I2S/AIF2 Outputs */
+       {"I2S DIN Mux", "DIN", "I2S DIN"},
+       {"I2S DIN Mux", "DIN1", "I2S DIN1"},
+       {"Left DAC", NULL, "I2S DIN Mux"},
+       {"Right DAC", NULL, "I2S DIN Mux"},
+       {"DAC HS1 Mux", "Left", "Left DAC"},
+       {"DAC HS1 Mux", "Right", "Right DAC"},
+       {"DAC HS2 Mux", "Left", "Left DAC"},
+       {"DAC HS2 Mux", "Right", "Right DAC"},
+       {"DAC LO1 Mux", "Left", "Left DAC"},
+       {"DAC LO1 Mux", "Right", "Right DAC"},
+       {"DAC LO2 Mux", "Left", "Left DAC"},
+       {"DAC LO2 Mux", "Right", "Right DAC"},
+       {"Headset1 Mux", "Digital", "DAC HS1 Mux"},
+       {"Headset2 Mux", "Digital", "DAC HS2 Mux"},
+       {"Lineout1 Mux", "Digital", "DAC LO1 Mux"},
+       {"Lineout2 Mux", "Digital", "DAC LO2 Mux"},
+       {"Headset1 PGA", NULL, "Headset1 Mux"},
+       {"Headset2 PGA", NULL, "Headset2 Mux"},
+       {"Lineout1 PGA", NULL, "Lineout1 Mux"},
+       {"Lineout2 PGA", NULL, "Lineout2 Mux"},
+       {"DAC SP Mux", "Left", "Left DAC"},
+       {"DAC SP Mux", "Right", "Right DAC"},
+       {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"},
+       {"Speaker PGA", NULL, "Speaker Earpiece Demux"},
+       {"Earpiece PGA", NULL, "Speaker Earpiece Demux"},
+
+       {"RSYNC", NULL, "Headset1 PGA"},
+       {"RSYNC", NULL, "Headset2 PGA"},
+       {"RSYNC", NULL, "Lineout1 PGA"},
+       {"RSYNC", NULL, "Lineout2 PGA"},
+       {"RSYNC", NULL, "Speaker PGA"},
+       {"RSYNC", NULL, "Speaker PGA"},
+       {"RSYNC", NULL, "Earpiece PGA"},
+       {"RSYNC", NULL, "Earpiece PGA"},
+
+       {"HS1", NULL, "RSYNC"},
+       {"HS2", NULL, "RSYNC"},
+       {"LINEOUT1", NULL, "RSYNC"},
+       {"LINEOUT2", NULL, "RSYNC"},
+       {"LSP", NULL, "RSYNC"},
+       {"LSN", NULL, "RSYNC"},
+       {"EARP", NULL, "RSYNC"},
+       {"EARN", NULL, "RSYNC"},
+};
+
+/*
+ * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute.
+ * These bits can also be used to mute.
+ */
+static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       int data = 0, mask = MUTE_LEFT | MUTE_RIGHT;
+
+       if (mute)
+               data = mask;
+       snd_soc_update_bits(codec, PM860X_DAC_OFFSET, mask, data);
+       snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
+                           RSYNC_CHANGE, RSYNC_CHANGE);
+       return 0;
+}
+
+static int pm860x_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;
+       unsigned char inf = 0, mask = 0;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               inf &= ~PCM_INF2_18WL;
+               break;
+       case SNDRV_PCM_FORMAT_S18_3LE:
+               inf |= PCM_INF2_18WL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       mask |= PCM_INF2_18WL;
+       snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+
+       /* sample rate */
+       switch (params_rate(params)) {
+       case 8000:
+               inf = 0;
+               break;
+       case 16000:
+               inf = 3;
+               break;
+       case 32000:
+               inf = 6;
+               break;
+       case 48000:
+               inf = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf);
+
+       return 0;
+}
+
+static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                 unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+       unsigned char inf = 0, mask = 0;
+       int ret = -EINVAL;
+
+       mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+       case SND_SOC_DAIFMT_CBM_CFS:
+               if (pm860x->dir == PM860X_CLK_DIR_OUT) {
+                       inf |= PCM_INF2_MASTER;
+                       ret = 0;
+               }
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               if (pm860x->dir == PM860X_CLK_DIR_IN) {
+                       inf &= ~PCM_INF2_MASTER;
+                       ret = 0;
+               }
+               break;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               inf |= PCM_EXACT_I2S;
+               ret = 0;
+               break;
+       }
+       mask |= PCM_MODE_MASK;
+       if (ret)
+               return ret;
+       snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
+       return 0;
+}
+
+static int pm860x_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 pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+
+       if (dir == PM860X_CLK_DIR_OUT)
+               pm860x->dir = PM860X_CLK_DIR_OUT;
+       else {
+               pm860x->dir = PM860X_CLK_DIR_IN;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int pm860x_i2s_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;
+       unsigned char inf;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               inf = 0;
+               break;
+       case SNDRV_PCM_FORMAT_S18_3LE:
+               inf = PCM_INF2_18WL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf);
+
+       /* sample rate */
+       switch (params_rate(params)) {
+       case 8000:
+               inf = 0;
+               break;
+       case 11025:
+               inf = 1;
+               break;
+       case 16000:
+               inf = 3;
+               break;
+       case 22050:
+               inf = 4;
+               break;
+       case 32000:
+               inf = 6;
+               break;
+       case 44100:
+               inf = 7;
+               break;
+       case 48000:
+               inf = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+       snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf);
+
+       return 0;
+}
+
+static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                 unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+       unsigned char inf = 0, mask = 0;
+
+       mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               if (pm860x->dir == PM860X_CLK_DIR_OUT)
+                       inf |= PCM_INF2_MASTER;
+               else
+                       return -EINVAL;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               if (pm860x->dir == PM860X_CLK_DIR_IN)
+                       inf &= ~PCM_INF2_MASTER;
+               else
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               inf |= PCM_EXACT_I2S;
+               break;
+       default:
+               return -EINVAL;
+       }
+       mask |= PCM_MODE_MASK;
+       snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf);
+       return 0;
+}
+
+static int pm860x_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       int data;
+
+       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) {
+                       /* Enable Audio PLL & Audio section */
+                       data = AUDIO_PLL | AUDIO_SECTION_RESET
+                               | AUDIO_SECTION_ON;
+                       pm860x_reg_write(codec->control_data, REG_MISC2, data);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
+               pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+       .digital_mute   = pm860x_digital_mute,
+       .hw_params      = pm860x_pcm_hw_params,
+       .set_fmt        = pm860x_pcm_set_dai_fmt,
+       .set_sysclk     = pm860x_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+       .digital_mute   = pm860x_digital_mute,
+       .hw_params      = pm860x_i2s_hw_params,
+       .set_fmt        = pm860x_i2s_set_dai_fmt,
+       .set_sysclk     = pm860x_set_dai_sysclk,
+};
+
+#define PM860X_RATES   (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |   \
+                        SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+
+static struct snd_soc_dai_driver pm860x_dai[] = {
+       {
+               /* DAI PCM */
+               .name   = "88pm860x-pcm",
+               .id     = 1,
+               .playback = {
+                       .stream_name    = "PCM Playback",
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = PM860X_RATES,
+                       .formats        = SNDRV_PCM_FORMAT_S16_LE | \
+                                         SNDRV_PCM_FORMAT_S18_3LE,
+               },
+               .capture = {
+                       .stream_name    = "PCM Capture",
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = PM860X_RATES,
+                       .formats        = SNDRV_PCM_FORMAT_S16_LE | \
+                                         SNDRV_PCM_FORMAT_S18_3LE,
+               },
+               .ops    = &pm860x_pcm_dai_ops,
+       }, {
+               /* DAI I2S */
+               .name   = "88pm860x-i2s",
+               .id     = 2,
+               .playback = {
+                       .stream_name    = "I2S Playback",
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = SNDRV_PCM_RATE_8000_48000,
+                       .formats        = SNDRV_PCM_FORMAT_S16_LE | \
+                                         SNDRV_PCM_FORMAT_S18_3LE,
+               },
+               .capture = {
+                       .stream_name    = "I2S Capture",
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = SNDRV_PCM_RATE_8000_48000,
+                       .formats        = SNDRV_PCM_FORMAT_S16_LE | \
+                                         SNDRV_PCM_FORMAT_S18_3LE,
+               },
+               .ops    = &pm860x_i2s_dai_ops,
+       },
+};
+
+static irqreturn_t pm860x_codec_handler(int irq, void *data)
+{
+       struct pm860x_priv *pm860x = data;
+       int status, shrt, report = 0, mic_report = 0;
+       int mask;
+
+       status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1);
+       shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS);
+       mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt
+               | pm860x->det.hp_det;
+
+       if ((pm860x->det.hp_det & SND_JACK_HEADPHONE)
+               && (status & HEADSET_STATUS))
+               report |= SND_JACK_HEADPHONE;
+
+       if ((pm860x->det.mic_det & SND_JACK_MICROPHONE)
+               && (status & MIC_STATUS))
+               mic_report |= SND_JACK_MICROPHONE;
+
+       if (pm860x->det.hs_shrt && (shrt & (SHORT_HS1 | SHORT_HS2)))
+               report |= pm860x->det.hs_shrt;
+
+       if (pm860x->det.hook_det && (status & HOOK_STATUS))
+               report |= pm860x->det.hook_det;
+
+       if (pm860x->det.lo_shrt && (shrt & (SHORT_LO1 | SHORT_LO2)))
+               report |= pm860x->det.lo_shrt;
+
+       if (report)
+               snd_soc_jack_report(pm860x->det.hp_jack, report, mask);
+       if (mic_report)
+               snd_soc_jack_report(pm860x->det.mic_jack, SND_JACK_MICROPHONE,
+                                   SND_JACK_MICROPHONE);
+
+       dev_dbg(pm860x->codec->dev, "headphone report:0x%x, mask:%x\n",
+               report, mask);
+       dev_dbg(pm860x->codec->dev, "microphone report:0x%x\n", mic_report);
+       return IRQ_HANDLED;
+}
+
+int pm860x_hs_jack_detect(struct snd_soc_codec *codec,
+                         struct snd_soc_jack *jack,
+                         int det, int hook, int hs_shrt, int lo_shrt)
+{
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+       int data;
+
+       pm860x->det.hp_jack = jack;
+       pm860x->det.hp_det = det;
+       pm860x->det.hook_det = hook;
+       pm860x->det.hs_shrt = hs_shrt;
+       pm860x->det.lo_shrt = lo_shrt;
+
+       if (det & SND_JACK_HEADPHONE)
+               pm860x_set_bits(codec->control_data, REG_HS_DET,
+                               EN_HS_DET, EN_HS_DET);
+       /* headset short detect */
+       if (hs_shrt) {
+               data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
+               pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+       }
+       /* Lineout short detect */
+       if (lo_shrt) {
+               data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
+               pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
+       }
+
+       /* sync status */
+       pm860x_codec_handler(0, pm860x);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pm860x_hs_jack_detect);
+
+int pm860x_mic_jack_detect(struct snd_soc_codec *codec,
+                          struct snd_soc_jack *jack, int det)
+{
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+
+       pm860x->det.mic_jack = jack;
+       pm860x->det.mic_det = det;
+
+       if (det & SND_JACK_MICROPHONE)
+               pm860x_set_bits(codec->control_data, REG_MIC_DET,
+                               MICDET_MASK, MICDET_MASK);
+
+       /* sync status */
+       pm860x_codec_handler(0, pm860x);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect);
+
+static int pm860x_probe(struct snd_soc_codec *codec)
+{
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+       int i, ret;
+
+       pm860x->codec = codec;
+
+       codec->control_data = pm860x->i2c;
+
+       for (i = 0; i < 4; i++) {
+               ret = request_threaded_irq(pm860x->irq[i], NULL,
+                                          pm860x_codec_handler, IRQF_ONESHOT,
+                                          pm860x->name[i], pm860x);
+               if (ret < 0) {
+                       dev_err(codec->dev, "Failed to request IRQ!\n");
+                       goto out_irq;
+               }
+       }
+
+       pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
+                              REG_CACHE_SIZE, codec->reg_cache);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to fill register cache: %d\n",
+                       ret);
+               goto out_codec;
+       }
+
+       snd_soc_add_controls(codec, pm860x_snd_controls,
+                            ARRAY_SIZE(pm860x_snd_controls));
+       snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets,
+                                 ARRAY_SIZE(pm860x_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+       return 0;
+
+out_codec:
+       i = 3;
+out_irq:
+       for (; i >= 0; i--)
+               free_irq(pm860x->irq[i], pm860x);
+       return -EINVAL;
+}
+
+static int pm860x_remove(struct snd_soc_codec *codec)
+{
+       struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
+       int i;
+
+       for (i = 3; i >= 0; i--)
+               free_irq(pm860x->irq[i], pm860x);
+       pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
+       .probe          = pm860x_probe,
+       .remove         = pm860x_remove,
+       .read           = pm860x_read_reg_cache,
+       .write          = pm860x_write_reg_cache,
+       .reg_cache_size = REG_CACHE_SIZE,
+       .reg_word_size  = sizeof(u8),
+       .set_bias_level = pm860x_set_bias_level,
+};
+
+static int __devinit pm860x_codec_probe(struct platform_device *pdev)
+{
+       struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct pm860x_priv *pm860x;
+       struct resource *res;
+       int i, ret;
+
+       pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL);
+       if (pm860x == NULL)
+               return -ENOMEM;
+
+       pm860x->chip = chip;
+       pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
+                       : chip->companion;
+       platform_set_drvdata(pdev, pm860x);
+
+       for (i = 0; i < 4; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               if (!res) {
+                       dev_err(&pdev->dev, "Failed to get IRQ resources\n");
+                       goto out;
+               }
+               pm860x->irq[i] = res->start + chip->irq_base;
+               strncpy(pm860x->name[i], res->name, MAX_NAME_LEN);
+       }
+
+       ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x,
+                                    pm860x_dai, ARRAY_SIZE(pm860x_dai));
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register codec\n");
+               goto out;
+       }
+       return ret;
+
+out:
+       platform_set_drvdata(pdev, NULL);
+       kfree(pm860x);
+       return -EINVAL;
+}
+
+static int __devexit pm860x_codec_remove(struct platform_device *pdev)
+{
+       struct pm860x_priv *pm860x = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_codec(&pdev->dev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(pm860x);
+       return 0;
+}
+
+static struct platform_driver pm860x_codec_driver = {
+       .driver = {
+               .name   = "88pm860x-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = pm860x_codec_probe,
+       .remove = __devexit_p(pm860x_codec_remove),
+};
+
+static __init int pm860x_init(void)
+{
+       return platform_driver_register(&pm860x_codec_driver);
+}
+module_init(pm860x_init);
+
+static __exit void pm860x_exit(void)
+{
+       platform_driver_unregister(&pm860x_codec_driver);
+}
+module_exit(pm860x_exit);
+
+MODULE_DESCRIPTION("ASoC 88PM860x driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-codec");
+
diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h
new file mode 100644 (file)
index 0000000..3364ba4
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver
+ *
+ * Copyright 2010 Marvell International Ltd.
+ *     Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __88PM860X_H
+#define __88PM860X_H
+
+/* The offset of these registers are 0xb0 */
+#define PM860X_PCM_IFACE_1             0x00
+#define PM860X_PCM_IFACE_2             0x01
+#define PM860X_PCM_IFACE_3             0x02
+#define PM860X_PCM_RATE                        0x03
+#define PM860X_EC_PATH                 0x04
+#define PM860X_SIDETONE_L_GAIN         0x05
+#define PM860X_SIDETONE_R_GAIN         0x06
+#define PM860X_SIDETONE_SHIFT          0x07
+#define PM860X_ADC_OFFSET_1            0x08
+#define PM860X_ADC_OFFSET_2            0x09
+#define PM860X_DMIC_DELAY              0x0a
+
+#define PM860X_I2S_IFACE_1             0x0b
+#define PM860X_I2S_IFACE_2             0x0c
+#define PM860X_I2S_IFACE_3             0x0d
+#define PM860X_I2S_IFACE_4             0x0e
+#define PM860X_EQUALIZER_N0_1          0x0f
+#define PM860X_EQUALIZER_N0_2          0x10
+#define PM860X_EQUALIZER_N1_1          0x11
+#define PM860X_EQUALIZER_N1_2          0x12
+#define PM860X_EQUALIZER_D1_1          0x13
+#define PM860X_EQUALIZER_D1_2          0x14
+#define PM860X_LOFI_GAIN_LEFT          0x15
+#define PM860X_LOFI_GAIN_RIGHT         0x16
+#define PM860X_HIFIL_GAIN_LEFT         0x17
+#define PM860X_HIFIL_GAIN_RIGHT                0x18
+#define PM860X_HIFIR_GAIN_LEFT         0x19
+#define PM860X_HIFIR_GAIN_RIGHT                0x1a
+#define PM860X_DAC_OFFSET              0x1b
+#define PM860X_OFFSET_LEFT_1           0x1c
+#define PM860X_OFFSET_LEFT_2           0x1d
+#define PM860X_OFFSET_RIGHT_1          0x1e
+#define PM860X_OFFSET_RIGHT_2          0x1f
+#define PM860X_ADC_ANA_1               0x20
+#define PM860X_ADC_ANA_2               0x21
+#define PM860X_ADC_ANA_3               0x22
+#define PM860X_ADC_ANA_4               0x23
+#define PM860X_ANA_TO_ANA              0x24
+#define PM860X_HS1_CTRL                        0x25
+#define PM860X_HS2_CTRL                        0x26
+#define PM860X_LO1_CTRL                        0x27
+#define PM860X_LO2_CTRL                        0x28
+#define PM860X_EAR_CTRL_1              0x29
+#define PM860X_EAR_CTRL_2              0x2a
+#define PM860X_AUDIO_SUPPLIES_1                0x2b
+#define PM860X_AUDIO_SUPPLIES_2                0x2c
+#define PM860X_ADC_EN_1                        0x2d
+#define PM860X_ADC_EN_2                        0x2e
+#define PM860X_DAC_EN_1                        0x2f
+#define PM860X_DAC_EN_2                        0x31
+#define PM860X_AUDIO_CAL_1             0x32
+#define PM860X_AUDIO_CAL_2             0x33
+#define PM860X_AUDIO_CAL_3             0x34
+#define PM860X_AUDIO_CAL_4             0x35
+#define PM860X_AUDIO_CAL_5             0x36
+#define PM860X_ANA_INPUT_SEL_1         0x37
+#define PM860X_ANA_INPUT_SEL_2         0x38
+
+#define PM860X_PCM_IFACE_4             0x39
+#define PM860X_I2S_IFACE_5             0x3a
+
+#define PM860X_SHORTS                  0x3b
+#define PM860X_PLL_ADJ_1               0x3c
+#define PM860X_PLL_ADJ_2               0x3d
+
+/* bits definition */
+#define PM860X_CLK_DIR_IN              0
+#define PM860X_CLK_DIR_OUT             1
+
+#define PM860X_DET_HEADSET             (1 << 0)
+#define PM860X_DET_MIC                 (1 << 1)
+#define PM860X_DET_HOOK                        (1 << 2)
+#define PM860X_SHORT_HEADSET           (1 << 3)
+#define PM860X_SHORT_LINEOUT           (1 << 4)
+#define PM860X_DET_MASK                        0x1F
+
+extern int pm860x_hs_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
+                                int, int, int, int);
+extern int pm860x_mic_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
+                                 int);
+
+#endif /* __88PM860X_H */
index 83f5c67..94a9d06 100644 (file)
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
 
 config SND_SOC_ALL_CODECS
        tristate "Build all ASoC CODEC drivers"
+       select SND_SOC_88PM860X if MFD_88PM860X
        select SND_SOC_L3
        select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
        select SND_SOC_AD1836 if SPI_MASTER
@@ -26,6 +27,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_CS4270 if I2C
        select SND_SOC_DA7210 if I2C
        select SND_SOC_JZ4740 if SOC_JZ4740
+       select SND_SOC_MAX98088 if I2C
        select SND_SOC_MAX9877 if I2C
        select SND_SOC_PCM3008
        select SND_SOC_SPDIF
@@ -40,6 +42,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_TWL6040 if TWL4030_CORE
        select SND_SOC_UDA134X
        select SND_SOC_UDA1380 if I2C
+       select SND_SOC_WL1273 if WL1273_CORE
        select SND_SOC_WM2000 if I2C
        select SND_SOC_WM8350 if MFD_WM8350
        select SND_SOC_WM8400 if MFD_WM8400
@@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS
        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_WM8804 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8900 if I2C
        select SND_SOC_WM8903 if I2C
        select SND_SOC_WM8904 if I2C
@@ -61,9 +65,11 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8955 if I2C
        select SND_SOC_WM8960 if I2C
        select SND_SOC_WM8961 if I2C
+       select SND_SOC_WM8962 if I2C
        select SND_SOC_WM8971 if I2C
        select SND_SOC_WM8974 if I2C
        select SND_SOC_WM8978 if I2C
+       select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8990 if I2C
        select SND_SOC_WM8993 if I2C
@@ -84,6 +90,9 @@ config SND_SOC_ALL_CODECS
 
           If unsure select "N".
 
+config SND_SOC_88PM860X
+       tristate
+
 config SND_SOC_WM_HUBS
        tristate
        default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
@@ -150,6 +159,9 @@ config SND_SOC_L3
 config SND_SOC_DA7210
         tristate
 
+config SND_SOC_MAX98088
+       tristate
+
 config SND_SOC_PCM3008
        tristate
 
@@ -188,6 +200,9 @@ config SND_SOC_UDA134X
 config SND_SOC_UDA1380
         tristate
 
+config SND_SOC_WL1273
+       tristate
+
 config SND_SOC_WM8350
        tristate
 
@@ -227,6 +242,9 @@ config SND_SOC_WM8753
 config SND_SOC_WM8776
        tristate
 
+config SND_SOC_WM8804
+       tristate
+
 config SND_SOC_WM8900
        tristate
 
@@ -248,6 +266,9 @@ config SND_SOC_WM8960
 config SND_SOC_WM8961
        tristate
 
+config SND_SOC_WM8962
+       tristate
+
 config SND_SOC_WM8971
        tristate
 
@@ -257,6 +278,9 @@ config SND_SOC_WM8974
 config SND_SOC_WM8978
        tristate
 
+config SND_SOC_WM8985
+       tristate
+
 config SND_SOC_WM8988
        tristate
 
index 5352409..f67a2d6 100644 (file)
@@ -1,3 +1,4 @@
+snd-soc-88pm860x-objs := 88pm860x-codec.o
 snd-soc-ac97-objs := ac97.o
 snd-soc-ad1836-objs := ad1836.o
 snd-soc-ad193x-objs := ad193x.o
@@ -14,6 +15,7 @@ snd-soc-cs4270-objs := cs4270.o
 snd-soc-cx20442-objs := cx20442.o
 snd-soc-da7210-objs := da7210.o
 snd-soc-l3-objs := l3.o
+snd-soc-max98088-objs := max98088.o
 snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
@@ -26,6 +28,7 @@ snd-soc-twl4030-objs := twl4030.o
 snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
+snd-soc-wl1273-objs := wl1273.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
@@ -39,6 +42,7 @@ snd-soc-wm8741-objs := wm8741.o
 snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm8776-objs := wm8776.o
+snd-soc-wm8804-objs := wm8804.o
 snd-soc-wm8900-objs := wm8900.o
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8904-objs := wm8904.o
@@ -46,9 +50,11 @@ snd-soc-wm8940-objs := wm8940.o
 snd-soc-wm8955-objs := wm8955.o
 snd-soc-wm8960-objs := wm8960.o
 snd-soc-wm8961-objs := wm8961.o
+snd-soc-wm8962-objs := wm8962.o
 snd-soc-wm8971-objs := wm8971.o
 snd-soc-wm8974-objs := wm8974.o
 snd-soc-wm8978-objs := wm8978.o
+snd-soc-wm8985-objs := wm8985.o
 snd-soc-wm8988-objs := wm8988.o
 snd-soc-wm8990-objs := wm8990.o
 snd-soc-wm8993-objs := wm8993.o
@@ -66,6 +72,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-wm2000-objs := wm2000.o
 snd-soc-wm9090-objs := wm9090.o
 
+obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_AD1836)   += snd-soc-ad1836.o
 obj-$(CONFIG_SND_SOC_AD193X)   += snd-soc-ad193x.o
@@ -83,6 +90,7 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
 obj-$(CONFIG_SND_SOC_DA7210)   += snd-soc-da7210.o
 obj-$(CONFIG_SND_SOC_L3)       += snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)     += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
@@ -95,6 +103,7 @@ obj-$(CONFIG_SND_SOC_TWL4030)        += snd-soc-twl4030.o
 obj-$(CONFIG_SND_SOC_TWL6040)  += snd-soc-twl6040.o
 obj-$(CONFIG_SND_SOC_UDA134X)  += snd-soc-uda134x.o
 obj-$(CONFIG_SND_SOC_UDA1380)  += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.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
@@ -108,6 +117,7 @@ obj-$(CONFIG_SND_SOC_WM8741)        += snd-soc-wm8741.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_WM8804)   += snd-soc-wm8804.o
 obj-$(CONFIG_SND_SOC_WM8900)   += snd-soc-wm8900.o
 obj-$(CONFIG_SND_SOC_WM8903)   += snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8904)   += snd-soc-wm8904.o
@@ -115,9 +125,11 @@ obj-$(CONFIG_SND_SOC_WM8940)       += snd-soc-wm8940.o
 obj-$(CONFIG_SND_SOC_WM8955)   += snd-soc-wm8955.o
 obj-$(CONFIG_SND_SOC_WM8960)   += snd-soc-wm8960.o
 obj-$(CONFIG_SND_SOC_WM8961)   += snd-soc-wm8961.o
+obj-$(CONFIG_SND_SOC_WM8962)   += snd-soc-wm8962.o
 obj-$(CONFIG_SND_SOC_WM8971)   += snd-soc-wm8971.o
 obj-$(CONFIG_SND_SOC_WM8974)   += snd-soc-wm8974.o
 obj-$(CONFIG_SND_SOC_WM8978)   += snd-soc-wm8978.o
+obj-$(CONFIG_SND_SOC_WM8985)   += snd-soc-wm8985.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
index 1f5e57a..3c08793 100644 (file)
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
-#include "ac97.h"
-
-#define AC97_VERSION "0.6"
 
 static int ac97_prepare(struct snd_pcm_substream *substream,
                        struct snd_soc_dai *dai)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        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 snd_soc_codec *codec = rtd->codec;
 
        int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
                  AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
@@ -46,8 +42,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = {
        .prepare        = ac97_prepare,
 };
 
-struct snd_soc_dai ac97_dai = {
-       .name = "AC97 HiFi",
+static struct snd_soc_dai_driver ac97_dai = {
+       .name = "ac97-hifi",
        .ac97_control = 1,
        .playback = {
                .stream_name = "AC97 Playback",
@@ -63,7 +59,6 @@ struct snd_soc_dai ac97_dai = {
                .formats = SND_SOC_STD_AC97_FMTS,},
        .ops = &ac97_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ac97_dai);
 
 static unsigned int ac97_read(struct snd_soc_codec *codec,
        unsigned int reg)
@@ -78,95 +73,41 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
        return 0;
 }
 
-static int ac97_soc_probe(struct platform_device *pdev)
+static int ac97_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_codec *codec;
        struct snd_ac97_bus *ac97_bus;
        struct snd_ac97_template ac97_template;
-       int i;
-       int ret = 0;
-
-       printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
-
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (!socdev->card->codec)
-               return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->name = "AC97";
-       codec->owner = THIS_MODULE;
-       codec->dai = &ac97_dai;
-       codec->num_dai = 1;
-       codec->write = ac97_write;
-       codec->read = ac97_read;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto err;
+       int ret;
 
        /* add codec as bus device for standard ac97 */
-       ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
+       ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);
        if (ret < 0)
-               goto bus_err;
+               return ret;
 
        memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
        ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
        if (ret < 0)
-               goto bus_err;
-
-       for (i = 0; i < card->num_links; i++) {
-               if (card->dai_link[i].codec_dai->ac97_control) {
-                       snd_ac97_dev_add_pdata(codec->ac97,
-                               card->dai_link[i].cpu_dai->ac97_pdata);
-               }
-       }
+               return ret;
 
        return 0;
-
-bus_err:
-       snd_soc_free_pcms(socdev);
-
-err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
-       return ret;
 }
 
-static int ac97_soc_remove(struct platform_device *pdev)
+static int ac97_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (!codec)
-               return 0;
-
-       snd_soc_free_pcms(socdev);
-       kfree(socdev->card->codec);
-
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_ac97_suspend(socdev->card->codec->ac97);
+       snd_ac97_suspend(codec->ac97);
 
        return 0;
 }
 
-static int ac97_soc_resume(struct platform_device *pdev)
+static int ac97_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_ac97_resume(socdev->card->codec->ac97);
+       snd_ac97_resume(codec->ac97);
 
        return 0;
 }
@@ -175,14 +116,50 @@ static int ac97_soc_resume(struct platform_device *pdev)
 #define ac97_soc_resume NULL
 #endif
 
-struct snd_soc_codec_device soc_codec_dev_ac97 = {
+static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
+       .write =        ac97_write,
+       .read =         ac97_read,
        .probe =        ac97_soc_probe,
        .remove =       ac97_soc_remove,
        .suspend =      ac97_soc_suspend,
        .resume =       ac97_soc_resume,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
+
+static __devinit int ac97_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_ac97, &ac97_dai, 1);
+}
+
+static int __devexit ac97_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver ac97_codec_driver = {
+       .driver = {
+               .name = "ac97-codec",
+               .owner = THIS_MODULE,
+       },
+
+       .probe = ac97_probe,
+       .remove = __devexit_p(ac97_remove),
+};
+
+static int __init ac97_init(void)
+{
+       return platform_driver_register(&ac97_codec_driver);
+}
+module_init(ac97_init);
+
+static void __exit ac97_exit(void)
+{
+       platform_driver_unregister(&ac97_codec_driver);
+}
+module_exit(ac97_exit);
 
 MODULE_DESCRIPTION("Soc Generic AC97 driver");
 MODULE_AUTHOR("Liam Girdwood");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ac97-codec");
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
deleted file mode 100644 (file)
index 281aa42..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/sound/codecs/ac97.h -- ALSA SoC Layer
- *
- * Author:             Liam Girdwood
- * Created:            Dec 1st 2005
- * Copyright:  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_SOC_AC97_H
-#define __LINUX_SND_SOC_AC97_H
-
-extern struct snd_soc_codec_device soc_codec_dev_ac97;
-extern struct snd_soc_dai ac97_dai;
-
-#endif
index a01006c..d272534 100644 (file)
 
 /* codec private data */
 struct ad1836_priv {
-       struct snd_soc_codec codec;
-       u16 reg_cache[AD1836_NUM_REGS];
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
-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
  */
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
        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;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* bit size */
        switch (params_format(params)) {
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
 }
 
 #ifdef CONFIG_PM
-static int ad1836_soc_suspend(struct platform_device *pdev,
+static int ad1836_soc_suspend(struct snd_soc_codec *codec,
                pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        /* reset clock control mode */
        u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
        adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
        return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
 }
 
-static int ad1836_soc_resume(struct platform_device *pdev)
+static int ad1836_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        /* restore clock control mode */
        u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
        adc_ctrl2 |= AD1836_ADC_AUX;
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
 #define ad1836_soc_resume  NULL
 #endif
 
-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",
-               .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",
+static struct snd_soc_dai_driver ad1836_dai = {
+       .name = "ad1836-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
        },
        .ops = &ad1836_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ad1836_dai);
 
-static int ad1836_register(struct ad1836_priv *ad1836)
+static int ad1836_probe(struct snd_soc_codec *codec)
 {
-       int ret;
-       struct snd_soc_codec *codec = &ad1836->codec;
-
-       if (ad1836_codec) {
-               dev_err(codec->dev, "Another ad1836 is registered\n");
-               kfree(ad1836);
-               return -EINVAL;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       snd_soc_codec_set_drvdata(codec, 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;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       ad1836_dai.dev = codec->dev;
-       ad1836_codec = codec;
+       struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
 
+       codec->control_data = ad1836->control_data;
        ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
        if (ret < 0) {
                dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
        snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
        snd_soc_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));
 
-pcm_err:
        return ret;
 }
 
 /* power down chip */
-static int ad1836_remove(struct platform_device *pdev)
+static int ad1836_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       /* reset clock control mode */
+       u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
+       adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
 
-       return 0;
+       return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
 }
 
-struct snd_soc_codec_device soc_codec_dev_ad1836 = {
+static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
        .probe =        ad1836_probe,
        .remove =       ad1836_remove,
        .suspend =      ad1836_soc_suspend,
        .resume =       ad1836_soc_resume,
+       .reg_cache_size = AD1836_NUM_REGS,
+       .reg_word_size = sizeof(u16),
+};
+
+static int __devinit ad1836_spi_probe(struct spi_device *spi)
+{
+       struct ad1836_priv *ad1836;
+       int ret;
+
+       ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
+       if (ad1836 == NULL)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, ad1836);
+       ad1836->control_data = spi;
+       ad1836->control_type = SND_SOC_SPI;
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_ad1836, &ad1836_dai, 1);
+       if (ret < 0)
+               kfree(ad1836);
+       return ret;
+}
+
+static int __devexit ad1836_spi_remove(struct spi_device *spi)
+{
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
+}
+
+static struct spi_driver ad1836_spi_driver = {
+       .driver = {
+               .name   = "ad1836-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ad1836_spi_probe,
+       .remove         = __devexit_p(ad1836_spi_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
 
 static int __init ad1836_init(void)
 {
index e9d90d3..8455967 100644 (file)
@@ -60,6 +60,4 @@
 
 #define AD1836_NUM_REGS                16
 
-extern struct snd_soc_dai ad1836_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad1836;
 #endif
index 1def75e..fa2834c 100644 (file)
 
 /* codec private data */
 struct ad193x_priv {
-       unsigned int sysclk;
-       struct snd_soc_codec codec;
        u8 reg_cache[AD193X_NUM_REGS];
+       enum snd_soc_control_type bus_type;
+       void *control_data;
+       int sysclk;
 };
 
 /* ad193x register cache & default register settings */
@@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = {
        0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
 };
 
-static struct snd_soc_codec *ad193x_codec;
-struct snd_soc_codec_device soc_codec_dev_ad193x;
-
 /*
  * AD193X volume/mute/de-emphasis etc. controls
  */
@@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
        int word_len = 0, reg = 0, master_rate = 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;
+       struct snd_soc_codec *codec = rtd->codec;
        struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
 
        /* bit size */
@@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
-{
-       struct snd_soc_codec *codec;
-       struct ad193x_priv *ad193x;
-       int ret;
-
-       if (ad193x_codec) {
-               dev_err(dev, "Another ad193x is registered\n");
-               return -EINVAL;
-       }
-
-       ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
-       if (ad193x == NULL)
-               return -ENOMEM;
-
-       dev_set_drvdata(dev, ad193x);
-
-       codec = &ad193x->codec;
-       mutex_init(&codec->mutex);
-       codec->control_data = ctrl_data;
-       codec->dev = dev;
-       snd_soc_codec_set_drvdata(codec, ad193x);
-       codec->reg_cache = ad193x->reg_cache;
-       codec->reg_cache_size = AD193X_NUM_REGS;
-       codec->name = "AD193X";
-       codec->owner = THIS_MODULE;
-       codec->dai = &ad193x_dai;
-       codec->num_dai = 1;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       ad193x_dai.dev = codec->dev;
-       ad193x_codec = codec;
-
-       memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
-
-       if (bus_type == SND_SOC_I2C)
-               ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
-       else
-               ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
-       if (ret < 0) {
-               dev_err(codec->dev, "failed to set cache I/O: %d\n",
-                               ret);
-               kfree(ad193x);
-               return ret;
-       }
-
-       /* default setting for ad193x */
-
-       /* unmute dac channels */
-       snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
-       /* de-emphasis: 48kHz, powedown dac */
-       snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
-       /* powerdown dac, dac in tdm mode */
-       snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
-       /* high-pass filter enable */
-       snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
-       /* sata delay=1, adc aux mode */
-       snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
-       /* pll input: mclki/xi */
-       snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
-       snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
-       ad193x->sysclk = 12288000;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               kfree(ad193x);
-               return ret;
-       }
-
-       ret = snd_soc_register_dai(&ad193x_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               kfree(ad193x);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int ad193x_bus_remove(struct device *dev)
-{
-       struct ad193x_priv *ad193x = dev_get_drvdata(dev);
-
-       snd_soc_unregister_dai(&ad193x_dai);
-       snd_soc_unregister_codec(&ad193x->codec);
-       kfree(ad193x);
-       ad193x_codec = NULL;
-
-       return 0;
-}
-
 static struct snd_soc_dai_ops ad193x_dai_ops = {
        .hw_params = ad193x_hw_params,
        .digital_mute = ad193x_mute,
@@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {
 };
 
 /* codec DAI instance */
-struct snd_soc_dai ad193x_dai = {
-       .name = "AD193X",
+static struct snd_soc_dai_driver ad193x_dai = {
+       .name = "ad193x-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = {
        },
        .ops = &ad193x_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ad193x_dai);
 
-static int ad193x_probe(struct platform_device *pdev)
+static int ad193x_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
+       struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       if (ad193x_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       codec->control_data = ad193x->control_data;
+       if (ad193x->bus_type == SND_SOC_I2C)
+               ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type);
+       else
+               ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to set cache I/O: %d\n",
+                               ret);
+               kfree(ad193x);
+               return ret;
        }
 
-       socdev->card->codec = ad193x_codec;
-       codec = ad193x_codec;
+       /* default setting for ad193x */
 
-       /* 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;
-       }
+       /* unmute dac channels */
+       snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
+       /* de-emphasis: 48kHz, powedown dac */
+       snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
+       /* powerdown dac, dac in tdm mode */
+       snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
+       /* high-pass filter enable */
+       snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
+       /* sata delay=1, adc aux mode */
+       snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
+       /* pll input: mclki/xi */
+       snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
+       snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
 
        snd_soc_add_controls(codec, ad193x_snd_controls,
                             ARRAY_SIZE(ad193x_snd_controls));
@@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev)
                                  ARRAY_SIZE(ad193x_dapm_widgets));
        snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
 
-pcm_err:
        return ret;
 }
 
-/* power down chip */
-static int ad193x_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_ad193x = {
+static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
        .probe =        ad193x_probe,
-       .remove =       ad193x_remove,
+       .reg_cache_default = ad193x_reg,
+       .reg_cache_size = AD193X_NUM_REGS,
+       .reg_word_size = sizeof(u16),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
 
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit ad193x_spi_probe(struct spi_device *spi)
 {
-       return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI);
+       struct ad193x_priv *ad193x;
+       int ret;
+
+       ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+       if (ad193x == NULL)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, ad193x);
+       ad193x->control_data = spi;
+       ad193x->bus_type = SND_SOC_SPI;
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_ad193x, &ad193x_dai, 1);
+       if (ret < 0)
+               kfree(ad193x);
+       return ret;
 }
 
 static int __devexit ad193x_spi_remove(struct spi_device *spi)
 {
-       return ad193x_bus_remove(&spi->dev);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
 }
 
 static struct spi_driver ad193x_spi_driver = {
        .driver = {
-               .name   = "ad193x",
+               .name   = "ad193x-codec",
                .owner  = THIS_MODULE,
        },
        .probe          = ad193x_spi_probe,
@@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);
 static int __devinit ad193x_i2c_probe(struct i2c_client *client,
                const struct i2c_device_id *id)
 {
-       return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C);
+       struct ad193x_priv *ad193x;
+       int ret;
+
+       ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+       if (ad193x == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, ad193x);
+       ad193x->control_data = client;
+       ad193x->bus_type = SND_SOC_I2C;
+
+       ret =  snd_soc_register_codec(&client->dev,
+                       &soc_codec_dev_ad193x, &ad193x_dai, 1);
+       if (ret < 0)
+               kfree(ad193x);
+       return ret;
 }
 
 static int __devexit ad193x_i2c_remove(struct i2c_client *client)
 {
-       return ad193x_bus_remove(&client->dev);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
 }
 
 static struct i2c_driver ad193x_i2c_driver = {
        .driver = {
-               .name = "ad193x",
+               .name = "ad193x-codec",
        },
        .probe    = ad193x_i2c_probe,
        .remove   = __devexit_p(ad193x_i2c_remove),
index 654ba64..9747b54 100644 (file)
@@ -80,7 +80,4 @@
 
 #define AD193X_NUM_REGS          17
 
-extern struct snd_soc_dai ad193x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad193x;
-
 #endif
index 70cfaec..410ccd5 100644 (file)
 
 #include "ad1980.h"
 
-static unsigned int ac97_read(struct snd_soc_codec *codec,
-       unsigned int reg);
-static int ac97_write(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int val);
-
 /*
  * AD1980 register cache
  */
@@ -138,8 +133,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
        return 0;
 }
 
-struct snd_soc_dai ad1980_dai = {
-       .name = "AC97",
+static struct snd_soc_dai_driver ad1980_dai = {
+       .name = "ad1980-hifi",
        .ac97_control = 1,
        .playback = {
                .stream_name = "Playback",
@@ -185,53 +180,20 @@ err:
        return -EIO;
 }
 
-static int ad1980_soc_probe(struct platform_device *pdev)
+static int ad1980_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
+       int ret;
        u16 vendor_id2;
        u16 ext_status;
 
        printk(KERN_INFO "AD1980 SoC Audio Codec\n");
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (socdev->card->codec == NULL)
-               return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache =
-               kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-       memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
-                       ARRAY_SIZE(ad1980_reg));
-       codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
-       codec->reg_cache_step = 2;
-       codec->name = "AD1980";
-       codec->owner = THIS_MODULE;
-       codec->dai = &ad1980_dai;
-       codec->num_dai = 1;
-       codec->write = ac97_write;
-       codec->read = ac97_read;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0) {
                printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
-               goto codec_err;
+               return ret;
        }
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
-
        ret = ad1980_reset(codec, 0);
        if (ret < 0) {
                printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
@@ -270,41 +232,60 @@ static int ad1980_soc_probe(struct platform_device *pdev)
        return 0;
 
 reset_err:
-       snd_soc_free_pcms(socdev);
-
-pcm_err:
        snd_soc_free_ac97_codec(codec);
-
-codec_err:
-       kfree(codec->reg_cache);
-
-cache_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
        return ret;
 }
 
-static int ad1980_soc_remove(struct platform_device *pdev)
+static int ad1980_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-
-       snd_soc_dapm_free(socdev);
-       snd_soc_free_pcms(socdev);
        snd_soc_free_ac97_codec(codec);
-       kfree(codec->reg_cache);
-       kfree(codec);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_ad1980 = {
+static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
        .probe =        ad1980_soc_probe,
        .remove =       ad1980_soc_remove,
+       .reg_cache_size = ARRAY_SIZE(ad1980_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = ad1980_reg,
+       .reg_cache_step = 2,
+       .write = ac97_write,
+       .read = ac97_read,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980);
+
+static __devinit int ad1980_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_ad1980, &ad1980_dai, 1);
+}
+
+static int __devexit ad1980_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver ad1980_codec_driver = {
+       .driver = {
+                       .name = "ad1980-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = ad1980_probe,
+       .remove = __devexit_p(ad1980_remove),
+};
+
+static int __init ad1980_init(void)
+{
+       return platform_driver_register(&ad1980_codec_driver);
+}
+module_init(ad1980_init);
+
+static void __exit ad1980_exit(void)
+{
+       platform_driver_unregister(&ad1980_codec_driver);
+}
+module_exit(ad1980_exit);
 
 MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
 MODULE_AUTHOR("Roy Huang, Cliff Cai");
index 538f37c..eb0af44 100644 (file)
@@ -23,7 +23,4 @@
 #define PR5            0x2000
 #define PR6            0x4000
 
-extern struct snd_soc_dai ad1980_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad1980;
-
 #endif
index 475807b..c53955f 100644 (file)
@@ -23,8 +23,8 @@
 
 #include "ad73311.h"
 
-struct snd_soc_dai ad73311_dai = {
-       .name = "AD73311",
+static struct snd_soc_dai_driver ad73311_dai = {
+       .name = "ad73311-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {
                .rates = SNDRV_PCM_RATE_8000,
                .formats = SNDRV_PCM_FMTBIT_S16_LE, },
 };
-EXPORT_SYMBOL_GPL(ad73311_dai);
 
-static int ad73311_soc_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-       mutex_init(&codec->mutex);
-       codec->name = "AD73311";
-       codec->owner = THIS_MODULE;
-       codec->dai = &ad73311_dai;
-       codec->num_dai = 1;
-       socdev->card->codec = codec;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "ad73311: failed to create pcms\n");
-               goto pcm_err;
-       }
-
-       return ret;
+static struct snd_soc_codec_driver soc_codec_dev_ad73311;
 
-pcm_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
-       return ret;
+static int ad73311_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_ad73311, &ad73311_dai, 1);
 }
 
-static int ad73311_soc_remove(struct platform_device *pdev)
+static int ad73311_remove(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-       snd_soc_free_pcms(socdev);
-       kfree(codec);
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_ad73311 = {
-       .probe =        ad73311_soc_probe,
-       .remove =       ad73311_soc_remove,
+static struct platform_driver ad73311_codec_driver = {
+       .driver = {
+                       .name = "ad73311-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = ad73311_probe,
+       .remove = __devexit_p(ad73311_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
 
 static int __init ad73311_init(void)
 {
-       return snd_soc_register_dai(&ad73311_dai);
+       return platform_driver_register(&ad73311_codec_driver);
 }
 module_init(ad73311_init);
 
 static void __exit ad73311_exit(void)
 {
-       snd_soc_unregister_dai(&ad73311_dai);
+       platform_driver_unregister(&ad73311_codec_driver);
 }
 module_exit(ad73311_exit);
 
index 569573d..4b353ee 100644 (file)
@@ -85,6 +85,4 @@
 #define REGF_INV               (1 << 6)
 #define REGF_ALB               (1 << 7)
 
-extern struct snd_soc_dai ad73311_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ad73311;
 #endif
index f8e75ed..8402854 100644 (file)
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include "ads117x.h"
-
 #define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
-
 #define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
 
-struct snd_soc_dai ads117x_dai = {
+static struct snd_soc_dai_driver ads117x_dai = {
 /* ADC */
-       .name = "ADS117X ADC",
-       .id = 1,
+       .name = "ads117x-hifi",
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
@@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {
                .rates = ADS117X_RATES,
                .formats = ADS117X_FORMATS,},
 };
-EXPORT_SYMBOL_GPL(ads117x_dai);
-
-static int ads117x_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
 
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       codec->name = "ADS117X";
-       codec->owner = THIS_MODULE;
-       codec->dai = &ads117x_dai;
-       codec->num_dai = 1;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "ads117x: failed to create pcms\n");
-               kfree(codec);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int ads117x_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       snd_soc_free_pcms(socdev);
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ads117x = {
-       .probe =        ads117x_probe,
-       .remove =       ads117x_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x);
+static struct snd_soc_codec_driver soc_codec_dev_ads117x;
 
-static __devinit int ads117x_platform_probe(struct platform_device *pdev)
+static __devinit int ads117x_probe(struct platform_device *pdev)
 {
-       ads117x_dai.dev = &pdev->dev;
-       return snd_soc_register_dai(&ads117x_dai);
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_ads117x, &ads117x_dai, 1);
 }
 
-static int __devexit ads117x_platform_remove(struct platform_device *pdev)
+static int __devexit ads117x_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&ads117x_dai);
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver ads117x_codec_driver = {
        .driver = {
-                       .name = "ads117x",
+                       .name = "ads117x-codec",
                        .owner = THIS_MODULE,
        },
 
-       .probe = ads117x_platform_probe,
-       .remove = __devexit_p(ads117x_platform_remove),
+       .probe = ads117x_probe,
+       .remove = __devexit_p(ads117x_remove),
 };
 
 static int __init ads117x_init(void)
index dbcf50e..3ce0286 100644 (file)
@@ -9,5 +9,5 @@
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
  */
-extern struct snd_soc_dai ads117x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ads117x;
+extern struct snd_soc_dai_driver ads117x_dai;
+extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
index 192aebd..c27f8f5 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/spi/spi.h>
 #include <sound/asoundef.h>
 
-#include "ak4104.h"
-
 /* AK4104 registers addresses */
 #define AK4104_REG_CONTROL1            0x00
 #define AK4104_REG_RESERVED            0x01
 #define AK4104_TX_TXE                  (1 << 0)
 #define AK4104_TX_V                    (1 << 1)
 
-#define DRV_NAME "ak4104"
+#define DRV_NAME "ak4104-codec"
 
 struct ak4104_private {
-       struct snd_soc_codec codec;
-       u8 reg_cache[AK4104_NUM_REGS];
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 static int ak4104_fill_cache(struct snd_soc_codec *codec)
@@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec)
        u8 *reg_cache = codec->reg_cache;
        struct spi_device *spi = codec->control_data;
 
-       for (i = 0; i < codec->reg_cache_size; i++) {
+       for (i = 0; i < codec->driver->reg_cache_size; i++) {
                int ret = spi_w8r8(spi, i | AK4104_READ);
                if (ret < 0) {
                        dev_err(&spi->dev, "SPI write failure\n");
@@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
 {
        u8 *reg_cache = codec->reg_cache;
 
-       if (reg >= codec->reg_cache_size)
+       if (reg >= codec->driver->reg_cache_size)
                return -EINVAL;
 
        return reg_cache[reg];
@@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
        u8 *cache = codec->reg_cache;
        struct spi_device *spi = codec->control_data;
 
-       if (reg >= codec->reg_cache_size)
+       if (reg >= codec->driver->reg_cache_size)
                return -EINVAL;
 
        /* only write to the hardware if value has changed */
@@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        int val = 0;
 
        /* set the IEC958 bits: consumer mode, no copyright bit */
@@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = {
        .set_fmt = ak4104_set_dai_fmt,
 };
 
-struct snd_soc_dai ak4104_dai = {
-       .name = DRV_NAME,
+static struct snd_soc_dai_driver ak4104_dai = {
+       .name = "ak4104-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = {
        .ops = &ak4101_dai_ops,
 };
 
-static struct snd_soc_codec *ak4104_codec;
-
-static int ak4104_spi_probe(struct spi_device *spi)
+static int ak4104_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec;
-       struct ak4104_private *ak4104;
+       struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
        int ret, val;
 
-       spi->bits_per_word = 8;
-       spi->mode = SPI_MODE_0;
-       ret = spi_setup(spi);
-       if (ret < 0)
-               return ret;
-
-       ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
-       if (!ak4104) {
-               dev_err(&spi->dev, "could not allocate codec\n");
-               return -ENOMEM;
-       }
-
-       codec = &ak4104->codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->dev = &spi->dev;
-       codec->name = DRV_NAME;
-       codec->owner = THIS_MODULE;
-       codec->dai = &ak4104_dai;
-       codec->num_dai = 1;
-       snd_soc_codec_set_drvdata(codec, ak4104);
-       codec->control_data = spi;
-       codec->reg_cache = ak4104->reg_cache;
-       codec->reg_cache_size = AK4104_NUM_REGS;
+       codec->control_data = ak4104->control_data;
 
        /* read all regs and fill the cache */
        ret = ak4104_fill_cache(codec);
        if (ret < 0) {
-               dev_err(&spi->dev, "failed to fill register cache\n");
+               dev_err(codec->dev, "failed to fill register cache\n");
                return ret;
        }
 
@@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi)
         * should contain 0x5b. Not a good way to verify the presence of
         * the device, but there is no hardware ID register. */
        if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
-                                        AK4104_RESERVED_VAL) {
-               ret = -ENODEV;
-               goto error_free_codec;
-       }
+                                        AK4104_RESERVED_VAL)
+               return -ENODEV;
 
        /* set power-up and non-reset bits */
        val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
        val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
        ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
        if (ret < 0)
-               goto error_free_codec;
+               return ret;
 
        /* enable transmitter */
        val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
        val |= AK4104_TX_TXE;
        ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
        if (ret < 0)
-               goto error_free_codec;
-
-       ak4104_codec = codec;
-       ret = snd_soc_register_dai(&ak4104_dai);
-       if (ret < 0) {
-               dev_err(&spi->dev, "failed to register DAI\n");
-               goto error_free_codec;
-       }
+               return ret;
 
-       spi_set_drvdata(spi, ak4104);
-       dev_info(&spi->dev, "SPI device initialized\n");
+       dev_info(codec->dev, "SPI device initialized\n");
        return 0;
-
-error_free_codec:
-       kfree(ak4104);
-       ak4104_dai.dev = NULL;
-       return ret;
 }
 
-static int __devexit ak4104_spi_remove(struct spi_device *spi)
+static int ak4104_remove(struct snd_soc_codec *codec)
 {
-       int ret, val;
-       struct ak4104_private *ak4104 = spi_get_drvdata(spi);
+       int val, ret;
 
-       val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1);
+       val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
        if (val < 0)
                return val;
 
        /* clear power-up and non-reset bits */
        val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
-       ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val);
-       if (ret < 0)
-               return ret;
+       ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
 
-       ak4104_codec = NULL;
-       kfree(ak4104);
-       return 0;
+       return ret;
 }
 
-static int ak4104_probe(struct platform_device *pdev)
+static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
+       .probe =        ak4104_probe,
+       .remove =       ak4104_remove,
+       .reg_cache_size = AK4104_NUM_REGS,
+       .reg_word_size = sizeof(u16),
+};
+
+static int ak4104_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = ak4104_codec;
+       struct ak4104_private *ak4104;
        int ret;
 
-       /* Connect the codec to the socdev.  snd_soc_new_pcms() needs this. */
-       socdev->card->codec = 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\n");
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_0;
+       ret = spi_setup(spi);
+       if (ret < 0)
                return ret;
-       }
 
-       return 0;
+       ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
+       if (ak4104 == NULL)
+               return -ENOMEM;
+
+       ak4104->control_data = spi;
+       ak4104->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, ak4104);
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_device_ak4104, &ak4104_dai, 1);
+       if (ret < 0)
+               kfree(ak4104);
+       return ret;
 }
 
-static int ak4104_remove(struct platform_device *pdev)
+static int __devexit ak4104_spi_remove(struct spi_device *spi)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       snd_soc_free_pcms(socdev);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
-};
-
-struct snd_soc_codec_device soc_codec_device_ak4104 = {
-       .probe =        ak4104_probe,
-       .remove =       ak4104_remove
-};
-EXPORT_SYMBOL_GPL(soc_codec_device_ak4104);
+}
 
 static struct spi_driver ak4104_spi_driver = {
        .driver  = {
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h
deleted file mode 100644 (file)
index eb88fe7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _AK4104_H
-#define _AK4104_H
-
-extern struct snd_soc_dai ak4104_dai;
-extern struct snd_soc_codec_device soc_codec_device_ak4104;
-
-#endif
index d425367..cd88c8f 100644 (file)
 
 #define AK4535_VERSION "0.3"
 
-struct snd_soc_codec_device soc_codec_dev_ak4535;
-
 /* codec private data */
 struct ak4535_priv {
        unsigned int sysclk;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 /*
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
        u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
        int rate = params_rate(params), fs = 256;
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute)
 static int ak4535_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 i;
+       u16 i, mute_reg;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               ak4535_mute(codec->dai, 0);
+               mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
+               ak4535_write(codec, AK4535_DAC, mute_reg);
                break;
        case SND_SOC_BIAS_PREPARE:
-               ak4535_mute(codec->dai, 1);
+               mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
+               ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
                break;
        case SND_SOC_BIAS_STANDBY:
                i = ak4535_read_reg_cache(codec, AK4535_PM1);
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = {
        .set_sysclk     = ak4535_set_dai_sysclk,
 };
 
-struct snd_soc_dai ak4535_dai = {
-       .name = "AK4535",
+static struct snd_soc_dai_driver ak4535_dai = {
+       .name = "ak4535-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE,},
        .ops = &ak4535_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ak4535_dai);
 
-static int ak4535_suspend(struct platform_device *pdev, pm_message_t state)
+static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int ak4535_resume(struct platform_device *pdev)
+static int ak4535_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        ak4535_sync(codec);
        ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
 
-/*
- * initialise the AK4535 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int ak4535_init(struct snd_soc_device *socdev)
+static int ak4535_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret = 0;
+       struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
 
-       codec->name = "AK4535";
-       codec->owner = THIS_MODULE;
-       codec->read = ak4535_read_reg_cache;
-       codec->write = ak4535_write;
-       codec->set_bias_level = ak4535_set_bias_level;
-       codec->dai = &ak4535_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
-       codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
-
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "ak4535: failed to create pcms\n");
-               goto pcm_err;
-       }
+       codec->control_data = ak4535->control_data;
 
        /* power on device */
        ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev)
                                ARRAY_SIZE(ak4535_snd_controls));
        ak4535_add_widgets(codec);
 
-       return ret;
-
-pcm_err:
-       kfree(codec->reg_cache);
+       return 0;
+}
 
-       return ret;
+/* power down chip */
+static int ak4535_remove(struct snd_soc_codec *codec)
+{
+       ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-static struct snd_soc_device *ak4535_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
+       .probe =        ak4535_probe,
+       .remove =       ak4535_remove,
+       .suspend =      ak4535_suspend,
+       .resume =       ak4535_resume,
+       .read = ak4535_read_reg_cache,
+       .write = ak4535_write,
+       .set_bias_level = ak4535_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(ak4535_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = ak4535_reg,
+};
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-static int ak4535_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = ak4535_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct ak4535_priv *ak4535;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
+       if (ak4535 == NULL)
+               return -ENOMEM;
 
-       ret = ak4535_init(socdev);
-       if (ret < 0)
-               printk(KERN_ERR "failed to initialise AK4535\n");
+       i2c_set_clientdata(i2c, ak4535);
+       ak4535->control_data = i2c;
+       ak4535->control_type = SND_SOC_I2C;
 
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_ak4535, &ak4535_dai, 1);
+       if (ret < 0)
+               kfree(ak4535);
        return ret;
 }
 
-static int ak4535_i2c_remove(struct i2c_client *client)
+static __devexit int ak4535_i2c_remove(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
 
 static struct i2c_driver ak4535_i2c_driver = {
        .driver = {
-               .name = "AK4535 I2C Codec",
+               .name = "ak4535-codec",
                .owner = THIS_MODULE,
        },
        .probe =    ak4535_i2c_probe,
-       .remove =   ak4535_i2c_remove,
+       .remove =   __devexit_p(ak4535_i2c_remove),
        .id_table = ak4535_i2c_id,
 };
-
-static int ak4535_add_i2c_device(struct platform_device *pdev,
-                                const struct ak4535_setup_data *setup)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&ak4535_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "ak4535", 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(&ak4535_i2c_driver);
-       return -ENODEV;
-}
 #endif
 
-static int ak4535_probe(struct platform_device *pdev)
+static int __init ak4535_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct ak4535_setup_data *setup;
-       struct snd_soc_codec *codec;
-       struct ak4535_priv *ak4535;
-       int ret;
-
-       printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
-       if (ak4535 == NULL) {
-               kfree(codec);
-               return -ENOMEM;
-       }
-
-       snd_soc_codec_set_drvdata(codec, ak4535);
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       ak4535_socdev = socdev;
-       ret = -ENODEV;
-
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
-               ret = ak4535_add_i2c_device(pdev, setup);
-       }
-#endif
-
+       ret = i2c_add_driver(&ak4535_i2c_driver);
        if (ret != 0) {
-               kfree(snd_soc_codec_get_drvdata(codec));
-               kfree(codec);
+               printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
+                      ret);
        }
+#endif
        return ret;
 }
+module_init(ak4535_modinit);
 
-/* power down chip */
-static int ak4535_remove(struct platform_device *pdev)
+static void __exit ak4535_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               ak4535_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)
-       if (codec->control_data)
-               i2c_unregister_device(codec->control_data);
        i2c_del_driver(&ak4535_i2c_driver);
 #endif
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ak4535 = {
-       .probe =        ak4535_probe,
-       .remove =       ak4535_remove,
-       .suspend =      ak4535_suspend,
-       .resume =       ak4535_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
-
-static int __init ak4535_modinit(void)
-{
-       return snd_soc_register_dai(&ak4535_dai);
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
-       snd_soc_unregister_dai(&ak4535_dai);
 }
 module_exit(ak4535_exit);
 
index c7a5870..0431e5f 100644 (file)
 
 #define AK4535_CACHEREGNUM     0x10
 
-struct ak4535_setup_data {
-       int            i2c_bus;
-       unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai ak4535_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ak4535;
-
 #endif
index 3d7dc55..90c90b7 100644 (file)
@@ -30,8 +30,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include "ak4642.h"
-
 #define AK4642_VERSION "0.0.1"
 
 #define PW_MGMT1       0x00
 
 #define AK4642_CACHEREGNUM     0x25
 
+/* PW_MGMT1*/
+#define PMVCM          (1 << 6) /* VCOM Power Management */
+#define PMMIN          (1 << 5) /* MIN Input Power Management */
+#define PMDAC          (1 << 2) /* DAC Power Management */
+#define PMADL          (1 << 0) /* MIC Amp Lch and ADC Lch Power Management */
+
 /* PW_MGMT2 */
 #define HPMTN          (1 << 6)
 #define PMHPL          (1 << 5)
 #define PMHP_MASK      (PMHPL | PMHPR)
 #define PMHP           PMHP_MASK
 
+/* PW_MGMT3 */
+#define PMADR          (1 << 0) /* MIC L / ADC R Power Management */
+
+/* SG_SL1 */
+#define MINS           (1 << 6) /* Switch from MIN to Speaker */
+#define DACL           (1 << 4) /* Switch from DAC to Stereo or Receiver */
+#define PMMP           (1 << 2) /* MPWR pin Power Management */
+#define MGAIN0         (1 << 0) /* MIC amp gain*/
+
+/* TIMER */
+#define ZTM(param)     ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */
+#define WTM(param)     (((param & 0x4) << 4) | ((param & 0x3) << 2))
+
+/* ALC_CTL1 */
+#define ALC            (1 << 5) /* ALC Enable */
+#define LMTH0          (1 << 0) /* ALC Limiter / Recovery Level */
+
 /* MD_CTL1 */
 #define PLL3           (1 << 7)
 #define PLL2           (1 << 6)
 #define FS3            (1 << 5)
 #define FS_MASK                (FS0 | FS1 | FS2 | FS3)
 
-struct snd_soc_codec_device soc_codec_dev_ak4642;
+/* MD_CTL3 */
+#define BST1           (1 << 3)
+
+/* MD_CTL4 */
+#define DACH           (1 << 0)
 
 /*
  * Playback Volume (table 39)
@@ -123,11 +148,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
 
 /* codec private data */
 struct ak4642_priv {
-       struct snd_soc_codec codec;
+       unsigned int sysclk;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
-static struct snd_soc_codec *ak4642_codec;
-
 /*
  * ak4642 register cache
  */
@@ -219,11 +244,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                 * This operation came from example code of
                 * "ASAHI KASEI AK4642" (japanese) manual p97.
                 */
-               ak4642_write(codec, 0x0f, 0x09);
-               ak4642_write(codec, 0x0e, 0x19);
-               ak4642_write(codec, 0x09, 0x91);
-               ak4642_write(codec, 0x0c, 0x91);
-               ak4642_write(codec, 0x00, 0x64);
+               snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
+               snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
+               ak4642_write(codec, L_IVC, 0x91); /* volume */
+               ak4642_write(codec, R_IVC, 0x91); /* volume */
+               snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
+                                                    PMVCM | PMMIN | PMDAC);
                snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
                snd_soc_update_bits(codec, PW_MGMT2, HPMTN,     HPMTN);
        } else {
@@ -240,13 +266,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
                 * This operation came from example code of
                 * "ASAHI KASEI AK4642" (japanese) manual p94.
                 */
-               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);
+               ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
+               ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
+               ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
+               snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
+                                                    PMVCM | PMADL);
+               snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
        }
 
        return 0;
@@ -262,14 +287,14 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
                /* stop headphone output */
                snd_soc_update_bits(codec, PW_MGMT2, HPMTN,     0);
                snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
-               ak4642_write(codec, 0x00, 0x40);
-               ak4642_write(codec, 0x0e, 0x11);
-               ak4642_write(codec, 0x0f, 0x08);
+               snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
+               snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
+               snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
        } else {
                /* stop stereo input */
-               ak4642_write(codec, 0x00, 0x40);
-               ak4642_write(codec, 0x10, 0x00);
-               ak4642_write(codec, 0x07, 0x01);
+               snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
+               snd_soc_update_bits(codec, PW_MGMT3, PMADR, 0);
+               snd_soc_update_bits(codec, ALC_CTL1, ALC, 0);
        }
 }
 
@@ -393,8 +418,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
        .hw_params      = ak4642_dai_hw_params,
 };
 
-struct snd_soc_dai ak4642_dai = {
-       .name = "AK4642",
+static struct snd_soc_dai_driver ak4642_dai = {
+       .name = "ak4642-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -410,112 +435,65 @@ struct snd_soc_dai ak4642_dai = {
        .ops = &ak4642_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(ak4642_dai);
 
-static int ak4642_resume(struct platform_device *pdev)
+static int ak4642_resume(struct snd_soc_codec *codec)
 {
-       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)
+
+static int ak4642_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &ak4642->codec;
-       int ret = 0;
+       struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
 
-       if (ak4642_codec) {
-               dev_err(codec->dev, "Another ak4642 is registered\n");
-               return -EINVAL;
-       }
+       dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, 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);
+       codec->control_data     = ak4642->control_data;
 
-       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;
-       }
-
-       return ret;
-
-reg_cache_err:
-       kfree(codec->reg_cache);
-       codec->reg_cache = NULL;
+       snd_soc_add_controls(codec, ak4642_snd_controls,
+                            ARRAY_SIZE(ak4642_snd_controls));
 
-       return ret;
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
+       .probe                  = ak4642_probe,
+       .resume                 = ak4642_resume,
+       .read                   = ak4642_read_reg_cache,
+       .write                  = ak4642_write,
+       .reg_cache_size         = ARRAY_SIZE(ak4642_reg),
+       .reg_word_size          = sizeof(u8),
+       .reg_cache_default      = ak4642_reg,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int ak4642_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static __devinit 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;
+       ak4642->control_data = i2c;
+       ak4642->control_type = SND_SOC_I2C;
 
-       ret = ak4642_init(ak4642);
-       if (ret < 0) {
-               printk(KERN_ERR "failed to initialise AK4642\n");
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_ak4642, &ak4642_dai, 1);
+       if (ret < 0)
                kfree(ak4642);
-       }
-
        return ret;
 }
 
-static int ak4642_i2c_remove(struct i2c_client *client)
+static __devexit 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;
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -528,64 +506,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
 
 static struct i2c_driver ak4642_i2c_driver = {
        .driver = {
-               .name = "AK4642 I2C Codec",
+               .name = "ak4642-codec",
                .owner = THIS_MODULE,
        },
        .probe          = ak4642_i2c_probe,
-       .remove         = ak4642_i2c_remove,
+       .remove         = __devexit_p(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;
-       }
-
-       snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
-                            ARRAY_SIZE(ak4642_snd_controls));
-
-       dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
-       return ret;
-
-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 = 0;
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h
deleted file mode 100644 (file)
index e476833..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * ak4642.h  --  AK4642 Soc Audio driver
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * 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
index 8756693..24f5f49 100644 (file)
 
 #include "ak4671.h"
 
-static struct snd_soc_codec *ak4671_codec;
 
 /* codec private data */
 struct ak4671_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        u8 reg_cache[AK4671_CACHEREGNUM];
 };
 
@@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
        .set_fmt        = ak4671_set_dai_fmt,
 };
 
-struct snd_soc_dai ak4671_dai = {
-       .name = "AK4671",
+static struct snd_soc_dai_driver ak4671_dai = {
+       .name = "ak4671-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -635,27 +635,18 @@ struct snd_soc_dai ak4671_dai = {
                .formats = AK4671_FORMATS,},
        .ops = &ak4671_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ak4671_dai);
 
-static int ak4671_probe(struct platform_device *pdev)
+static int ak4671_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (ak4671_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
+       struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       socdev->card->codec = ak4671_codec;
-       codec = ak4671_codec;
+       codec->hw_write = (hw_write_t)i2c_master_send;
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
        if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
        snd_soc_add_controls(codec, ak4671_snd_controls,
@@ -665,121 +656,48 @@ static int ak4671_probe(struct platform_device *pdev)
        ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return ret;
-
-pcm_err:
-       return ret;
 }
 
-static int ak4671_remove(struct platform_device *pdev)
+static int ak4671_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_ak4671 = {
+static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
        .probe = ak4671_probe,
        .remove = ak4671_remove,
+       .set_bias_level = ak4671_set_bias_level,
+       .reg_cache_size = AK4671_CACHEREGNUM,
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = ak4671_reg,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
-
-static int ak4671_register(struct ak4671_priv *ak4671,
-               enum snd_soc_control_type control)
-{
-       int ret;
-       struct snd_soc_codec *codec = &ak4671->codec;
-
-       if (ak4671_codec) {
-               dev_err(codec->dev, "Another AK4671 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec,  ak4671);
-       codec->name = "AK4671";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = ak4671_set_bias_level;
-       codec->dai = &ak4671_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = AK4671_CACHEREGNUM;
-       codec->reg_cache = &ak4671->reg_cache;
-
-       memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
-
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
-       }
-
-       ak4671_dai.dev = codec->dev;
-       ak4671_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(&ak4671_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(ak4671);
-       return ret;
-}
-
-static void ak4671_unregister(struct ak4671_priv *ak4671)
-{
-       ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&ak4671_dai);
-       snd_soc_unregister_codec(&ak4671->codec);
-       kfree(ak4671);
-       ak4671_codec = NULL;
-}
 
 static int __devinit ak4671_i2c_probe(struct i2c_client *client,
                const struct i2c_device_id *id)
 {
        struct ak4671_priv *ak4671;
-       struct snd_soc_codec *codec;
+       int ret;
 
        ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
        if (ak4671 == NULL)
                return -ENOMEM;
 
-       codec = &ak4671->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        i2c_set_clientdata(client, ak4671);
-       codec->control_data = client;
-
-       codec->dev = &client->dev;
+       ak4671->control_data = client;
+       ak4671->control_type = SND_SOC_I2C;
 
-       return ak4671_register(ak4671, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&client->dev,
+                       &soc_codec_dev_ak4671, &ak4671_dai, 1);
+       if (ret < 0)
+               kfree(ak4671);
+       return ret;
 }
 
 static __devexit int ak4671_i2c_remove(struct i2c_client *client)
 {
-       struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
-
-       ak4671_unregister(ak4671);
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -791,7 +709,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
 
 static struct i2c_driver ak4671_i2c_driver = {
        .driver = {
-               .name = "ak4671",
+               .name = "ak4671-codec",
                .owner = THIS_MODULE,
        },
        .probe = ak4671_i2c_probe,
index e2fad96..61cb7ab 100644 (file)
 /* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
 #define AK4671_MUTEN                           0x04
 
-extern struct snd_soc_dai ak4671_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ak4671;
-
 #endif
index a320fb5..8236439 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/mfd/davinci_voicecodec.h>
+#include <linux/spi/spi.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -41,8 +42,6 @@
 
 #include <mach/dm365.h>
 
-#include "cq93vc.h"
-
 static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
                                                unsigned int reg)
 {
@@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {
        .set_sysclk     = cq93vc_set_dai_sysclk,
 };
 
-struct snd_soc_dai cq93vc_dai = {
-       .name = "CQ93VC",
+static struct snd_soc_dai_driver cq93vc_dai = {
+       .name = "cq93vc-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {
                .formats = CQ93VC_FORMATS,},
        .ops = &cq93vc_dai_ops,
 };
-EXPORT_SYMBOL_GPL(cq93vc_dai);
 
-static int cq93vc_resume(struct platform_device *pdev)
+static int cq93vc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
 
-static struct snd_soc_codec *cq93vc_codec;
-
-static int cq93vc_probe(struct platform_device *pdev)
+static int cq93vc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct device *dev = &pdev->dev;
-       struct snd_soc_codec *codec;
-       int ret;
-
-       socdev->card->codec = cq93vc_codec;
-       codec = socdev->card->codec;
-
-       /* Register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               dev_err(dev, "%s: failed to create pcms\n", pdev->name);
-               return ret;
-       }
+       struct davinci_vc *davinci_vc = codec->dev->platform_data;
+
+       davinci_vc->cq93vc.codec = codec;
+       codec->control_data = davinci_vc;
 
        /* Set controls */
        snd_soc_add_controls(codec, cq93vc_snd_controls,
@@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int cq93vc_remove(struct platform_device *pdev)
+static int cq93vc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_cq93vc = {
+static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
+       .read = cq93vc_read,
+       .write = cq93vc_write,
+       .set_bias_level = cq93vc_set_bias_level,
        .probe = cq93vc_probe,
        .remove = cq93vc_remove,
        .resume = cq93vc_resume,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
 
-static __init int cq93vc_codec_probe(struct platform_device *pdev)
+static int cq93vc_platform_probe(struct platform_device *pdev)
 {
-       struct davinci_vc *davinci_vc = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL) {
-               dev_dbg(davinci_vc->dev,
-                       "could not allocate memory for codec data\n");
-               return -ENOMEM;
-       }
-
-       davinci_vc->cq93vc.codec = codec;
-
-       cq93vc_dai.dev = &pdev->dev;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       codec->dev = &pdev->dev;
-       codec->name = "CQ93VC";
-       codec->owner = THIS_MODULE;
-       codec->read = cq93vc_read;
-       codec->write = cq93vc_write;
-       codec->set_bias_level = cq93vc_set_bias_level;
-       codec->dai = &cq93vc_dai;
-       codec->num_dai = 1;
-       codec->control_data = davinci_vc;
-
-       cq93vc_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret) {
-               dev_err(davinci_vc->dev, "failed to register codec\n");
-               goto fail1;
-       }
-
-       ret = snd_soc_register_dai(&cq93vc_dai);
-       if (ret) {
-               dev_err(davinci_vc->dev, "could register dai\n");
-               goto fail2;
-       }
-       return 0;
-
-fail2:
-       snd_soc_unregister_codec(codec);
-
-fail1:
-       kfree(codec);
-       cq93vc_codec = NULL;
-
-       return ret;
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_cq93vc, &cq93vc_dai, 1);
 }
 
-static int __devexit cq93vc_codec_remove(struct platform_device *pdev)
+static int cq93vc_platform_remove(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       snd_soc_unregister_dai(&cq93vc_dai);
-       snd_soc_unregister_codec(&codec);
-
-       kfree(codec);
-       cq93vc_codec = NULL;
-
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver cq93vc_codec_driver = {
        .driver = {
-                  .name = "cq93vc",
-                  .owner = THIS_MODULE,
-                  },
-       .probe = cq93vc_codec_probe,
-       .remove = __devexit_p(cq93vc_codec_remove),
+                       .name = "cq93vc-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = cq93vc_platform_probe,
+       .remove = __devexit_p(cq93vc_platform_remove),
 };
 
-static __init int cq93vc_init(void)
+static int __init cq93vc_init(void)
 {
-       return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe);
+       return platform_driver_register(&cq93vc_codec_driver);
 }
 module_init(cq93vc_init);
 
-static __exit void cq93vc_exit(void)
+static void __exit cq93vc_exit(void)
 {
        platform_driver_unregister(&cq93vc_codec_driver);
 }
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h
deleted file mode 100644 (file)
index 845b196..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
- *
- * Copyright (C) 2010 Texas Instruments, Inc
- *
- * Author: Miguel Aguilar <miguel.aguilar@ridgerun.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.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _CQ93VC_H
-#define _CQ93VC_H
-
-extern struct snd_soc_dai cq93vc_dai;
-extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
-
-#endif
index 30d9492..6d4bdc6 100644 (file)
@@ -31,8 +31,6 @@
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
-#include "cs4270.h"
-
 /*
  * The codec isn't really big-endian or little-endian, since the I2S
  * interface requires data to be sent serially with the MSbit first.
@@ -114,7 +112,8 @@ static const char *supply_names[] = {
 
 /* Private data for the CS4270 */
 struct cs4270_private {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        u8 reg_cache[CS4270_NUMREGS];
        unsigned int mclk; /* Input frequency of the MCLK pin */
        unsigned int mode; /* The mode (I2S or left-justified) */
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-       unsigned int rates = 0;
-       unsigned int rate_min = -1;
-       unsigned int rate_max = 0;
-       unsigned int i;
 
        cs4270->mclk = freq;
-
-       if (cs4270->mclk) {
-               for (i = 0; i < NUM_MCLK_RATIOS; i++) {
-                       unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
-                       rates |= snd_pcm_rate_to_rate_bit(rate);
-                       if (rate < rate_min)
-                               rate_min = rate;
-                       if (rate > rate_max)
-                               rate_max = rate;
-               }
-               /* FIXME: soc should support a rate list */
-               rates &= ~SNDRV_PCM_RATE_KNOT;
-
-               if (!rates) {
-                       dev_err(codec->dev, "could not find a valid sample rate\n");
-                       return -EINVAL;
-               }
-       } else {
-               /* enable all possible rates */
-               rates = SNDRV_PCM_RATE_8000_192000;
-               rate_min = 8000;
-               rate_max = 192000;
-       }
-
-       codec_dai->playback.rates = rates;
-       codec_dai->playback.rate_min = rate_min;
-       codec_dai->playback.rate_max = rate_max;
-
-       codec_dai->capture.rates = rates;
-       codec_dai->capture.rate_min = rate_min;
-       codec_dai->capture.rate_max = rate_max;
-
        return 0;
 }
 
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        int ret;
        unsigned int i;
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
                snd_soc_get_volsw, cs4270_soc_put_mute),
 };
 
-/*
- * cs4270_codec - global variable to store codec for the ASoC probe function
- *
- * If struct i2c_driver had a private_data field, we wouldn't need to use
- * cs4270_codec.  This is the only way to pass the codec structure from
- * cs4270_i2c_probe() to cs4270_probe().  Unfortunately, there is no good
- * way to synchronize these two functions.  cs4270_i2c_probe() can be called
- * multiple times before cs4270_probe() is called even once.  So for now, we
- * also only allow cs4270_i2c_probe() to be run once.  That means that we do
- * not support more than one cs4270 device in the system, at least for now.
- */
-static struct snd_soc_codec *cs4270_codec;
-
 static struct snd_soc_dai_ops cs4270_dai_ops = {
        .hw_params      = cs4270_hw_params,
        .set_sysclk     = cs4270_set_dai_sysclk,
@@ -569,25 +518,28 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
        .digital_mute   = cs4270_dai_mute,
 };
 
-struct snd_soc_dai cs4270_dai = {
-       .name = "cs4270",
+static struct snd_soc_dai_driver cs4270_dai = {
+       .name = "cs4270-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
                .channels_max = 2,
-               .rates = 0,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 4000,
+               .rate_max = 216000,
                .formats = CS4270_FORMATS,
        },
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
                .channels_max = 2,
-               .rates = 0,
+               .rates = SNDRV_PCM_RATE_CONTINUOUS,
+               .rate_min = 4000,
+               .rate_max = 216000,
                .formats = CS4270_FORMATS,
        },
        .ops = &cs4270_dai_ops,
 };
-EXPORT_SYMBOL_GPL(cs4270_dai);
 
 /**
  * cs4270_probe - ASoC probe function
@@ -596,153 +548,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
  * This function is called when ASoC has all the pieces it needs to
  * instantiate a sound driver.
  */
-static int cs4270_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = cs4270_codec;
-       struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
-       int i, ret;
-
-       /* Connect the codec to the socdev.  snd_soc_new_pcms() needs this. */
-       socdev->card->codec = 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\n");
-               return ret;
-       }
-
-       /* Add the non-DAPM controls */
-       ret = snd_soc_add_controls(codec, cs4270_snd_controls,
-                               ARRAY_SIZE(cs4270_snd_controls));
-       if (ret < 0) {
-               dev_err(codec->dev, "failed to add controls\n");
-               goto error_free_pcms;
-       }
-
-       /* get the power supply regulators */
-       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
-               cs4270->supplies[i].supply = supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
-                                cs4270->supplies);
-       if (ret < 0)
-               goto error_free_pcms;
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
-                                   cs4270->supplies);
-       if (ret < 0)
-               goto error_free_regulators;
-
-       return 0;
-
-error_free_regulators:
-       regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
-                           cs4270->supplies);
-
-error_free_pcms:
-       snd_soc_free_pcms(socdev);
-
-       return ret;
-}
-
-/**
- * cs4270_remove - ASoC remove function
- * @pdev: platform device
- *
- * This function is the counterpart to cs4270_probe().
- */
-static int cs4270_remove(struct platform_device *pdev)
+static int cs4270_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = cs4270_codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
+       int i, ret, reg;
 
-       snd_soc_free_pcms(socdev);
-       regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
-       regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
-
-       return 0;
-};
-
-/**
- * cs4270_i2c_probe - initialize the I2C interface of the CS4270
- * @i2c_client: the I2C client object
- * @id: the I2C device ID (ignored)
- *
- * This function is called whenever the I2C subsystem finds a device that
- * matches the device ID given via a prior call to i2c_add_driver().
- */
-static int cs4270_i2c_probe(struct i2c_client *i2c_client,
-       const struct i2c_device_id *id)
-{
-       struct snd_soc_codec *codec;
-       struct cs4270_private *cs4270;
-       unsigned int reg;
-       int ret;
-
-       /* For now, we only support one cs4270 device in the system.  See the
-        * comment for cs4270_codec.
-        */
-       if (cs4270_codec) {
-               dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n",
-                      i2c_client->addr);
-               dev_err(&i2c_client->dev, "only one per board allowed\n");
-               /* Should we return something other than ENODEV here? */
-               return -ENODEV;
-       }
-
-       /* Verify that we have a CS4270 */
-
-       ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
-       if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
-                      i2c_client->addr);
-               return ret;
-       }
-       /* The top four bits of the chip ID should be 1100. */
-       if ((ret & 0xF0) != 0xC0) {
-               dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
-                      i2c_client->addr);
-               return -ENODEV;
-       }
-
-       dev_info(&i2c_client->dev, "found device at i2c address %X\n",
-               i2c_client->addr);
-       dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
-
-       /* Allocate enough space for the snd_soc_codec structure
-          and our private data together. */
-       cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
-       if (!cs4270) {
-               dev_err(&i2c_client->dev, "could not allocate codec\n");
-               return -ENOMEM;
-       }
-       codec = &cs4270->codec;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->dev = &i2c_client->dev;
-       codec->name = "CS4270";
-       codec->owner = THIS_MODULE;
-       codec->dai = &cs4270_dai;
-       codec->num_dai = 1;
-       snd_soc_codec_set_drvdata(codec, cs4270);
-       codec->control_data = i2c_client;
-       codec->read = cs4270_read_reg_cache;
-       codec->write = cs4270_i2c_write;
-       codec->reg_cache = cs4270->reg_cache;
-       codec->reg_cache_size = CS4270_NUMREGS;
+       codec->control_data = cs4270->control_data;
 
        /* The I2C interface is set up, so pre-fill our register cache */
 
        ret = cs4270_fill_cache(codec);
        if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to fill register cache\n");
-               goto error_free_codec;
+               dev_err(codec->dev, "failed to fill register cache\n");
+               return ret;
        }
 
        /* Disable auto-mute.  This feature appears to be buggy.  In some
@@ -755,7 +573,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
        reg &= ~CS4270_MUTE_AUTO;
        ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
        if (ret < 0) {
-               dev_err(&i2c_client->dev, "i2c write failed\n");
+               dev_err(codec->dev, "i2c write failed\n");
                return ret;
        }
 
@@ -769,65 +587,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
        reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
        ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
        if (ret < 0) {
-               dev_err(&i2c_client->dev, "i2c write failed\n");
+               dev_err(codec->dev, "i2c write failed\n");
                return ret;
        }
 
-       /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI
-        * structure for each CS4270 device, but the machine driver needs to
-        * have a pointer to the DAI structure, so for now it must be a global
-        * variable.
-        */
-       cs4270_dai.dev = &i2c_client->dev;
-
-       /* Register the DAI.  If all the other ASoC driver have already
-        * registered, then this will call our probe function, so
-        * cs4270_codec needs to be ready.
-        */
-       cs4270_codec = codec;
-       ret = snd_soc_register_dai(&cs4270_dai);
+       /* Add the non-DAPM controls */
+       ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+                               ARRAY_SIZE(cs4270_snd_controls));
        if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to register DAIe\n");
-               goto error_free_codec;
+               dev_err(codec->dev, "failed to add controls\n");
+               return ret;
        }
 
-       i2c_set_clientdata(i2c_client, cs4270);
+       /* get the power supply regulators */
+       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+               cs4270->supplies[i].supply = supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
+                                cs4270->supplies);
+       if (ret < 0)
+               return ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
+                                   cs4270->supplies);
+       if (ret < 0)
+               goto error_free_regulators;
 
        return 0;
 
-error_free_codec:
-       kfree(cs4270);
-       cs4270_codec = NULL;
-       cs4270_dai.dev = NULL;
+error_free_regulators:
+       regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
+                           cs4270->supplies);
 
        return ret;
 }
 
 /**
- * cs4270_i2c_remove - remove an I2C device
- * @i2c_client: the I2C client object
+ * cs4270_remove - ASoC remove function
+ * @pdev: platform device
  *
- * This function is the counterpart to cs4270_i2c_probe().
+ * This function is the counterpart to cs4270_probe().
  */
-static int cs4270_i2c_remove(struct i2c_client *i2c_client)
+static int cs4270_remove(struct snd_soc_codec *codec)
 {
-       struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client);
+       struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
 
-       kfree(cs4270);
-       cs4270_codec = NULL;
-       cs4270_dai.dev = NULL;
+       regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
+       regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
 
        return 0;
-}
-
-/*
- * cs4270_id - I2C device IDs supported by this driver
- */
-static struct i2c_device_id cs4270_id[] = {
-       {"cs4270", 0},
-       {}
 };
-MODULE_DEVICE_TABLE(i2c, cs4270_id);
 
 #ifdef CONFIG_PM
 
@@ -840,9 +649,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
  * and all registers are written back to the hardware when resuming.
  */
 
-static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
+static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
 {
-       struct snd_soc_codec *codec = cs4270_codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        int reg, ret;
 
@@ -860,9 +668,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
        return 0;
 }
 
-static int cs4270_soc_resume(struct platform_device *pdev)
+static int cs4270_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = cs4270_codec;
        struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
        struct i2c_client *i2c_client = codec->control_data;
        int reg;
@@ -896,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
 #endif /* CONFIG_PM */
 
 /*
+ * ASoC codec device structure
+ *
+ * Assign this variable to the codec_dev field of the machine driver's
+ * snd_soc_device structure.
+ */
+static struct snd_soc_codec_driver soc_codec_device_cs4270 = {
+       .probe =        cs4270_probe,
+       .remove =       cs4270_remove,
+       .suspend =      cs4270_soc_suspend,
+       .resume =       cs4270_soc_resume,
+       .read = cs4270_read_reg_cache,
+       .write = cs4270_i2c_write,
+       .reg_cache_size = CS4270_NUMREGS,
+       .reg_word_size = sizeof(u8),
+};
+
+/**
+ * cs4270_i2c_probe - initialize the I2C interface of the CS4270
+ * @i2c_client: the I2C client object
+ * @id: the I2C device ID (ignored)
+ *
+ * This function is called whenever the I2C subsystem finds a device that
+ * matches the device ID given via a prior call to i2c_add_driver().
+ */
+static int cs4270_i2c_probe(struct i2c_client *i2c_client,
+       const struct i2c_device_id *id)
+{
+       struct cs4270_private *cs4270;
+       int ret;
+
+       /* Verify that we have a CS4270 */
+
+       ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
+       if (ret < 0) {
+               dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
+                      i2c_client->addr);
+               return ret;
+       }
+       /* The top four bits of the chip ID should be 1100. */
+       if ((ret & 0xF0) != 0xC0) {
+               dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
+                      i2c_client->addr);
+               return -ENODEV;
+       }
+
+       dev_info(&i2c_client->dev, "found device at i2c address %X\n",
+               i2c_client->addr);
+       dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
+
+       cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
+       if (!cs4270) {
+               dev_err(&i2c_client->dev, "could not allocate codec\n");
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(i2c_client, cs4270);
+       cs4270->control_data = i2c_client;
+       cs4270->control_type = SND_SOC_I2C;
+
+       ret = snd_soc_register_codec(&i2c_client->dev,
+                       &soc_codec_device_cs4270, &cs4270_dai, 1);
+       if (ret < 0)
+               kfree(cs4270);
+       return ret;
+}
+
+/**
+ * cs4270_i2c_remove - remove an I2C device
+ * @i2c_client: the I2C client object
+ *
+ * This function is the counterpart to cs4270_i2c_probe().
+ */
+static int cs4270_i2c_remove(struct i2c_client *i2c_client)
+{
+       snd_soc_unregister_codec(&i2c_client->dev);
+       kfree(i2c_get_clientdata(i2c_client));
+       return 0;
+}
+
+/*
+ * cs4270_id - I2C device IDs supported by this driver
+ */
+static struct i2c_device_id cs4270_id[] = {
+       {"cs4270", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, cs4270_id);
+
+/*
  * cs4270_i2c_driver - I2C device identification
  *
  * This structure tells the I2C subsystem how to identify and support a
@@ -903,7 +799,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
  */
 static struct i2c_driver cs4270_i2c_driver = {
        .driver = {
-               .name = "cs4270",
+               .name = "cs4270-codec",
                .owner = THIS_MODULE,
        },
        .id_table = cs4270_id,
@@ -911,20 +807,6 @@ static struct i2c_driver cs4270_i2c_driver = {
        .remove = cs4270_i2c_remove,
 };
 
-/*
- * ASoC codec device structure
- *
- * Assign this variable to the codec_dev field of the machine driver's
- * snd_soc_device structure.
- */
-struct snd_soc_codec_device soc_codec_device_cs4270 = {
-       .probe =        cs4270_probe,
-       .remove =       cs4270_remove,
-       .suspend =      cs4270_soc_suspend,
-       .resume =       cs4270_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
-
 static int __init cs4270_init(void)
 {
        pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h
deleted file mode 100644 (file)
index adc6cd9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Cirrus Logic CS4270 ALSA SoC Codec Driver
- *
- * Author: Timur Tabi <timur@freescale.com>
- *
- * Copyright 2007 Freescale Semiconductor, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef _CS4270_H
-#define _CS4270_H
-
-/*
- * The ASoC codec DAI structure for the CS4270.  Assign this structure to
- * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
- */
-extern struct snd_soc_dai cs4270_dai;
-
-/*
- * The ASoC codec device structure for the CS4270.  Assign this structure
- * to the .codec_dev field of your machine driver's snd_soc_device
- * structure.
- */
-extern struct snd_soc_codec_device soc_codec_device_cs4270;
-
-#endif
index dd9b855..cb086ea 100644 (file)
@@ -42,15 +42,14 @@ enum master_slave_mode {
 };
 
 struct cs42l51_private {
+       enum snd_soc_control_type control_type;
+       void *control_data;
        unsigned int mclk;
        unsigned int audio_mode;        /* The mode (I2S or left-justified) */
        enum master_slave_mode func;
-       struct snd_soc_codec codec;
        u8 reg_cache[CS42L51_NUMREGS];
 };
 
-static struct snd_soc_codec *cs42l51_codec;
-
 #define CS42L51_FORMATS ( \
                SNDRV_PCM_FMTBIT_S16_LE  | SNDRV_PCM_FMTBIT_S16_BE  | \
                SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
@@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
-       const struct i2c_device_id *id)
-{
-       struct snd_soc_codec *codec;
-       struct cs42l51_private *cs42l51;
-       int ret = 0;
-       int reg;
-
-       if (cs42l51_codec)
-               return -EBUSY;
-
-       /* Verify that we have a CS42L51 */
-       ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
-       if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to read I2C\n");
-               goto error;
-       }
-
-       if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
-           (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
-               dev_err(&i2c_client->dev, "Invalid chip id\n");
-               ret = -ENODEV;
-               goto error;
-       }
-
-       dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
-                               ret & 7);
-
-       cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
-       if (!cs42l51) {
-               dev_err(&i2c_client->dev, "could not allocate codec\n");
-               return -ENOMEM;
-       }
-       codec = &cs42l51->codec;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->dev = &i2c_client->dev;
-       codec->name = "CS42L51";
-       codec->owner = THIS_MODULE;
-       codec->dai = &cs42l51_dai;
-       codec->num_dai = 1;
-       snd_soc_codec_set_drvdata(codec, cs42l51);
-
-       codec->control_data = i2c_client;
-       codec->reg_cache = cs42l51->reg_cache;
-       codec->reg_cache_size = CS42L51_NUMREGS;
-       i2c_set_clientdata(i2c_client, codec);
-
-       ret = cs42l51_fill_cache(codec);
-       if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to fill register cache\n");
-               goto error_alloc;
-       }
-
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
-       if (ret < 0) {
-               dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
-               goto error_alloc;
-       }
-
-       /*
-        * DAC configuration
-        * - Use signal processor
-        * - auto mute
-        * - vol changes immediate
-        * - no de-emphasize
-        */
-       reg = CS42L51_DAC_CTL_DATA_SEL(1)
-               | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
-       ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
-       if (ret < 0)
-               goto error_alloc;
-
-       cs42l51_dai.dev = codec->dev;
-       cs42l51_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto error_alloc;
-       }
-
-       ret = snd_soc_register_dai(&cs42l51_dai);
-       if (ret < 0) {
-               dev_err(&i2c_client->dev, "failed to register DAIe\n");
-               goto error_reg;
-       }
-
-       return 0;
-
-error_reg:
-       snd_soc_unregister_codec(codec);
-error_alloc:
-       kfree(cs42l51);
-error:
-       return ret;
-}
-
-static int cs42l51_i2c_remove(struct i2c_client *client)
-{
-       struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
-       snd_soc_unregister_dai(&cs42l51_dai);
-       snd_soc_unregister_codec(cs42l51_codec);
-       cs42l51_codec = NULL;
-       kfree(cs42l51);
-       return 0;
-}
-
-
-static const struct i2c_device_id cs42l51_id[] = {
-       {"cs42l51", 0},
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, cs42l51_id);
-
-static struct i2c_driver cs42l51_i2c_driver = {
-       .driver = {
-               .name = "CS42L51 I2C",
-               .owner = THIS_MODULE,
-       },
-       .id_table = cs42l51_id,
-       .probe = cs42l51_i2c_probe,
-       .remove = cs42l51_i2c_remove,
-};
-
 static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
-       struct cs42l51_ratios *ratios = NULL;
-       int nr_ratios = 0;
-       unsigned int rates = 0;
-       unsigned int rate_min = -1;
-       unsigned int rate_max = 0;
-       int i;
 
        cs42l51->mclk = freq;
-
-       switch (cs42l51->func) {
-       case MODE_MASTER:
-               return -EINVAL;
-       case MODE_SLAVE:
-               ratios = slave_ratios;
-               nr_ratios = ARRAY_SIZE(slave_ratios);
-               break;
-       case MODE_SLAVE_AUTO:
-               ratios = slave_auto_ratios;
-               nr_ratios = ARRAY_SIZE(slave_auto_ratios);
-               break;
-       }
-
-       for (i = 0; i < nr_ratios; i++) {
-               unsigned int rate = freq / ratios[i].ratio;
-               rates |= snd_pcm_rate_to_rate_bit(rate);
-               if (rate < rate_min)
-                       rate_min = rate;
-               if (rate > rate_max)
-                       rate_max = rate;
-       }
-       rates &= ~SNDRV_PCM_RATE_KNOT;
-
-       if (!rates) {
-               dev_err(codec->dev, "could not find a valid sample rate\n");
-               return -EINVAL;
-       }
-
-       codec_dai->playback.rates = rates;
-       codec_dai->playback.rate_min = rate_min;
-       codec_dai->playback.rate_max = rate_max;
-
-       codec_dai->capture.rates = rates;
-       codec_dai->capture.rate_min = rate_min;
-       codec_dai->capture.rate_max = rate_max;
-
        return 0;
 }
 
@@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
                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 snd_soc_codec *codec = rtd->codec;
        struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
        int ret;
        unsigned int i;
@@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {
        .digital_mute   = cs42l51_dai_mute,
 };
 
-struct snd_soc_dai cs42l51_dai = {
-       .name = "CS42L51 HiFi",
+static struct snd_soc_dai_driver cs42l51_dai = {
+       .name = "cs42l51-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {
        },
        .ops = &cs42l51_dai_ops,
 };
-EXPORT_SYMBOL_GPL(cs42l51_dai);
-
 
-static int cs42l51_probe(struct platform_device *pdev)
+static int cs42l51_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
+       struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
+       int ret, reg;
 
-       if (!cs42l51_codec) {
-               dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
-               return -EINVAL;
-       }
+       codec->control_data = cs42l51->control_data;
 
-       socdev->card->codec = cs42l51_codec;
-       codec = socdev->card->codec;
+       ret = cs42l51_fill_cache(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to fill register cache\n");
+               return ret;
+       }
 
-       /* Register PCMs */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
        if (ret < 0) {
-               dev_err(&pdev->dev, "failed to create PCMs\n");
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
+       /*
+        * DAC configuration
+        * - Use signal processor
+        * - auto mute
+        * - vol changes immediate
+        * - no de-emphasize
+        */
+       reg = CS42L51_DAC_CTL_DATA_SEL(1)
+               | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
+       ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
+       if (ret < 0)
+               return ret;
+
        snd_soc_add_controls(codec, cs42l51_snd_controls,
                ARRAY_SIZE(cs42l51_snd_controls));
        snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
@@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)
        return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
+       .probe =        cs42l51_probe,
+       .reg_cache_size = CS42L51_NUMREGS,
+       .reg_word_size = sizeof(u8),
+};
 
-static int cs42l51_remove(struct platform_device *pdev)
+static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
+       const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct cs42l51_private *cs42l51;
+       int ret;
 
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       /* Verify that we have a CS42L51 */
+       ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
+       if (ret < 0) {
+               dev_err(&i2c_client->dev, "failed to read I2C\n");
+               goto error;
+       }
+
+       if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
+           (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
+               dev_err(&i2c_client->dev, "Invalid chip id\n");
+               ret = -ENODEV;
+               goto error;
+       }
+
+       dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
+                               ret & 7);
+
+       cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
+       if (!cs42l51) {
+               dev_err(&i2c_client->dev, "could not allocate codec\n");
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(i2c_client, cs42l51);
+       cs42l51->control_data = i2c_client;
+       cs42l51->control_type = SND_SOC_I2C;
 
+       ret =  snd_soc_register_codec(&i2c_client->dev,
+                       &soc_codec_device_cs42l51, &cs42l51_dai, 1);
+       if (ret < 0)
+               kfree(cs42l51);
+error:
+       return ret;
+}
+
+static int cs42l51_i2c_remove(struct i2c_client *client)
+{
+       struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_codec(&client->dev);
+       kfree(cs42l51);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_device_cs42l51 = {
-       .probe =        cs42l51_probe,
-       .remove =       cs42l51_remove
+static const struct i2c_device_id cs42l51_id[] = {
+       {"cs42l51", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, cs42l51_id);
+
+static struct i2c_driver cs42l51_i2c_driver = {
+       .driver = {
+               .name = "cs42l51-codec",
+               .owner = THIS_MODULE,
+       },
+       .id_table = cs42l51_id,
+       .probe = cs42l51_i2c_probe,
+       .remove = cs42l51_i2c_remove,
 };
-EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
 
 static int __init cs42l51_init(void)
 {
@@ -758,6 +649,6 @@ static void __exit cs42l51_exit(void)
 }
 module_exit(cs42l51_exit);
 
-MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");
index 8f0bd97..2beeb17 100644 (file)
 #define CS42L51_LASTREG                0x20
 #define CS42L51_NUMREGS                (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
 
-extern struct snd_soc_dai cs42l51_dai;
-extern struct snd_soc_codec_device soc_codec_device_cs42l51;
 #endif
index f07a415..e8d27c8 100644 (file)
@@ -24,7 +24,8 @@
 
 
 struct cx20442_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        u8 reg_cache[1];
 };
 
@@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
 {
        u8 *reg_cache = codec->reg_cache;
 
-       if (reg >= codec->reg_cache_size)
+       if (reg >= codec->driver->reg_cache_size)
                return -EINVAL;
 
        return reg_cache[reg];
@@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)
 static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
                                                        unsigned int value)
 {
+       struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
        u8 *reg_cache = codec->reg_cache;
        int vls, vsp, old, len;
        char buf[18];
 
-       if (reg >= codec->reg_cache_size)
+       if (reg >= codec->driver->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)
+       if (!codec->hw_write || !cx20442->control_data)
                return -EIO;
 
        old = reg_cache[reg];
@@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
                return -ENOMEM;
 
        dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
-       if (codec->hw_write(codec->control_data, buf, len) != len)
+       if (codec->hw_write(cx20442->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
  *
@@ -228,15 +226,15 @@ 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;
+       /* Won't work if no codec pointer has been passed by a card driver */
+       if (!tty->disc_data)
+               return -ENODEV;
 
        if (tty->ops->write(tty, v253_init, len) != len) {
                ret = -EIO;
@@ -253,15 +251,18 @@ err:
 static void v253_close(struct tty_struct *tty)
 {
        struct snd_soc_codec *codec = tty->disc_data;
+       struct cx20442_priv *cx20442;
 
        tty->disc_data = NULL;
 
        if (!codec)
                return;
 
+       cx20442 = snd_soc_codec_get_drvdata(codec);
+
        /* Prevent the codec driver from further accessing the modem */
        codec->hw_write = NULL;
-       codec->control_data = NULL;
+       cx20442->control_data = NULL;
        codec->pop_time = 0;
 }
 
@@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,
                                const unsigned char *cp, char *fp, int count)
 {
        struct snd_soc_codec *codec = tty->disc_data;
+       struct cx20442_priv *cx20442;
 
        if (!codec)
                return;
 
-       if (!codec->control_data) {
+       cx20442 = snd_soc_codec_get_drvdata(codec);
+
+       if (!cx20442->control_data) {
                /* First modem response, complete setup procedure */
 
                /* Set up codec driver access to modem controls */
-               codec->control_data = tty;
+               cx20442->control_data = tty;
                codec->hw_write = (hw_write_t)tty->ops->write;
                codec->pop_time = 1;
        }
@@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);
  * Codec DAI
  */
 
-struct snd_soc_dai cx20442_dai = {
-       .name = "CX20442",
+static struct snd_soc_dai_driver cx20442_dai = {
+       .name = "cx20442-voice",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
 };
-EXPORT_SYMBOL_GPL(cx20442_dai);
 
-static int cx20442_codec_probe(struct platform_device *pdev)
+static int cx20442_codec_probe(struct snd_soc_codec *codec)
 {
-       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;
+       struct cx20442_priv *cx20442;
 
-       /* 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 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
+       if (cx20442 == NULL)
+               return -ENOMEM;
+       snd_soc_codec_set_drvdata(codec, cx20442);
 
        cx20442_add_widgets(codec);
 
-pcm_err:
-       return ret;
+       cx20442->control_data = NULL;
+       codec->hw_write = NULL;
+       codec->pop_time = 0;
+
+       return 0;
 }
 
 /* power down chip */
-static int cx20442_codec_remove(struct platform_device *pdev)
+static int cx20442_codec_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
 
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       if (cx20442->control_data) {
+                       struct tty_struct *tty = cx20442->control_data;
+                       tty_hangup(tty);
+       }
 
+       kfree(cx20442);
        return 0;
 }
 
-struct snd_soc_codec_device cx20442_codec_dev = {
+static struct snd_soc_codec_driver cx20442_codec_dev = {
        .probe =        cx20442_codec_probe,
        .remove =       cx20442_codec_remove,
+       .reg_cache_size = 1,
+       .reg_word_size = sizeof(u8),
+       .read = cx20442_read_reg_cache,
+       .write = cx20442_write,
 };
-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;
-       snd_soc_codec_set_drvdata(codec, 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);
+       return snd_soc_register_codec(&pdev->dev,
+                       &cx20442_codec_dev, &cx20442_dai, 1);
 }
 
 static int __exit cx20442_platform_remove(struct platform_device *pdev)
 {
-       struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
-
-       cx20442_unregister(cx20442);
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver cx20442_platform_driver = {
        .driver = {
-               .name = "cx20442",
+               .name = "cx20442-codec",
                .owner = THIS_MODULE,
                },
        .probe = cx20442_platform_probe,
@@ -487,4 +412,4 @@ module_exit(cx20442_exit);
 MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
 MODULE_AUTHOR("Janusz Krzysztofik");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cx20442");
+MODULE_ALIAS("platform:cx20442-codec");
index 688a5eb..c7a7c79 100644 (file)
@@ -13,8 +13,6 @@
 #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
index 3c51d6a..58bb9b9 100644 (file)
@@ -25,8 +25,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include "da7210.h"
-
 /* DA7210 register space */
 #define DA7210_STATUS                  0x02
 #define DA7210_STARTUP1                        0x03
@@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
 
 /* Codec private data */
 struct da7210_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
-static struct snd_soc_codec *da7210_codec;
-
 /*
  * Register cache
  */
@@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
        u8 *cache = codec->reg_cache;
        u8 data[2];
 
-       BUG_ON(codec->volatile_register);
+       BUG_ON(codec->driver->volatile_register);
 
        data[0] = reg & 0xff;
        data[1] = value & 0xff;
 
-       if (reg >= codec->reg_cache_size)
+       if (reg >= codec->driver->reg_cache_size)
                return -EIO;
 
        if (2 != codec->hw_write(codec->control_data, data, 2))
@@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        u32 dai_cfg1;
        u32 hpf_reg, hpf_mask, hpf_value;
        u32 fs, bypass;
@@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {
        .set_fmt        = da7210_set_dai_fmt,
 };
 
-struct snd_soc_dai da7210_dai = {
-       .name = "DA7210 IIS",
-       .id = 0,
+static struct snd_soc_dai_driver da7210_dai = {
+       .name = "da7210-hifi",
        /* playback capabilities */
        .playback = {
                .stream_name = "Playback",
@@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {
        .ops = &da7210_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(da7210_dai);
 
-/*
- * Initialize the DA7210 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int da7210_init(struct da7210_priv *da7210)
+static int da7210_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &da7210->codec;
-       int ret = 0;
+       struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
 
-       if (da7210_codec) {
-               dev_err(codec->dev, "Another da7210 is registered\n");
-               return -EINVAL;
-       }
+       dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, da7210);
-       codec->name             = "DA7210";
-       codec->owner            = THIS_MODULE;
-       codec->read             = da7210_read;
-       codec->write            = da7210_write;
-       codec->dai              = &da7210_dai;
-       codec->num_dai          = 1;
+       codec->control_data     = da7210->control_data;
        codec->hw_write         = (hw_write_t)i2c_master_send;
-       codec->reg_cache_size   = ARRAY_SIZE(da7210_reg);
-       codec->reg_cache        = kmemdup(da7210_reg,
-                                         sizeof(da7210_reg), GFP_KERNEL);
-
-       if (!codec->reg_cache)
-               return -ENOMEM;
-
-       da7210_dai.dev = codec->dev;
-       da7210_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret) {
-               dev_err(codec->dev, "Failed to register CODEC: %d\n", ret);
-               goto init_err;
-       }
-
-       ret = snd_soc_register_dai(&da7210_dai);
-       if (ret) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto codec_err;
-       }
 
        /* FIXME
         *
@@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)
        /* Activate all enabled subsystem */
        da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
 
-       return ret;
-
-codec_err:
-       snd_soc_unregister_codec(codec);
-init_err:
-       kfree(codec->reg_cache);
-       codec->reg_cache = NULL;
+       snd_soc_add_controls(codec, da7210_snd_controls,
+                            ARRAY_SIZE(da7210_snd_controls));
 
-       return ret;
+       dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
 
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
+       .probe                  = da7210_probe,
+       .read                   = da7210_read,
+       .write                  = da7210_write,
+       .reg_cache_size         = ARRAY_SIZE(da7210_reg),
+       .reg_word_size          = sizeof(u8),
+       .reg_cache_default      = da7210_reg,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct da7210_priv *da7210;
-       struct snd_soc_codec *codec;
        int ret;
 
        da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
        if (!da7210)
                return -ENOMEM;
 
-       codec = &da7210->codec;
-       codec->dev = &i2c->dev;
-
        i2c_set_clientdata(i2c, da7210);
-       codec->control_data = i2c;
+       da7210->control_data = i2c;
+       da7210->control_type = SND_SOC_I2C;
 
-       ret = da7210_init(da7210);
-       if (ret < 0) {
-               pr_err("Failed to initialise da7210 audio codec\n");
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_da7210, &da7210_dai, 1);
+       if (ret < 0)
                kfree(da7210);
-       }
 
        return ret;
 }
 
 static int __devexit da7210_i2c_remove(struct i2c_client *client)
 {
-       struct da7210_priv *da7210 = i2c_get_clientdata(client);
-
-       snd_soc_unregister_dai(&da7210_dai);
-       kfree(da7210->codec.reg_cache);
-       kfree(da7210);
-       da7210_codec = NULL;
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -643,59 +594,15 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
 /* I2C codec control layer */
 static struct i2c_driver da7210_i2c_driver = {
        .driver = {
-               .name = "DA7210 I2C Codec",
+               .name = "da7210-codec",
                .owner = THIS_MODULE,
        },
-       .probe = da7210_i2c_probe,
-       .remove  __devexit_p(da7210_i2c_remove),
-       .id_table = da7210_i2c_id,
+       .probe          = da7210_i2c_probe,
+       .remove         = __devexit_p(da7210_i2c_remove),
+       .id_table       = da7210_i2c_id,
 };
 #endif
 
-static int da7210_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       if (!da7210_codec) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = da7210_codec;
-       codec = da7210_codec;
-
-       /* Register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
-       snd_soc_add_controls(da7210_codec, da7210_snd_controls,
-                            ARRAY_SIZE(da7210_snd_controls));
-
-       dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
-
-pcm_err:
-       return ret;
-}
-
-static int da7210_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_da7210 = {
-       .probe =        da7210_probe,
-       .remove =       da7210_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_da7210);
-
 static int __init da7210_modinit(void)
 {
        int ret = 0;
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h
deleted file mode 100644 (file)
index 390d621..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * da7210.h  --  audio driver for da7210
- *
- * Copyright (c) 2009 Dialog Semiconductor
- * Written by David Chen <Dajun.chen@diasemi.com>
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.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.
- *
- */
-
-#ifndef _DA7210_H
-#define _DA7210_H
-
-extern struct snd_soc_dai da7210_dai;
-extern struct snd_soc_codec_device soc_codec_dev_da7210;
-
-#endif
-
index 66557de..16253ec 100644 (file)
@@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {
 struct jz4740_codec {
        void __iomem *base;
        struct resource *mem;
-
-       uint32_t reg_cache[2];
-       struct snd_soc_codec codec;
 };
 
-static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
-{
-       return container_of(codec, struct jz4740_codec, codec);
-}
-
 static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
        unsigned int reg)
 {
-       struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
        return readl(jz4740_codec->base + (reg << 2));
 }
 
 static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
        unsigned int val)
 {
-       struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec);
+       struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
+       u32 *cache = codec->reg_cache;
 
-       jz4740_codec->reg_cache[reg] = val;
+       cache[reg] = val;
        writel(val, jz4740_codec->base + (reg << 2));
 
        return 0;
@@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
 {
        uint32_t val;
        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 snd_soc_codec *codec =rtd->codec;
 
        switch (params_rate(params)) {
        case 8000:
@@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
        .hw_params = jz4740_codec_hw_params,
 };
 
-struct snd_soc_dai jz4740_codec_dai = {
-       .name = "jz4740",
+static struct snd_soc_dai_driver jz4740_codec_dai = {
+       .name = "jz4740-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {
        .ops = &jz4740_codec_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(jz4740_codec_dai);
 
 static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
 {
@@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static struct snd_soc_codec *jz4740_codec_codec;
-
-static int jz4740_codec_dev_probe(struct platform_device *pdev)
+static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
 {
-       int ret;
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = jz4740_codec_codec;
-
-       BUG_ON(!codec);
-
-       socdev->card->codec = codec;
-
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
-               return ret;
-       }
+       snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
+                       JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
 
        snd_soc_add_controls(codec, jz4740_codec_controls,
                ARRAY_SIZE(jz4740_codec_controls));
@@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev)
 
        snd_soc_dapm_new_widgets(codec);
 
+       jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
        return 0;
 }
 
-static int jz4740_codec_dev_remove(struct platform_device *pdev)
+static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
 
-static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state)
+static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
 
-static int jz4740_codec_resume(struct platform_device *pdev)
+static int jz4740_codec_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 }
 
@@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev)
 #define jz4740_codec_resume NULL
 #endif
 
-struct snd_soc_codec_device soc_codec_dev_jz4740_codec = {
+static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
        .probe = jz4740_codec_dev_probe,
        .remove = jz4740_codec_dev_remove,
        .suspend = jz4740_codec_suspend,
        .resume = jz4740_codec_resume,
+       .read = jz4740_codec_read,
+       .write = jz4740_codec_write,
+       .set_bias_level = jz4740_codec_set_bias_level,
+       .reg_cache_default      = jz4740_codec_regs,
+       .reg_word_size = sizeof(u32),
+       .reg_cache_size = 2,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
 
 static int __devinit jz4740_codec_probe(struct platform_device *pdev)
 {
        int ret;
        struct jz4740_codec *jz4740_codec;
-       struct snd_soc_codec *codec;
        struct resource *mem;
 
        jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
@@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
        }
        jz4740_codec->mem = mem;
 
-       jz4740_codec_dai.dev = &pdev->dev;
-
-       codec = &jz4740_codec->codec;
-
-       codec->dev              = &pdev->dev;
-       codec->name             = "jz4740";
-       codec->owner            = THIS_MODULE;
-
-       codec->read             = jz4740_codec_read;
-       codec->write            = jz4740_codec_write;
-       codec->set_bias_level   = jz4740_codec_set_bias_level;
-       codec->bias_level       = SND_SOC_BIAS_OFF;
-
-       codec->dai              = &jz4740_codec_dai;
-       codec->num_dai          = 1;
-
-       codec->reg_cache        = jz4740_codec->reg_cache;
-       codec->reg_cache_size   = 2;
-       memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       jz4740_codec_codec = codec;
-
-       snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
-                       JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
-
        platform_set_drvdata(pdev, jz4740_codec);
 
-       ret = snd_soc_register_codec(codec);
+       ret = snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
        if (ret) {
                dev_err(&pdev->dev, "Failed to register codec\n");
                goto err_iounmap;
        }
 
-       ret = snd_soc_register_dai(&jz4740_codec_dai);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to register codec dai\n");
-               goto err_unregister_codec;
-       }
-
-       jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        return 0;
 
-err_unregister_codec:
-       snd_soc_unregister_codec(codec);
 err_iounmap:
        iounmap(jz4740_codec->base);
 err_release_mem_region:
@@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
        struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
        struct resource *mem = jz4740_codec->mem;
 
-       snd_soc_unregister_dai(&jz4740_codec_dai);
-       snd_soc_unregister_codec(&jz4740_codec->codec);
+       snd_soc_unregister_codec(&pdev->dev);
 
        iounmap(jz4740_codec->base);
        release_mem_region(mem->start, resource_size(mem));
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h
deleted file mode 100644 (file)
index b5a0691..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
- *
- * 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.
- *
- *  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.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
-#define __SND_SOC_CODECS_JZ4740_CODEC_H__
-
-extern struct snd_soc_dai jz4740_codec_dai;
-extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
-
-#endif
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
new file mode 100644 (file)
index 0000000..e7a40d1
--- /dev/null
@@ -0,0 +1,2097 @@
+/*
+ * max98088.c -- MAX98088 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Maxim Integrated Products
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+#include <sound/max98088.h>
+#include "max98088.h"
+
+struct max98088_cdata {
+       unsigned int rate;
+       unsigned int fmt;
+       int eq_sel;
+};
+
+struct max98088_priv {
+       u8 reg_cache[M98088_REG_CNT];
+       void *control_data;
+       struct max98088_pdata *pdata;
+       unsigned int sysclk;
+       struct max98088_cdata dai[2];
+       int eq_textcnt;
+       const char **eq_texts;
+       struct soc_enum eq_enum;
+       u8 ina_state;
+       u8 inb_state;
+       unsigned int ex_mode;
+       unsigned int digmic;
+       unsigned int mic1pre;
+       unsigned int mic2pre;
+       unsigned int extmic_mode;
+};
+
+static const u8 max98088_reg[M98088_REG_CNT] = {
+       0x00, /* 00 IRQ status */
+       0x00, /* 01 MIC status */
+       0x00, /* 02 jack status */
+       0x00, /* 03 battery voltage */
+       0x00, /* 04 */
+       0x00, /* 05 */
+       0x00, /* 06 */
+       0x00, /* 07 */
+       0x00, /* 08 */
+       0x00, /* 09 */
+       0x00, /* 0A */
+       0x00, /* 0B */
+       0x00, /* 0C */
+       0x00, /* 0D */
+       0x00, /* 0E */
+       0x00, /* 0F interrupt enable */
+
+       0x00, /* 10 master clock */
+       0x00, /* 11 DAI1 clock mode */
+       0x00, /* 12 DAI1 clock control */
+       0x00, /* 13 DAI1 clock control */
+       0x00, /* 14 DAI1 format */
+       0x00, /* 15 DAI1 clock */
+       0x00, /* 16 DAI1 config */
+       0x00, /* 17 DAI1 TDM */
+       0x00, /* 18 DAI1 filters */
+       0x00, /* 19 DAI2 clock mode */
+       0x00, /* 1A DAI2 clock control */
+       0x00, /* 1B DAI2 clock control */
+       0x00, /* 1C DAI2 format */
+       0x00, /* 1D DAI2 clock */
+       0x00, /* 1E DAI2 config */
+       0x00, /* 1F DAI2 TDM */
+
+       0x00, /* 20 DAI2 filters */
+       0x00, /* 21 data config */
+       0x00, /* 22 DAC mixer */
+       0x00, /* 23 left ADC mixer */
+       0x00, /* 24 right ADC mixer */
+       0x00, /* 25 left HP mixer */
+       0x00, /* 26 right HP mixer */
+       0x00, /* 27 HP control */
+       0x00, /* 28 left REC mixer */
+       0x00, /* 29 right REC mixer */
+       0x00, /* 2A REC control */
+       0x00, /* 2B left SPK mixer */
+       0x00, /* 2C right SPK mixer */
+       0x00, /* 2D SPK control */
+       0x00, /* 2E sidetone */
+       0x00, /* 2F DAI1 playback level */
+
+       0x00, /* 30 DAI1 playback level */
+       0x00, /* 31 DAI2 playback level */
+       0x00, /* 32 DAI2 playbakc level */
+       0x00, /* 33 left ADC level */
+       0x00, /* 34 right ADC level */
+       0x00, /* 35 MIC1 level */
+       0x00, /* 36 MIC2 level */
+       0x00, /* 37 INA level */
+       0x00, /* 38 INB level */
+       0x00, /* 39 left HP volume */
+       0x00, /* 3A right HP volume */
+       0x00, /* 3B left REC volume */
+       0x00, /* 3C right REC volume */
+       0x00, /* 3D left SPK volume */
+       0x00, /* 3E right SPK volume */
+       0x00, /* 3F MIC config */
+
+       0x00, /* 40 MIC threshold */
+       0x00, /* 41 excursion limiter filter */
+       0x00, /* 42 excursion limiter threshold */
+       0x00, /* 43 ALC */
+       0x00, /* 44 power limiter threshold */
+       0x00, /* 45 power limiter config */
+       0x00, /* 46 distortion limiter config */
+       0x00, /* 47 audio input */
+       0x00, /* 48 microphone */
+       0x00, /* 49 level control */
+       0x00, /* 4A bypass switches */
+       0x00, /* 4B jack detect */
+       0x00, /* 4C input enable */
+       0x00, /* 4D output enable */
+       0xF0, /* 4E bias control */
+       0x00, /* 4F DAC power */
+
+       0x0F, /* 50 DAC power */
+       0x00, /* 51 system */
+       0x00, /* 52 DAI1 EQ1 */
+       0x00, /* 53 DAI1 EQ1 */
+       0x00, /* 54 DAI1 EQ1 */
+       0x00, /* 55 DAI1 EQ1 */
+       0x00, /* 56 DAI1 EQ1 */
+       0x00, /* 57 DAI1 EQ1 */
+       0x00, /* 58 DAI1 EQ1 */
+       0x00, /* 59 DAI1 EQ1 */
+       0x00, /* 5A DAI1 EQ1 */
+       0x00, /* 5B DAI1 EQ1 */
+       0x00, /* 5C DAI1 EQ2 */
+       0x00, /* 5D DAI1 EQ2 */
+       0x00, /* 5E DAI1 EQ2 */
+       0x00, /* 5F DAI1 EQ2 */
+
+       0x00, /* 60 DAI1 EQ2 */
+       0x00, /* 61 DAI1 EQ2 */
+       0x00, /* 62 DAI1 EQ2 */
+       0x00, /* 63 DAI1 EQ2 */
+       0x00, /* 64 DAI1 EQ2 */
+       0x00, /* 65 DAI1 EQ2 */
+       0x00, /* 66 DAI1 EQ3 */
+       0x00, /* 67 DAI1 EQ3 */
+       0x00, /* 68 DAI1 EQ3 */
+       0x00, /* 69 DAI1 EQ3 */
+       0x00, /* 6A DAI1 EQ3 */
+       0x00, /* 6B DAI1 EQ3 */
+       0x00, /* 6C DAI1 EQ3 */
+       0x00, /* 6D DAI1 EQ3 */
+       0x00, /* 6E DAI1 EQ3 */
+       0x00, /* 6F DAI1 EQ3 */
+
+       0x00, /* 70 DAI1 EQ4 */
+       0x00, /* 71 DAI1 EQ4 */
+       0x00, /* 72 DAI1 EQ4 */
+       0x00, /* 73 DAI1 EQ4 */
+       0x00, /* 74 DAI1 EQ4 */
+       0x00, /* 75 DAI1 EQ4 */
+       0x00, /* 76 DAI1 EQ4 */
+       0x00, /* 77 DAI1 EQ4 */
+       0x00, /* 78 DAI1 EQ4 */
+       0x00, /* 79 DAI1 EQ4 */
+       0x00, /* 7A DAI1 EQ5 */
+       0x00, /* 7B DAI1 EQ5 */
+       0x00, /* 7C DAI1 EQ5 */
+       0x00, /* 7D DAI1 EQ5 */
+       0x00, /* 7E DAI1 EQ5 */
+       0x00, /* 7F DAI1 EQ5 */
+
+       0x00, /* 80 DAI1 EQ5 */
+       0x00, /* 81 DAI1 EQ5 */
+       0x00, /* 82 DAI1 EQ5 */
+       0x00, /* 83 DAI1 EQ5 */
+       0x00, /* 84 DAI2 EQ1 */
+       0x00, /* 85 DAI2 EQ1 */
+       0x00, /* 86 DAI2 EQ1 */
+       0x00, /* 87 DAI2 EQ1 */
+       0x00, /* 88 DAI2 EQ1 */
+       0x00, /* 89 DAI2 EQ1 */
+       0x00, /* 8A DAI2 EQ1 */
+       0x00, /* 8B DAI2 EQ1 */
+       0x00, /* 8C DAI2 EQ1 */
+       0x00, /* 8D DAI2 EQ1 */
+       0x00, /* 8E DAI2 EQ2 */
+       0x00, /* 8F DAI2 EQ2 */
+
+       0x00, /* 90 DAI2 EQ2 */
+       0x00, /* 91 DAI2 EQ2 */
+       0x00, /* 92 DAI2 EQ2 */
+       0x00, /* 93 DAI2 EQ2 */
+       0x00, /* 94 DAI2 EQ2 */
+       0x00, /* 95 DAI2 EQ2 */
+       0x00, /* 96 DAI2 EQ2 */
+       0x00, /* 97 DAI2 EQ2 */
+       0x00, /* 98 DAI2 EQ3 */
+       0x00, /* 99 DAI2 EQ3 */
+       0x00, /* 9A DAI2 EQ3 */
+       0x00, /* 9B DAI2 EQ3 */
+       0x00, /* 9C DAI2 EQ3 */
+       0x00, /* 9D DAI2 EQ3 */
+       0x00, /* 9E DAI2 EQ3 */
+       0x00, /* 9F DAI2 EQ3 */
+
+       0x00, /* A0 DAI2 EQ3 */
+       0x00, /* A1 DAI2 EQ3 */
+       0x00, /* A2 DAI2 EQ4 */
+       0x00, /* A3 DAI2 EQ4 */
+       0x00, /* A4 DAI2 EQ4 */
+       0x00, /* A5 DAI2 EQ4 */
+       0x00, /* A6 DAI2 EQ4 */
+       0x00, /* A7 DAI2 EQ4 */
+       0x00, /* A8 DAI2 EQ4 */
+       0x00, /* A9 DAI2 EQ4 */
+       0x00, /* AA DAI2 EQ4 */
+       0x00, /* AB DAI2 EQ4 */
+       0x00, /* AC DAI2 EQ5 */
+       0x00, /* AD DAI2 EQ5 */
+       0x00, /* AE DAI2 EQ5 */
+       0x00, /* AF DAI2 EQ5 */
+
+       0x00, /* B0 DAI2 EQ5 */
+       0x00, /* B1 DAI2 EQ5 */
+       0x00, /* B2 DAI2 EQ5 */
+       0x00, /* B3 DAI2 EQ5 */
+       0x00, /* B4 DAI2 EQ5 */
+       0x00, /* B5 DAI2 EQ5 */
+       0x00, /* B6 DAI1 biquad */
+       0x00, /* B7 DAI1 biquad */
+       0x00, /* B8 DAI1 biquad */
+       0x00, /* B9 DAI1 biquad */
+       0x00, /* BA DAI1 biquad */
+       0x00, /* BB DAI1 biquad */
+       0x00, /* BC DAI1 biquad */
+       0x00, /* BD DAI1 biquad */
+       0x00, /* BE DAI1 biquad */
+       0x00, /* BF DAI1 biquad */
+
+       0x00, /* C0 DAI2 biquad */
+       0x00, /* C1 DAI2 biquad */
+       0x00, /* C2 DAI2 biquad */
+       0x00, /* C3 DAI2 biquad */
+       0x00, /* C4 DAI2 biquad */
+       0x00, /* C5 DAI2 biquad */
+       0x00, /* C6 DAI2 biquad */
+       0x00, /* C7 DAI2 biquad */
+       0x00, /* C8 DAI2 biquad */
+       0x00, /* C9 DAI2 biquad */
+       0x00, /* CA */
+       0x00, /* CB */
+       0x00, /* CC */
+       0x00, /* CD */
+       0x00, /* CE */
+       0x00, /* CF */
+
+       0x00, /* D0 */
+       0x00, /* D1 */
+       0x00, /* D2 */
+       0x00, /* D3 */
+       0x00, /* D4 */
+       0x00, /* D5 */
+       0x00, /* D6 */
+       0x00, /* D7 */
+       0x00, /* D8 */
+       0x00, /* D9 */
+       0x00, /* DA */
+       0x70, /* DB */
+       0x00, /* DC */
+       0x00, /* DD */
+       0x00, /* DE */
+       0x00, /* DF */
+
+       0x00, /* E0 */
+       0x00, /* E1 */
+       0x00, /* E2 */
+       0x00, /* E3 */
+       0x00, /* E4 */
+       0x00, /* E5 */
+       0x00, /* E6 */
+       0x00, /* E7 */
+       0x00, /* E8 */
+       0x00, /* E9 */
+       0x00, /* EA */
+       0x00, /* EB */
+       0x00, /* EC */
+       0x00, /* ED */
+       0x00, /* EE */
+       0x00, /* EF */
+
+       0x00, /* F0 */
+       0x00, /* F1 */
+       0x00, /* F2 */
+       0x00, /* F3 */
+       0x00, /* F4 */
+       0x00, /* F5 */
+       0x00, /* F6 */
+       0x00, /* F7 */
+       0x00, /* F8 */
+       0x00, /* F9 */
+       0x00, /* FA */
+       0x00, /* FB */
+       0x00, /* FC */
+       0x00, /* FD */
+       0x00, /* FE */
+       0x00, /* FF */
+};
+
+static struct {
+       int readable;
+       int writable;
+       int vol;
+} max98088_access[M98088_REG_CNT] = {
+       { 0xFF, 0xFF, 1 }, /* 00 IRQ status */
+       { 0xFF, 0x00, 1 }, /* 01 MIC status */
+       { 0xFF, 0x00, 1 }, /* 02 jack status */
+       { 0x1F, 0x1F, 1 }, /* 03 battery voltage */
+       { 0xFF, 0xFF, 0 }, /* 04 */
+       { 0xFF, 0xFF, 0 }, /* 05 */
+       { 0xFF, 0xFF, 0 }, /* 06 */
+       { 0xFF, 0xFF, 0 }, /* 07 */
+       { 0xFF, 0xFF, 0 }, /* 08 */
+       { 0xFF, 0xFF, 0 }, /* 09 */
+       { 0xFF, 0xFF, 0 }, /* 0A */
+       { 0xFF, 0xFF, 0 }, /* 0B */
+       { 0xFF, 0xFF, 0 }, /* 0C */
+       { 0xFF, 0xFF, 0 }, /* 0D */
+       { 0xFF, 0xFF, 0 }, /* 0E */
+       { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */
+
+       { 0xFF, 0xFF, 0 }, /* 10 master clock */
+       { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */
+       { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */
+       { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */
+       { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */
+       { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */
+       { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */
+       { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */
+       { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */
+       { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */
+       { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */
+       { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */
+       { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */
+       { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */
+       { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */
+       { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */
+
+       { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */
+       { 0xFF, 0xFF, 0 }, /* 21 data config */
+       { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */
+       { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */
+       { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */
+       { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */
+       { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */
+       { 0xFF, 0xFF, 0 }, /* 27 HP control */
+       { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */
+       { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */
+       { 0xFF, 0xFF, 0 }, /* 2A REC control */
+       { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */
+       { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */
+       { 0xFF, 0xFF, 0 }, /* 2D SPK control */
+       { 0xFF, 0xFF, 0 }, /* 2E sidetone */
+       { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */
+
+       { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */
+       { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */
+       { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */
+       { 0xFF, 0xFF, 0 }, /* 33 left ADC level */
+       { 0xFF, 0xFF, 0 }, /* 34 right ADC level */
+       { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */
+       { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */
+       { 0xFF, 0xFF, 0 }, /* 37 INA level */
+       { 0xFF, 0xFF, 0 }, /* 38 INB level */
+       { 0xFF, 0xFF, 0 }, /* 39 left HP volume */
+       { 0xFF, 0xFF, 0 }, /* 3A right HP volume */
+       { 0xFF, 0xFF, 0 }, /* 3B left REC volume */
+       { 0xFF, 0xFF, 0 }, /* 3C right REC volume */
+       { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */
+       { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */
+       { 0xFF, 0xFF, 0 }, /* 3F MIC config */
+
+       { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */
+       { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */
+       { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */
+       { 0xFF, 0xFF, 0 }, /* 43 ALC */
+       { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */
+       { 0xFF, 0xFF, 0 }, /* 45 power limiter config */
+       { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */
+       { 0xFF, 0xFF, 0 }, /* 47 audio input */
+       { 0xFF, 0xFF, 0 }, /* 48 microphone */
+       { 0xFF, 0xFF, 0 }, /* 49 level control */
+       { 0xFF, 0xFF, 0 }, /* 4A bypass switches */
+       { 0xFF, 0xFF, 0 }, /* 4B jack detect */
+       { 0xFF, 0xFF, 0 }, /* 4C input enable */
+       { 0xFF, 0xFF, 0 }, /* 4D output enable */
+       { 0xFF, 0xFF, 0 }, /* 4E bias control */
+       { 0xFF, 0xFF, 0 }, /* 4F DAC power */
+
+       { 0xFF, 0xFF, 0 }, /* 50 DAC power */
+       { 0xFF, 0xFF, 0 }, /* 51 system */
+       { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */
+
+       { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */
+
+       { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */
+
+       { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */
+       { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */
+
+       { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */
+       { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */
+
+       { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */
+       { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */
+       { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */
+
+       { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */
+       { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */
+       { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */
+
+       { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */
+       { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */
+       { 0x00, 0x00, 0 }, /* CA */
+       { 0x00, 0x00, 0 }, /* CB */
+       { 0x00, 0x00, 0 }, /* CC */
+       { 0x00, 0x00, 0 }, /* CD */
+       { 0x00, 0x00, 0 }, /* CE */
+       { 0x00, 0x00, 0 }, /* CF */
+
+       { 0x00, 0x00, 0 }, /* D0 */
+       { 0x00, 0x00, 0 }, /* D1 */
+       { 0x00, 0x00, 0 }, /* D2 */
+       { 0x00, 0x00, 0 }, /* D3 */
+       { 0x00, 0x00, 0 }, /* D4 */
+       { 0x00, 0x00, 0 }, /* D5 */
+       { 0x00, 0x00, 0 }, /* D6 */
+       { 0x00, 0x00, 0 }, /* D7 */
+       { 0x00, 0x00, 0 }, /* D8 */
+       { 0x00, 0x00, 0 }, /* D9 */
+       { 0x00, 0x00, 0 }, /* DA */
+       { 0x00, 0x00, 0 }, /* DB */
+       { 0x00, 0x00, 0 }, /* DC */
+       { 0x00, 0x00, 0 }, /* DD */
+       { 0x00, 0x00, 0 }, /* DE */
+       { 0x00, 0x00, 0 }, /* DF */
+
+       { 0x00, 0x00, 0 }, /* E0 */
+       { 0x00, 0x00, 0 }, /* E1 */
+       { 0x00, 0x00, 0 }, /* E2 */
+       { 0x00, 0x00, 0 }, /* E3 */
+       { 0x00, 0x00, 0 }, /* E4 */
+       { 0x00, 0x00, 0 }, /* E5 */
+       { 0x00, 0x00, 0 }, /* E6 */
+       { 0x00, 0x00, 0 }, /* E7 */
+       { 0x00, 0x00, 0 }, /* E8 */
+       { 0x00, 0x00, 0 }, /* E9 */
+       { 0x00, 0x00, 0 }, /* EA */
+       { 0x00, 0x00, 0 }, /* EB */
+       { 0x00, 0x00, 0 }, /* EC */
+       { 0x00, 0x00, 0 }, /* ED */
+       { 0x00, 0x00, 0 }, /* EE */
+       { 0x00, 0x00, 0 }, /* EF */
+
+       { 0x00, 0x00, 0 }, /* F0 */
+       { 0x00, 0x00, 0 }, /* F1 */
+       { 0x00, 0x00, 0 }, /* F2 */
+       { 0x00, 0x00, 0 }, /* F3 */
+       { 0x00, 0x00, 0 }, /* F4 */
+       { 0x00, 0x00, 0 }, /* F5 */
+       { 0x00, 0x00, 0 }, /* F6 */
+       { 0x00, 0x00, 0 }, /* F7 */
+       { 0x00, 0x00, 0 }, /* F8 */
+       { 0x00, 0x00, 0 }, /* F9 */
+       { 0x00, 0x00, 0 }, /* FA */
+       { 0x00, 0x00, 0 }, /* FB */
+       { 0x00, 0x00, 0 }, /* FC */
+       { 0x00, 0x00, 0 }, /* FD */
+       { 0x00, 0x00, 0 }, /* FE */
+       { 0xFF, 0x00, 1 }, /* FF */
+};
+
+static int max98088_volatile_register(unsigned int reg)
+{
+       return max98088_access[reg].vol;
+}
+
+
+/*
+ * Load equalizer DSP coefficient configurations registers
+ */
+static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai,
+                   unsigned int band, u16 *coefs)
+{
+       unsigned int eq_reg;
+       unsigned int i;
+
+       BUG_ON(band > 4);
+       BUG_ON(dai > 1);
+
+       /* Load the base register address */
+       eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE;
+
+       /* Add the band address offset, note adjustment for word address */
+       eq_reg += band * (M98088_COEFS_PER_BAND << 1);
+
+       /* Step through the registers and coefs */
+       for (i = 0; i < M98088_COEFS_PER_BAND; i++) {
+               snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i]));
+               snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i]));
+       }
+}
+
+/*
+ * Excursion limiter modes
+ */
+static const char *max98088_exmode_texts[] = {
+       "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz",
+       "400-600Hz", "400-800Hz",
+};
+
+static const unsigned int max98088_exmode_values[] = {
+       0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32
+};
+
+static const struct soc_enum max98088_exmode_enum =
+       SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127,
+                             ARRAY_SIZE(max98088_exmode_texts),
+                             max98088_exmode_texts,
+                             max98088_exmode_values);
+static const struct snd_kcontrol_new max98088_exmode_controls =
+       SOC_DAPM_VALUE_ENUM("Route", max98088_exmode_enum);
+
+static const char *max98088_ex_thresh[] = { /* volts PP */
+       "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"};
+static const struct soc_enum max98088_ex_thresh_enum[] = {
+       SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8,
+               max98088_ex_thresh),
+};
+
+static const char *max98088_fltr_mode[] = {"Voice", "Music" };
+static const struct soc_enum max98088_filter_mode_enum[] = {
+       SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode),
+};
+
+static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" };
+
+static const struct soc_enum max98088_extmic_enum =
+       SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text);
+
+static const struct snd_kcontrol_new max98088_extmic_mux =
+       SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum);
+
+static const char *max98088_dai1_fltr[] = {
+       "Off", "fc=258/fs=16k", "fc=500/fs=16k",
+       "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"};
+static const struct soc_enum max98088_dai1_dac_filter_enum[] = {
+       SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr),
+};
+static const struct soc_enum max98088_dai1_adc_filter_enum[] = {
+       SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr),
+};
+
+static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       unsigned int sel = ucontrol->value.integer.value[0];
+
+       max98088->mic1pre = sel;
+       snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK,
+               (1+sel)<<M98088_MICPRE_SHIFT);
+
+       return 0;
+}
+
+static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = max98088->mic1pre;
+       return 0;
+}
+
+static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       unsigned int sel = ucontrol->value.integer.value[0];
+
+       max98088->mic2pre = sel;
+       snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK,
+               (1+sel)<<M98088_MICPRE_SHIFT);
+
+       return 0;
+}
+
+static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = max98088->mic2pre;
+       return 0;
+}
+
+static const unsigned int max98088_micboost_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+       2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
+};
+
+static const struct snd_kcontrol_new max98088_snd_controls[] = {
+
+       SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L,
+               M98088_REG_3A_LVL_HP_R, 0, 31, 0),
+       SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
+               M98088_REG_3E_LVL_SPK_R, 0, 31, 0),
+       SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L,
+               M98088_REG_3C_LVL_REC_R, 0, 31, 0),
+
+       SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L,
+               M98088_REG_3A_LVL_HP_R, 7, 1, 1),
+       SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L,
+               M98088_REG_3E_LVL_SPK_R, 7, 1, 1),
+       SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L,
+               M98088_REG_3C_LVL_REC_R, 7, 1, 1),
+
+       SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1),
+       SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1),
+
+       SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
+                       M98088_REG_35_LVL_MIC1, 5, 2, 0,
+                       max98088_mic1pre_get, max98088_mic1pre_set,
+                       max98088_micboost_tlv),
+       SOC_SINGLE_EXT_TLV("MIC2 Boost Volume",
+                       M98088_REG_36_LVL_MIC2, 5, 2, 0,
+                       max98088_mic2pre_get, max98088_mic2pre_set,
+                       max98088_micboost_tlv),
+
+       SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1),
+       SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1),
+
+       SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0),
+       SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0),
+
+       SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0),
+       SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0),
+
+       SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0),
+       SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0),
+
+       SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum),
+
+       SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum),
+       SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum),
+       SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum),
+       SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS,
+               0, 1, 0),
+
+       SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0),
+       SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0),
+       SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0),
+       SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0),
+
+       SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG,
+               4, 15, 0),
+       SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0),
+       SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0),
+       SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0),
+
+       SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0),
+       SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0),
+};
+
+/* Left speaker mixer switch */
+static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0),
+};
+
+/* Right speaker mixer switch */
+static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0),
+};
+
+/* Left headphone mixer switch */
+static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0),
+};
+
+/* Right headphone mixer switch */
+static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0),
+};
+
+/* Left earpiece/receiver mixer switch */
+static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0),
+};
+
+/* Right earpiece/receiver mixer switch */
+static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0),
+};
+
+/* Left ADC mixer switch */
+static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0),
+};
+
+/* Right ADC mixer switch */
+static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = {
+       SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0),
+       SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0),
+       SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0),
+       SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0),
+       SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0),
+       SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0),
+};
+
+static int max98088_mic_event(struct snd_soc_dapm_widget *w,
+                            struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (w->reg == M98088_REG_35_LVL_MIC1) {
+                       snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
+                               (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT);
+               } else {
+                       snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
+                               (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT);
+               }
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * The line inputs are 2-channel stereo inputs with the left
+ * and right channels sharing a common PGA power control signal.
+ */
+static int max98088_line_pga(struct snd_soc_dapm_widget *w,
+                            int event, int line, u8 channel)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       u8 *state;
+
+       BUG_ON(!((channel == 1) || (channel == 2)));
+
+       switch (line) {
+       case LINE_INA:
+               state = &max98088->ina_state;
+               break;
+       case LINE_INB:
+               state = &max98088->inb_state;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               *state |= channel;
+               snd_soc_update_bits(codec, w->reg,
+                       (1 << w->shift), (1 << w->shift));
+               break;
+       case SND_SOC_DAPM_POST_PMD:
+               *state &= ~channel;
+               if (*state == 0) {
+                       snd_soc_update_bits(codec, w->reg,
+                               (1 << w->shift), 0);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w,
+                                  struct snd_kcontrol *k, int event)
+{
+       return max98088_line_pga(w, event, LINE_INA, 1);
+}
+
+static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w,
+                                  struct snd_kcontrol *k, int event)
+{
+       return max98088_line_pga(w, event, LINE_INA, 2);
+}
+
+static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w,
+                                  struct snd_kcontrol *k, int event)
+{
+       return max98088_line_pga(w, event, LINE_INB, 1);
+}
+
+static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w,
+                                  struct snd_kcontrol *k, int event)
+{
+       return max98088_line_pga(w, event, LINE_INB, 2);
+}
+
+static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = {
+
+       SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0),
+       SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0),
+
+       SND_SOC_DAPM_DAC("DACL1", "HiFi Playback",
+               M98088_REG_4D_PWR_EN_OUT, 1, 0),
+       SND_SOC_DAPM_DAC("DACR1", "HiFi Playback",
+               M98088_REG_4D_PWR_EN_OUT, 0, 0),
+       SND_SOC_DAPM_DAC("DACL2", "Aux Playback",
+               M98088_REG_4D_PWR_EN_OUT, 1, 0),
+       SND_SOC_DAPM_DAC("DACR2", "Aux Playback",
+               M98088_REG_4D_PWR_EN_OUT, 0, 0),
+
+       SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT,
+               7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT,
+               6, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT,
+               5, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT,
+               4, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT,
+               3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT,
+               2, 0, NULL, 0),
+
+       SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0,
+               &max98088_extmic_mux),
+
+       SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_left_hp_mixer_controls[0],
+               ARRAY_SIZE(max98088_left_hp_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_right_hp_mixer_controls[0],
+               ARRAY_SIZE(max98088_right_hp_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_left_speaker_mixer_controls[0],
+               ARRAY_SIZE(max98088_left_speaker_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_right_speaker_mixer_controls[0],
+               ARRAY_SIZE(max98088_right_speaker_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0,
+         &max98088_left_rec_mixer_controls[0],
+               ARRAY_SIZE(max98088_left_rec_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0,
+         &max98088_right_rec_mixer_controls[0],
+               ARRAY_SIZE(max98088_right_rec_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_left_ADC_mixer_controls[0],
+               ARRAY_SIZE(max98088_left_ADC_mixer_controls)),
+
+       SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
+               &max98088_right_ADC_mixer_controls[0],
+               ARRAY_SIZE(max98088_right_ADC_mixer_controls)),
+
+       SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1,
+               5, 0, NULL, 0, max98088_mic_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2,
+               5, 0, NULL, 0, max98088_mic_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN,
+               7, 0, NULL, 0, max98088_pga_ina1_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN,
+               7, 0, NULL, 0, max98088_pga_ina2_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN,
+               6, 0, NULL, 0, max98088_pga_inb1_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN,
+               6, 0, NULL, 0, max98088_pga_inb2_event,
+               SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+       SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0),
+
+       SND_SOC_DAPM_MUX("EX Limiter Mode", SND_SOC_NOPM, 0, 0,
+               &max98088_exmode_controls),
+
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+       SND_SOC_DAPM_OUTPUT("SPKL"),
+       SND_SOC_DAPM_OUTPUT("SPKR"),
+       SND_SOC_DAPM_OUTPUT("RECL"),
+       SND_SOC_DAPM_OUTPUT("RECR"),
+
+       SND_SOC_DAPM_INPUT("MIC1"),
+       SND_SOC_DAPM_INPUT("MIC2"),
+       SND_SOC_DAPM_INPUT("INA1"),
+       SND_SOC_DAPM_INPUT("INA2"),
+       SND_SOC_DAPM_INPUT("INB1"),
+       SND_SOC_DAPM_INPUT("INB2"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* Left headphone output mixer */
+       {"Left HP Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Left HP Mixer", "Left DAC2 Switch", "DACL2"},
+       {"Left HP Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Left HP Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Left HP Mixer", "INA1 Switch", "INA1 Input"},
+       {"Left HP Mixer", "INA2 Switch", "INA2 Input"},
+       {"Left HP Mixer", "INB1 Switch", "INB1 Input"},
+       {"Left HP Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Right headphone output mixer */
+       {"Right HP Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Right HP Mixer", "Left DAC2 Switch", "DACL2"  },
+       {"Right HP Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Right HP Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Right HP Mixer", "INA1 Switch", "INA1 Input"},
+       {"Right HP Mixer", "INA2 Switch", "INA2 Input"},
+       {"Right HP Mixer", "INB1 Switch", "INB1 Input"},
+       {"Right HP Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Left speaker output mixer */
+       {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"},
+       {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Left SPK Mixer", "INA1 Switch", "INA1 Input"},
+       {"Left SPK Mixer", "INA2 Switch", "INA2 Input"},
+       {"Left SPK Mixer", "INB1 Switch", "INB1 Input"},
+       {"Left SPK Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Right speaker output mixer */
+       {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"},
+       {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Right SPK Mixer", "INA1 Switch", "INA1 Input"},
+       {"Right SPK Mixer", "INA2 Switch", "INA2 Input"},
+       {"Right SPK Mixer", "INB1 Switch", "INB1 Input"},
+       {"Right SPK Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Earpiece/Receiver output mixer */
+       {"Left REC Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Left REC Mixer", "Left DAC2 Switch", "DACL2"},
+       {"Left REC Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Left REC Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Left REC Mixer", "INA1 Switch", "INA1 Input"},
+       {"Left REC Mixer", "INA2 Switch", "INA2 Input"},
+       {"Left REC Mixer", "INB1 Switch", "INB1 Input"},
+       {"Left REC Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Earpiece/Receiver output mixer */
+       {"Right REC Mixer", "Left DAC1 Switch", "DACL1"},
+       {"Right REC Mixer", "Left DAC2 Switch", "DACL2"},
+       {"Right REC Mixer", "Right DAC1 Switch", "DACR1"},
+       {"Right REC Mixer", "Right DAC2 Switch", "DACR2"},
+       {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Right REC Mixer", "INA1 Switch", "INA1 Input"},
+       {"Right REC Mixer", "INA2 Switch", "INA2 Input"},
+       {"Right REC Mixer", "INB1 Switch", "INB1 Input"},
+       {"Right REC Mixer", "INB2 Switch", "INB2 Input"},
+
+       {"HP Left Out", NULL, "Left HP Mixer"},
+       {"HP Right Out", NULL, "Right HP Mixer"},
+       {"SPK Left Out", NULL, "Left SPK Mixer"},
+       {"SPK Right Out", NULL, "Right SPK Mixer"},
+       {"REC Left Out", NULL, "Left REC Mixer"},
+       {"REC Right Out", NULL, "Right REC Mixer"},
+
+       {"HPL", NULL, "HP Left Out"},
+       {"HPR", NULL, "HP Right Out"},
+       {"SPKL", NULL, "SPK Left Out"},
+       {"SPKR", NULL, "SPK Right Out"},
+       {"RECL", NULL, "REC Left Out"},
+       {"RECR", NULL, "REC Right Out"},
+
+       /* Left ADC input mixer */
+       {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Left ADC Mixer", "INA1 Switch", "INA1 Input"},
+       {"Left ADC Mixer", "INA2 Switch", "INA2 Input"},
+       {"Left ADC Mixer", "INB1 Switch", "INB1 Input"},
+       {"Left ADC Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Right ADC input mixer */
+       {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"},
+       {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"},
+       {"Right ADC Mixer", "INA1 Switch", "INA1 Input"},
+       {"Right ADC Mixer", "INA2 Switch", "INA2 Input"},
+       {"Right ADC Mixer", "INB1 Switch", "INB1 Input"},
+       {"Right ADC Mixer", "INB2 Switch", "INB2 Input"},
+
+       /* Inputs */
+       {"ADCL", NULL, "Left ADC Mixer"},
+       {"ADCR", NULL, "Right ADC Mixer"},
+       {"INA1 Input", NULL, "INA1"},
+       {"INA2 Input", NULL, "INA2"},
+       {"INB1 Input", NULL, "INB1"},
+       {"INB2 Input", NULL, "INB2"},
+       {"MIC1 Input", NULL, "MIC1"},
+       {"MIC2 Input", NULL, "MIC2"},
+};
+
+static int max98088_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, max98088_dapm_widgets,
+                                 ARRAY_SIZE(max98088_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_add_controls(codec, max98088_snd_controls,
+                            ARRAY_SIZE(max98088_snd_controls));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+/* codec mclk clock divider coefficients */
+static const struct {
+       u32 rate;
+       u8  sr;
+} rate_table[] = {
+       {8000,  0x10},
+       {11025, 0x20},
+       {16000, 0x30},
+       {22050, 0x40},
+       {24000, 0x50},
+       {32000, 0x60},
+       {44100, 0x70},
+       {48000, 0x80},
+       {88200, 0x90},
+       {96000, 0xA0},
+};
+
+static inline int rate_value(int rate, u8 *value)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
+               if (rate_table[i].rate >= rate) {
+                       *value = rate_table[i].sr;
+                       return 0;
+               }
+       }
+       *value = rate_table[0].sr;
+       return -EINVAL;
+}
+
+static int max98088_dai1_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 max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_cdata *cdata;
+       unsigned long long ni;
+       unsigned int rate;
+       u8 regval;
+
+       cdata = &max98088->dai[0];
+
+       rate = params_rate(params);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+                       M98088_DAI_WS, 0);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+                       M98088_DAI_WS, M98088_DAI_WS);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
+
+       if (rate_value(rate, &regval))
+               return -EINVAL;
+
+       snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE,
+               M98088_CLKMODE_MASK, regval);
+       cdata->rate = rate;
+
+       /* Configure NI when operating as master */
+       if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT)
+               & M98088_DAI_MAS) {
+               if (max98088->sysclk == 0) {
+                       dev_err(codec->dev, "Invalid system clock frequency\n");
+                       return -EINVAL;
+               }
+               ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
+                               * (unsigned long long int)rate;
+               do_div(ni, (unsigned long long int)max98088->sysclk);
+               snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
+                       (ni >> 8) & 0x7F);
+               snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
+                       ni & 0xFF);
+       }
+
+       /* Update sample rate mode */
+       if (rate < 50000)
+               snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
+                       M98088_DAI_DHF, 0);
+       else
+               snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
+                       M98088_DAI_DHF, M98088_DAI_DHF);
+
+       snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
+               M98088_SHDNRUN);
+
+       return 0;
+}
+
+static int max98088_dai2_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 max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_cdata *cdata;
+       unsigned long long ni;
+       unsigned int rate;
+       u8 regval;
+
+       cdata = &max98088->dai[1];
+
+       rate = params_rate(params);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+                       M98088_DAI_WS, 0);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+                       M98088_DAI_WS, M98088_DAI_WS);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
+
+       if (rate_value(rate, &regval))
+               return -EINVAL;
+
+       snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE,
+               M98088_CLKMODE_MASK, regval);
+       cdata->rate = rate;
+
+       /* Configure NI when operating as master */
+       if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT)
+               & M98088_DAI_MAS) {
+               if (max98088->sysclk == 0) {
+                       dev_err(codec->dev, "Invalid system clock frequency\n");
+                       return -EINVAL;
+               }
+               ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
+                               * (unsigned long long int)rate;
+               do_div(ni, (unsigned long long int)max98088->sysclk);
+               snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
+                       (ni >> 8) & 0x7F);
+               snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
+                       ni & 0xFF);
+       }
+
+       /* Update sample rate mode */
+       if (rate < 50000)
+               snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
+                       M98088_DAI_DHF, 0);
+       else
+               snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
+                       M98088_DAI_DHF, M98088_DAI_DHF);
+
+       snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
+               M98088_SHDNRUN);
+
+       return 0;
+}
+
+static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
+                                  int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+
+       /* Requested clock frequency is already setup */
+       if (freq == max98088->sysclk)
+               return 0;
+
+       max98088->sysclk = freq; /* remember current sysclk */
+
+       /* Setup clocks for slave mode, and using the PLL
+        * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
+        *         0x02 (when master clk is 20MHz to 30MHz)..
+        */
+       if ((freq >= 10000000) && (freq < 20000000)) {
+               snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10);
+       } else if ((freq >= 20000000) && (freq < 30000000)) {
+               snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20);
+       } else {
+               dev_err(codec->dev, "Invalid master clock frequency\n");
+               return -EINVAL;
+       }
+
+       if (snd_soc_read(codec, M98088_REG_51_PWR_SYS)  & M98088_SHDNRUN) {
+               snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
+                       M98088_SHDNRUN, 0);
+               snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
+                       M98088_SHDNRUN, M98088_SHDNRUN);
+       }
+
+       dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
+
+       max98088->sysclk = freq;
+       return 0;
+}
+
+static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai,
+                                unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_cdata *cdata;
+       u8 reg15val;
+       u8 reg14val = 0;
+
+       cdata = &max98088->dai[0];
+
+       if (fmt != cdata->fmt) {
+               cdata->fmt = fmt;
+
+               switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       /* Slave mode PLL */
+                       snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
+                               0x80);
+                       snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
+                               0x00);
+                       break;
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       /* Set to master mode */
+                       reg14val |= M98088_DAI_MAS;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFM:
+               case SND_SOC_DAIFMT_CBM_CFS:
+               default:
+                       dev_err(codec->dev, "Clock mode unsupported");
+                       return -EINVAL;
+               }
+
+               switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+               case SND_SOC_DAIFMT_I2S:
+                       reg14val |= M98088_DAI_DLY;
+                       break;
+               case SND_SOC_DAIFMT_LEFT_J:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       reg14val |= M98088_DAI_WCI;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       reg14val |= M98088_DAI_BCI;
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       reg14val |= M98088_DAI_BCI|M98088_DAI_WCI;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
+                       M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
+                       M98088_DAI_WCI, reg14val);
+
+               reg15val = M98088_DAI_BSEL64;
+               if (max98088->digmic)
+                       reg15val |= M98088_DAI_OSR64;
+               snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val);
+       }
+
+       return 0;
+}
+
+static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
+                                unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_cdata *cdata;
+       u8 reg1Cval = 0;
+
+       cdata = &max98088->dai[1];
+
+       if (fmt != cdata->fmt) {
+               cdata->fmt = fmt;
+
+               switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       /* Slave mode PLL */
+                       snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
+                               0x80);
+                       snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
+                               0x00);
+                       break;
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       /* Set to master mode */
+                       reg1Cval |= M98088_DAI_MAS;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFM:
+               case SND_SOC_DAIFMT_CBM_CFS:
+               default:
+                       dev_err(codec->dev, "Clock mode unsupported");
+                       return -EINVAL;
+               }
+
+               switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+               case SND_SOC_DAIFMT_I2S:
+                       reg1Cval |= M98088_DAI_DLY;
+                       break;
+               case SND_SOC_DAIFMT_LEFT_J:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       reg1Cval |= M98088_DAI_WCI;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       reg1Cval |= M98088_DAI_BCI;
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+               snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
+                       M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
+                       M98088_DAI_WCI, reg1Cval);
+
+               snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK,
+                       M98088_DAI_BSEL64);
+       }
+
+       return 0;
+}
+
+static void max98088_sync_cache(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       int i;
+
+       if (!codec->cache_sync)
+               return;
+
+       codec->cache_only = 0;
+
+       /* write back cached values if they're writeable and
+        * different from the hardware default.
+        */
+       for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
+               if (!max98088_access[i].writable)
+                       continue;
+
+               if (max98088->reg_cache[i] == max98088_reg[i])
+                       continue;
+
+               snd_soc_write(codec, i, max98088->reg_cache[i]);
+       }
+
+       codec->cache_sync = 0;
+}
+
+static int max98088_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)
+                       max98088_sync_cache(codec);
+
+               snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+                               M98088_MBEN, M98088_MBEN);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
+                               M98088_MBEN, 0);
+               codec->cache_sync = 1;
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
+#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max98088_dai1_ops = {
+       .set_sysclk = max98088_dai_set_sysclk,
+       .set_fmt = max98088_dai1_set_fmt,
+       .hw_params = max98088_dai1_hw_params,
+};
+
+static struct snd_soc_dai_ops max98088_dai2_ops = {
+       .set_sysclk = max98088_dai_set_sysclk,
+       .set_fmt = max98088_dai2_set_fmt,
+       .hw_params = max98088_dai2_hw_params,
+};
+
+static struct snd_soc_dai_driver max98088_dai[] = {
+{
+       .name = "HiFi",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = MAX98088_RATES,
+               .formats = MAX98088_FORMATS,
+       },
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = MAX98088_RATES,
+               .formats = MAX98088_FORMATS,
+       },
+        .ops = &max98088_dai1_ops,
+},
+{
+       .name = "Aux",
+       .playback = {
+               .stream_name = "Aux Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = MAX98088_RATES,
+               .formats = MAX98088_FORMATS,
+       },
+       .ops = &max98088_dai2_ops,
+}
+};
+
+static int max98088_get_channel(const char *name)
+{
+       if (strcmp(name, "EQ1 Mode") == 0)
+               return 0;
+       if (strcmp(name, "EQ2 Mode") == 0)
+               return 1;
+       return -EINVAL;
+}
+
+static void max98088_setup_eq1(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_pdata *pdata = max98088->pdata;
+       struct max98088_eq_cfg *coef_set;
+       int best, best_val, save, i, sel, fs;
+       struct max98088_cdata *cdata;
+
+       cdata = &max98088->dai[0];
+
+       if (!pdata || !max98088->eq_textcnt)
+               return;
+
+       /* Find the selected configuration with nearest sample rate */
+       fs = cdata->rate;
+       sel = cdata->eq_sel;
+
+       best = 0;
+       best_val = INT_MAX;
+       for (i = 0; i < pdata->eq_cfgcnt; i++) {
+               if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
+                   abs(pdata->eq_cfg[i].rate - fs) < best_val) {
+                       best = i;
+                       best_val = abs(pdata->eq_cfg[i].rate - fs);
+               }
+       }
+
+       dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
+               pdata->eq_cfg[best].name,
+               pdata->eq_cfg[best].rate, fs);
+
+       /* Disable EQ while configuring, and save current on/off state */
+       save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
+       snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0);
+
+       coef_set = &pdata->eq_cfg[sel];
+
+       m98088_eq_band(codec, 0, 0, coef_set->band1);
+       m98088_eq_band(codec, 0, 1, coef_set->band2);
+       m98088_eq_band(codec, 0, 2, coef_set->band3);
+       m98088_eq_band(codec, 0, 3, coef_set->band4);
+       m98088_eq_band(codec, 0, 4, coef_set->band5);
+
+       /* Restore the original on/off state */
+       snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save);
+}
+
+static void max98088_setup_eq2(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_pdata *pdata = max98088->pdata;
+       struct max98088_eq_cfg *coef_set;
+       int best, best_val, save, i, sel, fs;
+       struct max98088_cdata *cdata;
+
+       cdata = &max98088->dai[1];
+
+       if (!pdata || !max98088->eq_textcnt)
+               return;
+
+       /* Find the selected configuration with nearest sample rate */
+       fs = cdata->rate;
+
+       sel = cdata->eq_sel;
+       best = 0;
+       best_val = INT_MAX;
+       for (i = 0; i < pdata->eq_cfgcnt; i++) {
+               if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
+                   abs(pdata->eq_cfg[i].rate - fs) < best_val) {
+                       best = i;
+                       best_val = abs(pdata->eq_cfg[i].rate - fs);
+               }
+       }
+
+       dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
+               pdata->eq_cfg[best].name,
+               pdata->eq_cfg[best].rate, fs);
+
+       /* Disable EQ while configuring, and save current on/off state */
+       save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
+       snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0);
+
+       coef_set = &pdata->eq_cfg[sel];
+
+       m98088_eq_band(codec, 1, 0, coef_set->band1);
+       m98088_eq_band(codec, 1, 1, coef_set->band2);
+       m98088_eq_band(codec, 1, 2, coef_set->band3);
+       m98088_eq_band(codec, 1, 3, coef_set->band4);
+       m98088_eq_band(codec, 1, 4, coef_set->band5);
+
+       /* Restore the original on/off state */
+       snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN,
+               save);
+}
+
+static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_pdata *pdata = max98088->pdata;
+       int channel = max98088_get_channel(kcontrol->id.name);
+       struct max98088_cdata *cdata;
+       int sel = ucontrol->value.integer.value[0];
+
+       cdata = &max98088->dai[channel];
+
+       if (sel >= pdata->eq_cfgcnt)
+               return -EINVAL;
+
+       cdata->eq_sel = sel;
+
+       switch (channel) {
+       case 0:
+               max98088_setup_eq1(codec);
+               break;
+       case 1:
+               max98088_setup_eq2(codec);
+               break;
+       }
+
+       return 0;
+}
+
+static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
+                                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       int channel = max98088_get_channel(kcontrol->id.name);
+       struct max98088_cdata *cdata;
+
+       cdata = &max98088->dai[channel];
+       ucontrol->value.enumerated.item[0] = cdata->eq_sel;
+       return 0;
+}
+
+static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_pdata *pdata = max98088->pdata;
+       struct max98088_eq_cfg *cfg;
+       unsigned int cfgcnt;
+       int i, j;
+       const char **t;
+       int ret;
+
+       struct snd_kcontrol_new controls[] = {
+               SOC_ENUM_EXT("EQ1 Mode",
+                       max98088->eq_enum,
+                       max98088_get_eq_enum,
+                       max98088_put_eq_enum),
+               SOC_ENUM_EXT("EQ2 Mode",
+                       max98088->eq_enum,
+                       max98088_get_eq_enum,
+                       max98088_put_eq_enum),
+       };
+
+       cfg = pdata->eq_cfg;
+       cfgcnt = pdata->eq_cfgcnt;
+
+       /* Setup an array of texts for the equalizer enum.
+        * This is based on Mark Brown's equalizer driver code.
+        */
+       max98088->eq_textcnt = 0;
+       max98088->eq_texts = NULL;
+       for (i = 0; i < cfgcnt; i++) {
+               for (j = 0; j < max98088->eq_textcnt; j++) {
+                       if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0)
+                               break;
+               }
+
+               if (j != max98088->eq_textcnt)
+                       continue;
+
+               /* Expand the array */
+               t = krealloc(max98088->eq_texts,
+                            sizeof(char *) * (max98088->eq_textcnt + 1),
+                            GFP_KERNEL);
+               if (t == NULL)
+                       continue;
+
+               /* Store the new entry */
+               t[max98088->eq_textcnt] = cfg[i].name;
+               max98088->eq_textcnt++;
+               max98088->eq_texts = t;
+       }
+
+       /* Now point the soc_enum to .texts array items */
+       max98088->eq_enum.texts = max98088->eq_texts;
+       max98088->eq_enum.max = max98088->eq_textcnt;
+
+       ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
+}
+
+static void max98088_handle_pdata(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_pdata *pdata = max98088->pdata;
+       u8 regval = 0;
+
+       if (!pdata) {
+               dev_dbg(codec->dev, "No platform data\n");
+               return;
+       }
+
+       /* Configure mic for analog/digital mic mode */
+       if (pdata->digmic_left_mode)
+               regval |= M98088_DIGMIC_L;
+
+       if (pdata->digmic_right_mode)
+               regval |= M98088_DIGMIC_R;
+
+       max98088->digmic = (regval ? 1 : 0);
+
+       snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval);
+
+       /* Configure receiver output */
+       regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0);
+       snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL,
+               M98088_REC_LINEMODE_MASK, regval);
+
+       /* Configure equalizers */
+       if (pdata->eq_cfgcnt)
+               max98088_handle_eq_pdata(codec);
+}
+
+#ifdef CONFIG_PM
+static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int max98088_resume(struct snd_soc_codec *codec)
+{
+       max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+}
+#else
+#define max98088_suspend NULL
+#define max98088_resume NULL
+#endif
+
+static int max98088_probe(struct snd_soc_codec *codec)
+{
+       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       struct max98088_cdata *cdata;
+       int ret = 0;
+
+       codec->cache_sync = 1;
+       memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       /* initalize private data */
+
+       max98088->sysclk = (unsigned)-1;
+       max98088->eq_textcnt = 0;
+
+       cdata = &max98088->dai[0];
+       cdata->rate = (unsigned)-1;
+       cdata->fmt  = (unsigned)-1;
+       cdata->eq_sel = 0;
+
+       cdata = &max98088->dai[1];
+       cdata->rate = (unsigned)-1;
+       cdata->fmt  = (unsigned)-1;
+       cdata->eq_sel = 0;
+
+       max98088->ina_state = 0;
+       max98088->inb_state = 0;
+       max98088->ex_mode = 0;
+       max98088->digmic = 0;
+       max98088->mic1pre = 0;
+       max98088->mic2pre = 0;
+
+       ret = snd_soc_read(codec, M98088_REG_FF_REV_ID);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_access;
+       }
+       dev_info(codec->dev, "revision %c\n", ret + 'A');
+
+       snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV);
+
+       /* initialize registers cache to hardware default */
+       max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00);
+
+       snd_soc_write(codec, M98088_REG_22_MIX_DAC,
+               M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL|
+               M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR);
+
+       snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0);
+       snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F);
+
+       snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG,
+               M98088_S1NORMAL|M98088_SDATA);
+
+       snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG,
+               M98088_S2NORMAL|M98088_SDATA);
+
+       max98088_handle_pdata(codec);
+
+       max98088_add_widgets(codec);
+
+err_access:
+       return ret;
+}
+
+static int max98088_remove(struct snd_soc_codec *codec)
+{
+       max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
+       .probe   = max98088_probe,
+       .remove  = max98088_remove,
+       .suspend = max98088_suspend,
+       .resume  = max98088_resume,
+       .set_bias_level = max98088_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(max98088_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = max98088_reg,
+       .volatile_register = max98088_volatile_register,
+};
+
+static int max98088_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
+{
+       struct max98088_priv *max98088;
+       int ret;
+
+       max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL);
+       if (max98088 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, max98088);
+       max98088->control_data = i2c;
+       max98088->pdata = i2c->dev.platform_data;
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_max98088, &max98088_dai[0], 2);
+       if (ret < 0)
+               kfree(max98088);
+       return ret;
+}
+
+static int max98088_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id max98088_i2c_id[] = {
+       { "max98088", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
+
+static struct i2c_driver max98088_i2c_driver = {
+       .driver = {
+               .name = "max98088",
+               .owner = THIS_MODULE,
+       },
+       .probe  = max98088_i2c_probe,
+       .remove = __devexit_p(max98088_i2c_remove),
+       .id_table = max98088_i2c_id,
+};
+
+static int __init max98088_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&max98088_i2c_driver);
+       if (ret)
+               pr_err("Failed to register max98088 I2C driver: %d\n", ret);
+
+       return ret;
+}
+module_init(max98088_init);
+
+static void __exit max98088_exit(void)
+{
+       i2c_del_driver(&max98088_i2c_driver);
+}
+module_exit(max98088_exit);
+
+MODULE_DESCRIPTION("ALSA SoC MAX98088 driver");
+MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h
new file mode 100644 (file)
index 0000000..56554c7
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * max98088.h -- MAX98088 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Maxim Integrated Products
+ *
+ * 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 _MAX98088_H
+#define _MAX98088_H
+
+/*
+ * MAX98088 Registers Definition
+ */
+#define M98088_REG_00_IRQ_STATUS            0x00
+#define M98088_REG_01_MIC_STATUS            0x01
+#define M98088_REG_02_JACK_STAUS            0x02
+#define M98088_REG_03_BATTERY_VOLTAGE       0x03
+#define M98088_REG_0F_IRQ_ENABLE            0x0F
+#define M98088_REG_10_SYS_CLK               0x10
+#define M98088_REG_11_DAI1_CLKMODE          0x11
+#define M98088_REG_12_DAI1_CLKCFG_HI        0x12
+#define M98088_REG_13_DAI1_CLKCFG_LO        0x13
+#define M98088_REG_14_DAI1_FORMAT           0x14
+#define M98088_REG_15_DAI1_CLOCK            0x15
+#define M98088_REG_16_DAI1_IOCFG            0x16
+#define M98088_REG_17_DAI1_TDM              0x17
+#define M98088_REG_18_DAI1_FILTERS          0x18
+#define M98088_REG_19_DAI2_CLKMODE          0x19
+#define M98088_REG_1A_DAI2_CLKCFG_HI        0x1A
+#define M98088_REG_1B_DAI2_CLKCFG_LO        0x1B
+#define M98088_REG_1C_DAI2_FORMAT           0x1C
+#define M98088_REG_1D_DAI2_CLOCK            0x1D
+#define M98088_REG_1E_DAI2_IOCFG            0x1E
+#define M98088_REG_1F_DAI2_TDM              0x1F
+#define M98088_REG_20_DAI2_FILTERS          0x20
+#define M98088_REG_21_SRC                   0x21
+#define M98088_REG_22_MIX_DAC               0x22
+#define M98088_REG_23_MIX_ADC_LEFT          0x23
+#define M98088_REG_24_MIX_ADC_RIGHT         0x24
+#define M98088_REG_25_MIX_HP_LEFT           0x25
+#define M98088_REG_26_MIX_HP_RIGHT          0x26
+#define M98088_REG_27_MIX_HP_CNTL           0x27
+#define M98088_REG_28_MIX_REC_LEFT          0x28
+#define M98088_REG_29_MIX_REC_RIGHT         0x29
+#define M98088_REG_2A_MIC_REC_CNTL          0x2A
+#define M98088_REG_2B_MIX_SPK_LEFT          0x2B
+#define M98088_REG_2C_MIX_SPK_RIGHT         0x2C
+#define M98088_REG_2D_MIX_SPK_CNTL          0x2D
+#define M98088_REG_2E_LVL_SIDETONE          0x2E
+#define M98088_REG_2F_LVL_DAI1_PLAY         0x2F
+#define M98088_REG_30_LVL_DAI1_PLAY_EQ      0x30
+#define M98088_REG_31_LVL_DAI2_PLAY         0x31
+#define M98088_REG_32_LVL_DAI2_PLAY_EQ      0x32
+#define M98088_REG_33_LVL_ADC_L             0x33
+#define M98088_REG_34_LVL_ADC_R             0x34
+#define M98088_REG_35_LVL_MIC1              0x35
+#define M98088_REG_36_LVL_MIC2              0x36
+#define M98088_REG_37_LVL_INA               0x37
+#define M98088_REG_38_LVL_INB               0x38
+#define M98088_REG_39_LVL_HP_L              0x39
+#define M98088_REG_3A_LVL_HP_R              0x3A
+#define M98088_REG_3B_LVL_REC_L             0x3B
+#define M98088_REG_3C_LVL_REC_R             0x3C
+#define M98088_REG_3D_LVL_SPK_L             0x3D
+#define M98088_REG_3E_LVL_SPK_R             0x3E
+#define M98088_REG_3F_MICAGC_CFG            0x3F
+#define M98088_REG_40_MICAGC_THRESH         0x40
+#define M98088_REG_41_SPKDHP                0x41
+#define M98088_REG_42_SPKDHP_THRESH         0x42
+#define M98088_REG_43_SPKALC_COMP           0x43
+#define M98088_REG_44_PWRLMT_CFG            0x44
+#define M98088_REG_45_PWRLMT_TIME           0x45
+#define M98088_REG_46_THDLMT_CFG            0x46
+#define M98088_REG_47_CFG_AUDIO_IN          0x47
+#define M98088_REG_48_CFG_MIC               0x48
+#define M98088_REG_49_CFG_LEVEL             0x49
+#define M98088_REG_4A_CFG_BYPASS            0x4A
+#define M98088_REG_4B_CFG_JACKDET           0x4B
+#define M98088_REG_4C_PWR_EN_IN             0x4C
+#define M98088_REG_4D_PWR_EN_OUT            0x4D
+#define M98088_REG_4E_BIAS_CNTL             0x4E
+#define M98088_REG_4F_DAC_BIAS1             0x4F
+#define M98088_REG_50_DAC_BIAS2             0x50
+#define M98088_REG_51_PWR_SYS               0x51
+#define M98088_REG_52_DAI1_EQ_BASE          0x52
+#define M98088_REG_84_DAI2_EQ_BASE          0x84
+#define M98088_REG_B6_DAI1_BIQUAD_BASE      0xB6
+#define M98088_REG_C0_DAI2_BIQUAD_BASE      0xC0
+#define M98088_REG_FF_REV_ID                0xFF
+
+#define M98088_REG_CNT                      (0xFF+1)
+
+/* MAX98088 Registers Bit Fields */
+
+/* M98088_REG_11_DAI1_CLKMODE, M98088_REG_19_DAI2_CLKMODE */
+       #define M98088_CLKMODE_MASK             0xFF
+
+/* M98088_REG_14_DAI1_FORMAT, M98088_REG_1C_DAI2_FORMAT */
+       #define M98088_DAI_MAS                  (1<<7)
+       #define M98088_DAI_WCI                  (1<<6)
+       #define M98088_DAI_BCI                  (1<<5)
+       #define M98088_DAI_DLY                  (1<<4)
+       #define M98088_DAI_TDM                  (1<<2)
+       #define M98088_DAI_FSW                  (1<<1)
+       #define M98088_DAI_WS                   (1<<0)
+
+/* M98088_REG_15_DAI1_CLOCK, M98088_REG_1D_DAI2_CLOCK */
+       #define M98088_DAI_BSEL64               (1<<0)
+       #define M98088_DAI_OSR64                (1<<6)
+
+/* M98088_REG_16_DAI1_IOCFG, M98088_REG_1E_DAI2_IOCFG */
+       #define M98088_S1NORMAL                 (1<<6)
+       #define M98088_S2NORMAL                 (2<<6)
+       #define M98088_SDATA                    (3<<0)
+
+/* M98088_REG_18_DAI1_FILTERS, M98088_REG_20_DAI2_FILTERS */
+       #define M98088_DAI_DHF                  (1<<3)
+
+/* M98088_REG_22_MIX_DAC */
+       #define M98088_DAI1L_TO_DACL            (1<<7)
+       #define M98088_DAI1R_TO_DACL            (1<<6)
+       #define M98088_DAI2L_TO_DACL            (1<<5)
+       #define M98088_DAI2R_TO_DACL            (1<<4)
+       #define M98088_DAI1L_TO_DACR            (1<<3)
+       #define M98088_DAI1R_TO_DACR            (1<<2)
+       #define M98088_DAI2L_TO_DACR            (1<<1)
+       #define M98088_DAI2R_TO_DACR            (1<<0)
+
+/* M98088_REG_2A_MIC_REC_CNTL */
+       #define M98088_REC_LINEMODE             (1<<7)
+       #define M98088_REC_LINEMODE_MASK        (1<<7)
+
+/* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */
+       #define M98088_MICPRE_MASK              (3<<5)
+       #define M98088_MICPRE_SHIFT             5
+
+/* M98088_REG_3A_LVL_HP_R */
+       #define M98088_HP_MUTE                  (1<<7)
+
+/* M98088_REG_3C_LVL_REC_R */
+       #define M98088_REC_MUTE                 (1<<7)
+
+/* M98088_REG_3E_LVL_SPK_R */
+       #define M98088_SP_MUTE                  (1<<7)
+
+/* M98088_REG_48_CFG_MIC */
+       #define M98088_EXTMIC_MASK              (3<<0)
+       #define M98088_DIGMIC_L                 (1<<5)
+       #define M98088_DIGMIC_R                 (1<<4)
+
+/* M98088_REG_49_CFG_LEVEL */
+       #define M98088_VSEN                     (1<<6)
+       #define M98088_ZDEN                     (1<<5)
+       #define M98088_EQ2EN                    (1<<1)
+       #define M98088_EQ1EN                    (1<<0)
+
+/* M98088_REG_4C_PWR_EN_IN */
+       #define M98088_INAEN                    (1<<7)
+       #define M98088_INBEN                    (1<<6)
+       #define M98088_MBEN                     (1<<3)
+       #define M98088_ADLEN                    (1<<1)
+       #define M98088_ADREN                    (1<<0)
+
+/* M98088_REG_4D_PWR_EN_OUT */
+       #define M98088_HPLEN                    (1<<7)
+       #define M98088_HPREN                    (1<<6)
+       #define M98088_HPEN                     ((1<<7)|(1<<6))
+       #define M98088_SPLEN                    (1<<5)
+       #define M98088_SPREN                    (1<<4)
+       #define M98088_RECEN                    (1<<3)
+       #define M98088_DALEN                    (1<<1)
+       #define M98088_DAREN                    (1<<0)
+
+/* M98088_REG_51_PWR_SYS */
+       #define M98088_SHDNRUN                  (1<<7)
+       #define M98088_PERFMODE                 (1<<3)
+       #define M98088_HPPLYBACK                (1<<2)
+       #define M98088_PWRSV8K                  (1<<1)
+       #define M98088_PWRSV                    (1<<0)
+
+/* Line inputs */
+#define LINE_INA  0
+#define LINE_INB  1
+
+#define M98088_COEFS_PER_BAND               5
+
+#define M98088_BYTE1(w) ((w >> 8) & 0xff)
+#define M98088_BYTE0(w) (w & 0xff)
+
+#endif
index 5a5f187..bd8f26e 100644 (file)
@@ -32,8 +32,8 @@
 #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |   \
                       SNDRV_PCM_RATE_48000)
 
-struct snd_soc_dai pcm3008_dai = {
-       .name = "PCM3008 HiFi",
+static struct snd_soc_dai_driver pcm3008_dai = {
+       .name = "pcm3008-hifi",
        .playback = {
                .stream_name = "PCM3008 Playback",
                .channels_min = 1,
@@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE,
        },
 };
-EXPORT_SYMBOL_GPL(pcm3008_dai);
 
 static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
 {
@@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
        gpio_free(setup->pdda_pin);
 }
 
-static int pcm3008_soc_probe(struct platform_device *pdev)
+static int pcm3008_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct pcm3008_setup_data *setup = socdev->codec_data;
+       struct pcm3008_setup_data *setup = codec->dev->platform_data;
        int ret = 0;
 
        printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (!socdev->card->codec)
-               return -ENOMEM;
-
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->name = "PCM3008";
-       codec->owner = THIS_MODULE;
-       codec->dai = &pcm3008_dai;
-       codec->num_dai = 1;
-       codec->write = NULL;
-       codec->read = NULL;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       /* Register PCMs. */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "pcm3008: failed to create pcms\n");
-               goto pcm_err;
-       }
-
        /* DEM1  DEM0  DE-EMPHASIS_MODE
         * Low   Low   De-emphasis 44.1 kHz ON
         * Low   High  De-emphasis OFF
@@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
 
 gpio_err:
        pcm3008_gpio_free(setup);
-pcm_err:
-       kfree(socdev->card->codec);
 
        return ret;
 }
 
-static int pcm3008_soc_remove(struct platform_device *pdev)
+static int pcm3008_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-       struct pcm3008_setup_data *setup = socdev->codec_data;
-
-       if (!codec)
-               return 0;
+       struct pcm3008_setup_data *setup = codec->dev->platform_data;
 
        pcm3008_gpio_free(setup);
-       snd_soc_free_pcms(socdev);
-       kfree(socdev->card->codec);
-
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct pcm3008_setup_data *setup = socdev->codec_data;
+       struct pcm3008_setup_data *setup = codec->dev->platform_data;
 
        gpio_set_value(setup->pdad_pin, 0);
        gpio_set_value(setup->pdda_pin, 0);
@@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
        return 0;
 }
 
-static int pcm3008_soc_resume(struct platform_device *pdev)
+static int pcm3008_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct pcm3008_setup_data *setup = socdev->codec_data;
+       struct pcm3008_setup_data *setup = codec->dev->platform_data;
 
        gpio_set_value(setup->pdad_pin, 1);
        gpio_set_value(setup->pdda_pin, 1);
@@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev)
 #define pcm3008_soc_resume NULL
 #endif
 
-struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
+static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
        .probe =        pcm3008_soc_probe,
        .remove =       pcm3008_soc_remove,
        .suspend =      pcm3008_soc_suspend,
        .resume =       pcm3008_soc_resume,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
 
-static int __init pcm3008_init(void)
+static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
+}
+
+static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+MODULE_ALIAS("platform:pcm3008-codec");
+
+static struct platform_driver pcm3008_codec_driver = {
+       .probe          = pcm3008_codec_probe,
+       .remove         = __devexit_p(pcm3008_codec_remove),
+       .driver         = {
+               .name   = "pcm3008-codec",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init pcm3008_modinit(void)
 {
-       return snd_soc_register_dai(&pcm3008_dai);
+       return platform_driver_register(&pcm3008_codec_driver);
 }
-module_init(pcm3008_init);
+module_init(pcm3008_modinit);
 
 static void __exit pcm3008_exit(void)
 {
-       snd_soc_unregister_dai(&pcm3008_dai);
+       platform_driver_unregister(&pcm3008_codec_driver);
 }
 module_exit(pcm3008_exit);
 
index d04e87d..7e5489a 100644 (file)
@@ -19,7 +19,4 @@ struct pcm3008_setup_data {
        unsigned pdda_pin;
 };
 
-extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
-extern struct snd_soc_dai pcm3008_dai;
-
 #endif
index 9119836..4c32b54 100644 (file)
 #include <sound/pcm.h>
 #include <sound/initval.h>
 
-#include "spdif_transciever.h"
-
 MODULE_LICENSE("GPL");
 
 #define STUB_RATES     SNDRV_PCM_RATE_8000_96000
 #define STUB_FORMATS   SNDRV_PCM_FMTBIT_S16_LE
 
-static struct snd_soc_codec *spdif_dit_codec;
-
-static int spdif_dit_codec_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       if (spdif_dit_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = spdif_dit_codec;
-       codec = spdif_dit_codec;
-
-       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 err_create_pcms;
-       }
-
-       return 0;
-
-err_create_pcms:
-       return ret;
-}
-
-static int spdif_dit_codec_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-
-       return 0;
-}
 
-struct snd_soc_codec_device soc_codec_dev_spdif_dit = {
-       .probe          = spdif_dit_codec_probe,
-       .remove         = spdif_dit_codec_remove,
-}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
+static struct snd_soc_codec_driver soc_codec_spdif_dit;
 
-struct snd_soc_dai dit_stub_dai = {
-       .name           = "DIT",
+static struct snd_soc_dai_driver dit_stub_dai = {
+       .name           = "dit-hifi",
        .playback       = {
                .stream_name    = "Playback",
                .channels_min   = 1,
@@ -80,65 +39,16 @@ 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)
 {
-       struct snd_soc_codec *codec;
-       int ret;
-
-       if (spdif_dit_codec) {
-               dev_err(&pdev->dev, "Another Codec is registered\n");
-               ret = -EINVAL;
-               goto err_reg_codec;
-       }
-
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       codec->dev = &pdev->dev;
-
-       mutex_init(&codec->mutex);
-
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "spdif-dit";
-       codec->owner = THIS_MODULE;
-       codec->dai = &dit_stub_dai;
-       codec->num_dai = 1;
-
-       spdif_dit_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err_reg_codec;
-       }
-
-       dit_stub_dai.dev = &pdev->dev;
-       ret = snd_soc_register_dai(&dit_stub_dai);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to register dai: %d\n", ret);
-               goto err_reg_dai;
-       }
-
-       return 0;
-
-err_reg_dai:
-       snd_soc_unregister_codec(codec);
-err_reg_codec:
-       kfree(spdif_dit_codec);
-       return ret;
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
+                       &dit_stub_dai, 1);
 }
 
 static int spdif_dit_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&dit_stub_dai);
-       snd_soc_unregister_codec(spdif_dit_codec);
-       kfree(spdif_dit_codec);
-       spdif_dit_codec = NULL;
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
deleted file mode 100644 (file)
index 1e10212..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * ALSA SoC DIT/DIR driver header
- *
- * Author:      Steve Chen,  <schen@mvista.com>
- * Copyright:   (C) 2008 MontaVista Software, Inc., <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef CODEC_STUBS_H
-#define CODEC_STUBS_H
-
-extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
-extern struct snd_soc_dai dit_stub_dai;
-
-#endif /* CODEC_STUBS_H */
index b47ed4f..6f38d61 100644 (file)
 
 #define SSM2602_VERSION "0.1"
 
-struct snd_soc_codec_device soc_codec_dev_ssm2602;
-
 /* codec private data */
 struct ssm2602_priv {
        unsigned int sysclk;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        struct snd_pcm_substream *master_substream;
        struct snd_pcm_substream *slave_substream;
 };
@@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
 {
        u16 srate;
        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 snd_soc_codec *codec = rtd->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
        struct i2c_client *i2c = codec->control_data;
        u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
@@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
        struct i2c_client *i2c = codec->control_data;
        struct snd_pcm_runtime *master_runtime;
@@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
                               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 snd_soc_codec *codec = rtd->codec;
        /* set active */
        ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
 
@@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
                             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 snd_soc_codec *codec = rtd->codec;
        struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
 
        /* deactivate */
@@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = {
        .set_fmt        = ssm2602_set_dai_fmt,
 };
 
-struct snd_soc_dai ssm2602_dai = {
-       .name = "SSM2602",
+static struct snd_soc_dai_driver ssm2602_dai = {
+       .name = "ssm2602-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = {
                .formats = SSM2602_FORMATS,},
        .ops = &ssm2602_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ssm2602_dai);
 
-static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state)
+static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int ssm2602_resume(struct platform_device *pdev)
+static int ssm2602_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -563,36 +553,17 @@ static int ssm2602_resume(struct platform_device *pdev)
        return 0;
 }
 
-/*
- * initialise the ssm2602 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int ssm2602_init(struct snd_soc_device *socdev)
+static int ssm2602_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int reg, ret = 0;
-
-       codec->name = "SSM2602";
-       codec->owner = THIS_MODULE;
-       codec->read = ssm2602_read_reg_cache;
-       codec->write = ssm2602_write;
-       codec->set_bias_level = ssm2602_set_bias_level;
-       codec->dai = &ssm2602_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = sizeof(ssm2602_reg);
-       codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg),
-                                       GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0, reg;
+
+       pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
+
+       codec->control_data = ssm2602->control_data;
 
        ssm2602_reset(codec);
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               pr_err("ssm2602: failed to create pcms\n");
-               goto pcm_err;
-       }
        /*power on device*/
        ssm2602_write(codec, SSM2602_ACTIVE, 0);
        /* set the update bits */
@@ -614,13 +585,27 @@ static int ssm2602_init(struct snd_soc_device *socdev)
        ssm2602_add_widgets(codec);
 
        return ret;
+}
 
-pcm_err:
-       kfree(codec->reg_cache);
-       return ret;
+/* remove everything here */
+static int ssm2602_remove(struct snd_soc_codec *codec)
+{
+       ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-static struct snd_soc_device *ssm2602_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
+       .probe =        ssm2602_probe,
+       .remove =       ssm2602_remove,
+       .suspend =      ssm2602_suspend,
+       .resume =       ssm2602_resume,
+       .read = ssm2602_read_reg_cache,
+       .write = ssm2602_write,
+       .set_bias_level = ssm2602_set_bias_level,
+       .reg_cache_size = sizeof(ssm2602_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = ssm2602_reg,
+};
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
@@ -632,24 +617,28 @@ static struct snd_soc_device *ssm2602_socdev;
 static int ssm2602_i2c_probe(struct i2c_client *i2c,
                             const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = ssm2602_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct ssm2602_priv *ssm2602;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
+       if (ssm2602 == NULL)
+               return -ENOMEM;
 
-       ret = ssm2602_init(socdev);
-       if (ret < 0)
-               pr_err("failed to initialise SSM2602\n");
+       i2c_set_clientdata(i2c, ssm2602);
+       ssm2602->control_data = i2c;
+       ssm2602->control_type = SND_SOC_I2C;
 
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
+       if (ret < 0)
+               kfree(ssm2602);
        return ret;
 }
 
 static int ssm2602_i2c_remove(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -658,130 +647,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {
        { }
 };
 MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
+
 /* corgi i2c codec control layer */
 static struct i2c_driver ssm2602_i2c_driver = {
        .driver = {
-               .name = "SSM2602 I2C Codec",
+               .name = "ssm2602-codec",
                .owner = THIS_MODULE,
        },
        .probe = ssm2602_i2c_probe,
        .remove = ssm2602_i2c_remove,
        .id_table = ssm2602_i2c_id,
 };
-
-static int ssm2602_add_i2c_device(struct platform_device *pdev,
-                                 const struct ssm2602_setup_data *setup)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&ssm2602_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "ssm2602", 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(&ssm2602_i2c_driver);
-       return -ENODEV;
-}
 #endif
 
-static int ssm2602_probe(struct platform_device *pdev)
+
+static int __init ssm2602_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct ssm2602_setup_data *setup;
-       struct snd_soc_codec *codec;
-       struct ssm2602_priv *ssm2602;
        int ret = 0;
-
-       pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
-       if (ssm2602 == NULL) {
-               kfree(codec);
-               return -ENOMEM;
-       }
-
-       snd_soc_codec_set_drvdata(codec, ssm2602);
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       ssm2602_socdev = socdev;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
-               ret = ssm2602_add_i2c_device(pdev, setup);
+       ret = i2c_add_driver(&ssm2602_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n",
+                      ret);
        }
-#else
-       /* other interfaces */
 #endif
        return ret;
 }
+module_init(ssm2602_modinit);
 
-/* remove everything here */
-static int ssm2602_remove(struct platform_device *pdev)
+static void __exit ssm2602_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               ssm2602_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(&ssm2602_i2c_driver);
 #endif
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
-       .probe =        ssm2602_probe,
-       .remove =       ssm2602_remove,
-       .suspend =      ssm2602_suspend,
-       .resume =       ssm2602_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
-
-static int __init ssm2602_modinit(void)
-{
-       return snd_soc_register_dai(&ssm2602_dai);
-}
-module_init(ssm2602_modinit);
-
-static void __exit ssm2602_exit(void)
-{
-       snd_soc_unregister_dai(&ssm2602_dai);
 }
 module_exit(ssm2602_exit);
 
index f344e6d..42a47d0 100644 (file)
@@ -124,7 +124,4 @@ struct ssm2602_setup_data {
        unsigned short i2c_address;
 };
 
-extern struct snd_soc_dai ssm2602_dai;
-extern struct snd_soc_codec_device soc_codec_dev_ssm2602;
-
 #endif
index ee86568..00d67cc 100644 (file)
@@ -25,7 +25,6 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
-#include <sound/soc-of-simple.h>
 
 #include "stac9766.h"
 
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
        return 0;
 }
 
-static int stac9766_codec_suspend(struct platform_device *pdev,
+static int stac9766_codec_suspend(struct snd_soc_codec *codec,
                                  pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int stac9766_codec_resume(struct platform_device *pdev)
+static int stac9766_codec_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        u16 id, reset;
 
        reset = 0;
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
        .prepare = ac97_digital_prepare,
 };
 
-struct snd_soc_dai stac9766_dai[] = {
+static struct snd_soc_dai_driver stac9766_dai[] = {
 {
-       .name = "stac9766 analog",
-       .id = 0,
+       .name = "stac9766-hifi-analog",
        .ac97_control = 1,
 
        /* stream cababilities */
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = {
        .ops = &stac9766_dai_ops_analog,
 },
 {
-       .name = "stac9766 IEC958",
-       .id = 1,
+       .name = "stac9766-hifi-IEC958",
        .ac97_control = 1,
 
        /* stream cababilities */
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = {
        .ops = &stac9766_dai_ops_digital,
 }
 };
-EXPORT_SYMBOL_GPL(stac9766_dai);
 
-static int stac9766_codec_probe(struct platform_device *pdev)
+static int stac9766_codec_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
        int ret = 0;
 
        printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (socdev->card->codec == NULL)
-               return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-       codec->reg_cache_size = sizeof(stac9766_reg);
-       codec->reg_cache_step = 2;
-
-       codec->name = "STAC9766";
-       codec->owner = THIS_MODULE;
-       codec->dai = stac9766_dai;
-       codec->num_dai = ARRAY_SIZE(stac9766_dai);
-       codec->write = stac9766_ac97_write;
-       codec->read = stac9766_ac97_read;
-       codec->set_bias_level = stac9766_set_bias_level;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0)
                goto codec_err;
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
        /* do a cold reset for the controller and then try
         * a warm reset followed by an optional cold reset for codec */
        stac9766_reset(codec, 0);
        ret = stac9766_reset(codec, 1);
        if (ret < 0) {
                printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
-               goto reset_err;
+               goto codec_err;
        }
 
        stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev)
 
        return 0;
 
-reset_err:
-       snd_soc_free_pcms(socdev);
-pcm_err:
-       snd_soc_free_ac97_codec(codec);
 codec_err:
-       kfree(snd_soc_codec_get_drvdata(codec));
-cache_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
+       snd_soc_free_ac97_codec(codec);
        return ret;
 }
 
-static int stac9766_codec_remove(struct platform_device *pdev)
+static int stac9766_codec_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-
-       snd_soc_free_pcms(socdev);
        snd_soc_free_ac97_codec(codec);
-       kfree(codec->reg_cache);
-       kfree(codec);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_stac9766 = {
+static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
+       .write = stac9766_ac97_write,
+       .read = stac9766_ac97_read,
+       .set_bias_level = stac9766_set_bias_level,
        .probe = stac9766_codec_probe,
        .remove = stac9766_codec_remove,
        .suspend = stac9766_codec_suspend,
        .resume = stac9766_codec_resume,
+       .reg_cache_size = sizeof(stac9766_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_step = 2,
+};
+
+static __devinit int stac9766_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
+}
+
+static int __devexit stac9766_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver stac9766_codec_driver = {
+       .driver = {
+                       .name = "stac9766-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = stac9766_probe,
+       .remove = __devexit_p(stac9766_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766);
+
+static int __init stac9766_init(void)
+{
+       return platform_driver_register(&stac9766_codec_driver);
+}
+module_init(stac9766_init);
+
+static void __exit stac9766_exit(void)
+{
+       platform_driver_unregister(&stac9766_codec_driver);
+}
+module_exit(stac9766_exit);
 
 MODULE_DESCRIPTION("ASoC stac9766 driver");
 MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
index 65642eb..c726f90 100644 (file)
@@ -14,8 +14,4 @@
 #define STAC9766_DAI_AC97_ANALOG               0
 #define STAC9766_DAI_AC97_DIGITAL              1
 
-extern struct snd_soc_dai stac9766_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_stac9766;
-
-
 #endif
index 0a4b0fe..e8652b1 100644 (file)
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = {
 
 /* AIC23 driver data */
 struct aic23 {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        int mclk;
        int requested_adc;
        int requested_dac;
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
                                 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 snd_soc_codec *codec = rtd->codec;
        u16 iface_reg;
        int ret;
-       struct aic23 *aic23 = container_of(codec, struct aic23, codec);
+       struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
        u32 sample_rate_adc = aic23->requested_adc;
        u32 sample_rate_dac = aic23->requested_dac;
        u32 sample_rate = params_rate(params);
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
                                   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 snd_soc_codec *codec = rtd->codec;
 
        /* set active */
        tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
                                 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 aic23 *aic23 = container_of(codec, struct aic23, codec);
+       struct snd_soc_codec *codec = rtd->codec;
+       struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
 
        /* deactivate */
        if (!codec->active) {
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int tlv320aic23_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 aic23 *aic23 = container_of(codec, struct aic23, codec);
+       struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
        aic23->mclk = freq;
        return 0;
 }
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
        .set_sysclk     = tlv320aic23_set_dai_sysclk,
 };
 
-struct snd_soc_dai tlv320aic23_dai = {
-       .name = "tlv320aic23",
+static struct snd_soc_dai_driver tlv320aic23_dai = {
+       .name = "tlv320aic23-hifi",
        .playback = {
                     .stream_name = "Playback",
                     .channels_min = 2,
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = {
                    .formats = AIC23_FORMATS,},
        .ops = &tlv320aic23_dai_ops,
 };
-EXPORT_SYMBOL_GPL(tlv320aic23_dai);
 
-static int tlv320aic23_suspend(struct platform_device *pdev,
+static int tlv320aic23_suspend(struct snd_soc_codec *codec,
                               pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int tlv320aic23_resume(struct platform_device *pdev)
+static int tlv320aic23_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        u16 reg;
 
        /* Sync reg_cache with the hardware */
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)
        return 0;
 }
 
-/*
- * initialise the AIC23 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int tlv320aic23_init(struct snd_soc_device *socdev)
+static int tlv320aic23_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret = 0;
-       u16 reg;
+       struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
+       int reg;
 
-       codec->name = "tlv320aic23";
-       codec->owner = THIS_MODULE;
-       codec->read = tlv320aic23_read_reg_cache;
-       codec->write = tlv320aic23_write;
-       codec->set_bias_level = tlv320aic23_set_bias_level;
-       codec->dai = &tlv320aic23_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
-       codec->reg_cache =
-           kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
+       codec->control_data = aic23->control_data;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+       codec->hw_read = NULL;
 
        /* Reset codec */
        tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
-               goto pcm_err;
-       }
-
        /* power on device */
        tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
                                ARRAY_SIZE(tlv320aic23_snd_controls));
        tlv320aic23_add_widgets(codec);
 
-       return ret;
+       return 0;
+}
 
-pcm_err:
-       kfree(codec->reg_cache);
-       return ret;
+static int tlv320aic23_remove(struct snd_soc_codec *codec)
+{
+       tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
-static struct snd_soc_device *tlv320aic23_socdev;
+
+static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
+       .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = tlv320aic23_reg,
+       .probe = tlv320aic23_probe,
+       .remove = tlv320aic23_remove,
+       .suspend = tlv320aic23_suspend,
+       .resume = tlv320aic23_resume,
+       .read = tlv320aic23_read_reg_cache,
+       .write = tlv320aic23_write,
+       .set_bias_level = tlv320aic23_set_bias_level,
+};
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev;
 static int tlv320aic23_codec_probe(struct i2c_client *i2c,
                                   const struct i2c_device_id *i2c_id)
 {
-       struct snd_soc_device *socdev = tlv320aic23_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct aic23 *aic23;
        int ret;
 
        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -EINVAL;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
+       if (aic23 == NULL)
+               return -ENOMEM;
 
-       ret = tlv320aic23_init(socdev);
-       if (ret < 0) {
-               printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n");
-               goto err;
-       }
-       return ret;
+       i2c_set_clientdata(i2c, aic23);
+       aic23->control_data = i2c;
+       aic23->control_type = SND_SOC_I2C;
 
-err:
-       kfree(codec);
-       kfree(i2c);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
+       if (ret < 0)
+               kfree(aic23);
        return ret;
 }
 static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
 {
-       put_device(&i2c->dev);
+       snd_soc_unregister_codec(&i2c->dev);
+       kfree(i2c_get_clientdata(i2c));
        return 0;
 }
 
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
 
 static struct i2c_driver tlv320aic23_i2c_driver = {
        .driver = {
-                  .name = "tlv320aic23",
+                  .name = "tlv320aic23-codec",
                   },
        .probe = tlv320aic23_codec_probe,
        .remove = __exit_p(tlv320aic23_i2c_remove),
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
 
 #endif
 
-static int tlv320aic23_probe(struct platform_device *pdev)
+static int __init tlv320aic23_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct aic23 *aic23;
-       int ret = 0;
-
-       printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
-
-       aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
-       if (aic23 == NULL)
-               return -ENOMEM;
-       codec = &aic23->codec;
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       tlv320aic23_socdev = socdev;
+       int ret;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       codec->hw_write = (hw_write_t) i2c_master_send;
-       codec->hw_read = NULL;
        ret = i2c_add_driver(&tlv320aic23_i2c_driver);
-       if (ret != 0)
-               printk(KERN_ERR "can't add i2c driver");
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
+                      ret);
+       }
 #endif
        return ret;
 }
+module_init(tlv320aic23_modinit);
 
-static int tlv320aic23_remove(struct platform_device *pdev)
+static void __exit tlv320aic23_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-       struct aic23 *aic23 = container_of(codec, struct aic23, codec);
-
-       if (codec->control_data)
-               tlv320aic23_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_del_driver(&tlv320aic23_i2c_driver);
 #endif
-       kfree(codec->reg_cache);
-       kfree(aic23);
-
-       return 0;
-}
-struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
-       .probe = tlv320aic23_probe,
-       .remove = tlv320aic23_remove,
-       .suspend = tlv320aic23_suspend,
-       .resume = tlv320aic23_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
-
-static int __init tlv320aic23_modinit(void)
-{
-       return snd_soc_register_dai(&tlv320aic23_dai);
-}
-module_init(tlv320aic23_modinit);
-
-static void __exit tlv320aic23_exit(void)
-{
-       snd_soc_unregister_dai(&tlv320aic23_dai);
 }
 module_exit(tlv320aic23_exit);
 
index 79d1faf..e804120 100644 (file)
 #define TLV320AIC23_SIDETONE_12                0x080
 #define TLV320AIC23_SIDETONE_18                0x0c0
 
-extern struct snd_soc_dai tlv320aic23_dai;
-extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
-
 #endif /* _TLV320AIC23_H */
index f0e00fd..6b7d71e 100644 (file)
@@ -19,7 +19,6 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
-#include <sound/soc-of-simple.h>
 #include <sound/initval.h>
 
 #include "tlv320aic26.h"
@@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
        struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
        int fsref, divisor, wlen, pval, jval, dval, qval;
        u16 reg;
@@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = {
        .set_fmt        = aic26_set_fmt,
 };
 
-struct snd_soc_dai aic26_dai = {
-       .name = "tlv320aic26",
+static struct snd_soc_dai_driver aic26_dai = {
+       .name = "tlv320aic26-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = {
        },
        .ops = &aic26_dai_ops,
 };
-EXPORT_SYMBOL_GPL(aic26_dai);
 
 /* ---------------------------------------------------------------------
  * ALSA controls
@@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = {
 };
 
 /* ---------------------------------------------------------------------
- * SoC CODEC portion of driver: probe and release routines
- */
-static int aic26_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct aic26 *aic26;
-       int ret, err;
-
-       dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
-       dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
-       dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data);
-
-       /* Fetch the relevant aic26 private data here (it's already been
-        * stored in the .codec pointer) */
-       aic26 = socdev->codec_data;
-       if (aic26 == NULL) {
-               dev_err(&pdev->dev, "aic26: missing codec pointer\n");
-               return -ENODEV;
-       }
-       codec = &aic26->codec;
-       socdev->card->codec = codec;
-
-       dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
-               &pdev->dev, socdev->dev);
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "aic26: failed to create pcms\n");
-               return -ENODEV;
-       }
-
-       /* register controls */
-       dev_dbg(&pdev->dev, "Registering controls\n");
-       err = snd_soc_add_controls(codec, aic26_snd_controls,
-                       ARRAY_SIZE(aic26_snd_controls));
-       WARN_ON(err < 0);
-
-       return 0;
-}
-
-static int aic26_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       snd_soc_free_pcms(socdev);
-       return 0;
-}
-
-struct snd_soc_codec_device aic26_soc_codec_dev = {
-       .probe = aic26_probe,
-       .remove = aic26_remove,
-};
-EXPORT_SYMBOL_GPL(aic26_soc_codec_dev);
-
-/* ---------------------------------------------------------------------
  * SPI device portion of driver: sysfs files for debugging
  */
 
@@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev,
 static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
 
 /* ---------------------------------------------------------------------
- * SPI device portion of driver: probe and release routines and SPI
- *                              driver registration.
+ * SoC CODEC portion of driver: probe and release routines
  */
-static int aic26_spi_probe(struct spi_device *spi)
+static int aic26_probe(struct snd_soc_codec *codec)
 {
-       struct aic26 *aic26;
-       int ret, i, reg;
-
-       dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
-
-       /* Allocate driver data */
-       aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
-       if (!aic26)
-               return -ENOMEM;
-
-       /* Initialize the driver data */
-       aic26->spi = spi;
-       dev_set_drvdata(&spi->dev, aic26);
+       struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
+       int ret, err, i, reg;
 
-       /* Setup what we can in the codec structure so that the register
-        * access functions will work as expected.  More will be filled
-        * out when it is probed by the SoC CODEC part of this driver */
-       snd_soc_codec_set_drvdata(&aic26->codec, aic26);
-       aic26->codec.name = "aic26";
-       aic26->codec.owner = THIS_MODULE;
-       aic26->codec.dai = &aic26_dai;
-       aic26->codec.num_dai = 1;
-       aic26->codec.read = aic26_reg_read;
-       aic26->codec.write = aic26_reg_write;
-       aic26->master = 1;
-       mutex_init(&aic26->codec.mutex);
-       INIT_LIST_HEAD(&aic26->codec.dapm_widgets);
-       INIT_LIST_HEAD(&aic26->codec.dapm_paths);
-       aic26->codec.reg_cache_size = AIC26_NUM_REGS;
-       aic26->codec.reg_cache = aic26->reg_cache;
-
-       aic26_dai.dev = &spi->dev;
-       ret = snd_soc_register_dai(&aic26_dai);
-       if (ret != 0) {
-               dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
-               kfree(aic26);
-               return ret;
-       }
+       dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
 
        /* Reset the codec to power on defaults */
-       aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
+       aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00);
 
        /* Power up CODEC */
-       aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0);
+       aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);
 
        /* Audio Control 3 (master mode, fsref rate) */
-       reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3);
+       reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3);
        reg &= ~0xf800;
        reg |= 0x0800; /* set master mode */
-       aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg);
+       aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
 
        /* Fill register cache */
        for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
-               aic26_reg_read(&aic26->codec, i);
+               aic26_reg_read(codec, i);
 
        /* Register the sysfs files for debugging */
        /* Create SysFS files */
-       ret = device_create_file(&spi->dev, &dev_attr_keyclick);
+       ret = device_create_file(codec->dev, &dev_attr_keyclick);
        if (ret)
-               dev_info(&spi->dev, "error creating sysfs files\n");
+               dev_info(codec->dev, "error creating sysfs files\n");
 
-#if defined(CONFIG_SND_SOC_OF_SIMPLE)
-       /* Tell the of_soc helper about this codec */
-       of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai,
-                                 spi->dev.archdata.of_node);
-#endif
+       /* register controls */
+       dev_dbg(codec->dev, "Registering controls\n");
+       err = snd_soc_add_controls(codec, aic26_snd_controls,
+                       ARRAY_SIZE(aic26_snd_controls));
+       WARN_ON(err < 0);
 
-       dev_dbg(&spi->dev, "SPI device initialized\n");
        return 0;
 }
 
-static int aic26_spi_remove(struct spi_device *spi)
+static struct snd_soc_codec_driver aic26_soc_codec_dev = {
+       .probe = aic26_probe,
+       .read = aic26_reg_read,
+       .write = aic26_reg_write,
+       .reg_cache_size = AIC26_NUM_REGS,
+       .reg_word_size = sizeof(u16),
+};
+
+/* ---------------------------------------------------------------------
+ * SPI device portion of driver: probe and release routines and SPI
+ *                              driver registration.
+ */
+static int aic26_spi_probe(struct spi_device *spi)
 {
-       struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
+       struct aic26 *aic26;
+       int ret;
 
-       snd_soc_unregister_dai(&aic26_dai);
-       kfree(aic26);
+       dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
+
+       /* Allocate driver data */
+       aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
+       if (!aic26)
+               return -ENOMEM;
 
+       /* Initialize the driver data */
+       aic26->spi = spi;
+       dev_set_drvdata(&spi->dev, aic26);
+       aic26->master = 1;
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &aic26_soc_codec_dev, &aic26_dai, 1);
+       if (ret < 0)
+               kfree(aic26);
+       return ret;
+
+       dev_dbg(&spi->dev, "SPI device initialized\n");
+       return 0;
+}
+
+static int aic26_spi_remove(struct spi_device *spi)
+{
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
 static struct spi_driver aic26_spi = {
        .driver = {
-               .name = "tlv320aic26",
+               .name = "tlv320aic26-codec",
                .owner = THIS_MODULE,
        },
        .probe = aic26_spi_probe,
index 786ba16..62b1f22 100644 (file)
@@ -90,7 +90,4 @@ enum aic26_wlen {
        AIC26_WLEN_32   = 3 << 10,
 };
 
-extern struct snd_soc_dai aic26_dai;
-extern struct snd_soc_codec_device aic26_soc_codec_dev;
-
 #endif /* _TLV320AIC16_H_ */
index 71a6990..fc68779 100644 (file)
  *
  * Notes:
  *  The AIC3X is a driver for a low power stereo audio
- *  codecs aic31, aic32, aic33.
+ *  codecs aic31, aic32, aic33, aic3007.
  *
  *  It supports full aic33 codec functionality.
- *  The compatibility with aic32, aic31 is as follows:
- *        aic32        |        aic31
+ *  The compatibility with aic32, aic31 and aic3007 is as follows:
+ *    aic32/aic3007    |        aic31
  *  ---------------------------------------
  *   MONO_LOUT -> N/A  |  MONO_LOUT -> N/A
  *                     |  IN1L -> LINE1L
@@ -61,13 +61,29 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
        "DRVDD",        /* ADC Analog and Output Driver Voltage */
 };
 
+struct aic3x_priv;
+
+struct aic3x_disable_nb {
+       struct notifier_block nb;
+       struct aic3x_priv *aic3x;
+};
+
 /* codec private data */
 struct aic3x_priv {
-       struct snd_soc_codec codec;
+       struct snd_soc_codec *codec;
        struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
+       struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
+       enum snd_soc_control_type control_type;
+       struct aic3x_setup_data *setup;
+       void *control_data;
        unsigned int sysclk;
        int master;
        int gpio_reset;
+       int power;
+#define AIC3X_MODEL_3X 0
+#define AIC3X_MODEL_33 1
+#define AIC3X_MODEL_3007 2
+       u16 model;
 };
 
 /*
@@ -106,62 +122,23 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
 };
 
 /*
- * read aic3x register cache
+ * read from the aic3x register space. Only use for this function is if
+ * wanting to read volatile bits from those registers that has both read-only
+ * and read/write bits. All other cases should use snd_soc_read.
  */
-static inline unsigned int aic3x_read_reg_cache(struct snd_soc_codec *codec,
-                                               unsigned int reg)
+static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
+                     u8 *value)
 {
        u8 *cache = codec->reg_cache;
-       if (reg >= AIC3X_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
 
-/*
- * write aic3x register cache
- */
-static inline void aic3x_write_reg_cache(struct snd_soc_codec *codec,
-                                        u8 reg, u8 value)
-{
-       u8 *cache = codec->reg_cache;
+       if (codec->cache_only)
+               return -EINVAL;
        if (reg >= AIC3X_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-/*
- * write to the aic3x register space
- */
-static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
-                      unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D8 aic3x register offset
-        *   D7...D0 register data
-        */
-       data[0] = reg & 0xff;
-       data[1] = value & 0xff;
-
-       aic3x_write_reg_cache(codec, data[0], data[1]);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-/*
- * read from the aic3x register space
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
-                     u8 *value)
-{
-       *value = reg & 0xff;
+               return -1;
 
-       value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
+       *value = codec->hw_read(codec, reg);
+       cache[reg] = *value;
 
-       aic3x_write_reg_cache(codec, reg, *value);
        return 0;
 }
 
@@ -286,64 +263,102 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        SOC_DOUBLE_R_TLV("PCM Playback Volume",
                         LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv),
 
+       /*
+        * Output controls that map to output mixer switches. Note these are
+        * only for swapped L-to-R and R-to-L routes. See below stereo controls
+        * for direct L-to-L and R-to-R routes.
+        */
+       SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume",
+                      LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume",
+                      PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume",
+                      DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume",
+                      LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume",
+                      PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume",
+                      DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume",
+                      LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume",
+                      PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume",
+                      DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume",
+                      LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume",
+                      PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume",
+                      DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume",
+                      LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume",
+                      PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume",
+                      DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
+
+       SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume",
+                      LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume",
+                      PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+       SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume",
+                      DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
+
+       /* Stereo output controls for direct L-to-L and R-to-R routes */
+       SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume",
+                        LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
+       SOC_DOUBLE_R_TLV("Line PGA Bypass Volume",
+                        PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL,
+                        0, 118, 1, output_stage_tlv),
        SOC_DOUBLE_R_TLV("Line DAC Playback Volume",
                         DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
-       SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
-       SOC_DOUBLE_R_TLV("LineL DAC Playback Volume",
-                        DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL,
-                        0, 118, 1, output_stage_tlv),
-       SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume",
-                      PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume",
-                      PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume",
-                        LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL,
+
+       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
+                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume",
-                        LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL,
+       SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
+                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
-
        SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
                         DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
-       SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume",
-                        PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
+
+       SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
+                        LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume",
-                        LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
+       SOC_DOUBLE_R_TLV("HP PGA Bypass Volume",
+                        PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
                         0, 118, 1, output_stage_tlv),
-
        SOC_DOUBLE_R_TLV("HP DAC Playback Volume",
                         DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
-                    0x01, 0),
-       SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume",
-                        PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
+
+       SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume",
+                        LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume",
-                      PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume",
-                      PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume",
-                        LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
+       SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume",
+                        PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL,
                         0, 118, 1, output_stage_tlv),
-
        SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume",
                         DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL,
                         0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
+
+       /* Output pin mute controls */
+       SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
+                    0x01, 0),
+       SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
+       SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
+                    0x01, 0),
+       SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
                     0x01, 0),
-       SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume",
-                      PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume",
-                      PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
-       SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume",
-                        LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
-                        0, 118, 1, output_stage_tlv),
 
        /*
         * Note: enable Automatic input Gain Controller with care. It can
@@ -359,6 +374,14 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
        SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
 };
 
+/*
+ * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
+ */
+static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
+
+static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
+       SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
+
 /* Left DAC Mux */
 static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
 SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -375,22 +398,74 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]);
 static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls =
 SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
 
-/* Left DAC_L1 Mixer */
-static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
+/* Left Line Mixer */
+static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
+};
+
+/* Right Line Mixer */
+static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
+};
+
+/* Left HP Mixer */
+static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0),
+};
+
+/* Right HP Mixer */
+static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
+};
+
+/* Left HPCOM Mixer */
+static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0),
 };
 
-/* Right DAC_R1 Mixer */
-static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
+/* Right HPCOM Mixer */
+static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = {
+       SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
+       SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
 };
 
 /* Left PGA Mixer */
@@ -427,54 +502,11 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]);
 static const struct snd_kcontrol_new aic3x_right_line2_mux_controls =
 SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
 
-/* Left PGA Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
-};
-
-/* Right PGA Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
-};
-
-/* Left Line2 Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
-};
-
-/* Right Line2 Bypass Mixer */
-static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
-       SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
-       SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
-};
-
 static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        /* Left DAC to Left Outputs */
        SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0),
        SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0,
                         &aic3x_left_dac_mux_controls),
-       SND_SOC_DAPM_MIXER("Left DAC_L1 Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_left_dac_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_left_dac_mixer_controls)),
        SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0,
                         &aic3x_left_hpcom_mux_controls),
        SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0),
@@ -485,9 +517,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0),
        SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0,
                         &aic3x_right_dac_mux_controls),
-       SND_SOC_DAPM_MIXER("Right DAC_R1 Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_right_dac_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_right_dac_mixer_controls)),
        SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0,
                         &aic3x_right_hpcom_mux_controls),
        SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0),
@@ -551,25 +580,28 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
                         MICBIAS_CTRL, 6, 3, 3, 0),
 
-       /* Left PGA to Left Output bypass */
-       SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_left_pga_bp_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_left_pga_bp_mixer_controls)),
-
-       /* Right PGA to Right Output bypass */
-       SND_SOC_DAPM_MIXER("Right PGA Bypass Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_right_pga_bp_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_right_pga_bp_mixer_controls)),
-
-       /* Left Line2 to Left Output bypass */
-       SND_SOC_DAPM_MIXER("Left Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_left_line2_bp_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_left_line2_bp_mixer_controls)),
-
-       /* Right Line2 to Right Output bypass */
-       SND_SOC_DAPM_MIXER("Right Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0,
-                          &aic3x_right_line2_bp_mixer_controls[0],
-                          ARRAY_SIZE(aic3x_right_line2_bp_mixer_controls)),
+       /* Output mixers */
+       SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_left_line_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_left_line_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_right_line_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_right_line_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_mono_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_mono_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_left_hp_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_left_hp_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_right_hp_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_right_hp_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_left_hpcom_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)),
+       SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0,
+                          &aic3x_right_hpcom_mixer_controls[0],
+                          ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)),
 
        SND_SOC_DAPM_OUTPUT("LLOUT"),
        SND_SOC_DAPM_OUTPUT("RLOUT"),
@@ -585,69 +617,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("LINE1R"),
        SND_SOC_DAPM_INPUT("LINE2L"),
        SND_SOC_DAPM_INPUT("LINE2R"),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-       /* Left Output */
-       {"Left DAC Mux", "DAC_L1", "Left DAC"},
-       {"Left DAC Mux", "DAC_L2", "Left DAC"},
-       {"Left DAC Mux", "DAC_L3", "Left DAC"},
-
-       {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
-       {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
-       {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
-       {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
-       {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
-       {"Left Line Out", NULL, "Left DAC Mux"},
-       {"Left HP Out", NULL, "Left DAC Mux"},
-
-       {"Left HPCOM Mux", "differential of HPLOUT", "Left DAC_L1 Mixer"},
-       {"Left HPCOM Mux", "constant VCM", "Left DAC_L1 Mixer"},
-       {"Left HPCOM Mux", "single-ended", "Left DAC_L1 Mixer"},
-
-       {"Left Line Out", NULL, "Left DAC_L1 Mixer"},
-       {"Mono Out", NULL, "Left DAC_L1 Mixer"},
-       {"Left HP Out", NULL, "Left DAC_L1 Mixer"},
-       {"Left HP Com", NULL, "Left HPCOM Mux"},
-
-       {"LLOUT", NULL, "Left Line Out"},
-       {"LLOUT", NULL, "Left Line Out"},
-       {"HPLOUT", NULL, "Left HP Out"},
-       {"HPLCOM", NULL, "Left HP Com"},
-
-       /* Right Output */
-       {"Right DAC Mux", "DAC_R1", "Right DAC"},
-       {"Right DAC Mux", "DAC_R2", "Right DAC"},
-       {"Right DAC Mux", "DAC_R3", "Right DAC"},
 
-       {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
-       {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
-       {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
-       {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
-       {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
-       {"Right Line Out", NULL, "Right DAC Mux"},
-       {"Right HP Out", NULL, "Right DAC Mux"},
+       /*
+        * Virtual output pin to detection block inside codec. This can be
+        * used to keep codec bias on if gpio or detection features are needed.
+        * Force pin on or construct a path with an input jack and mic bias
+        * widgets.
+        */
+       SND_SOC_DAPM_OUTPUT("Detection"),
+};
 
-       {"Right HPCOM Mux", "differential of HPROUT", "Right DAC_R1 Mixer"},
-       {"Right HPCOM Mux", "constant VCM", "Right DAC_R1 Mixer"},
-       {"Right HPCOM Mux", "single-ended", "Right DAC_R1 Mixer"},
-       {"Right HPCOM Mux", "differential of HPLCOM", "Right DAC_R1 Mixer"},
-       {"Right HPCOM Mux", "external feedback", "Right DAC_R1 Mixer"},
+static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
+       /* Class-D outputs */
+       SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0),
 
-       {"Right Line Out", NULL, "Right DAC_R1 Mixer"},
-       {"Mono Out", NULL, "Right DAC_R1 Mixer"},
-       {"Right HP Out", NULL, "Right DAC_R1 Mixer"},
-       {"Right HP Com", NULL, "Right HPCOM Mux"},
-
-       {"RLOUT", NULL, "Right Line Out"},
-       {"RLOUT", NULL, "Right Line Out"},
-       {"HPROUT", NULL, "Right HP Out"},
-       {"HPRCOM", NULL, "Right HP Com"},
-
-       /* Mono Output */
-       {"MONO_LOUT", NULL, "Mono Out"},
-       {"MONO_LOUT", NULL, "Mono Out"},
+       SND_SOC_DAPM_OUTPUT("SPOP"),
+       SND_SOC_DAPM_OUTPUT("SPOM"),
+};
 
+static const struct snd_soc_dapm_route intercon[] = {
        /* Left Input */
        {"Left Line1L Mux", "single-ended", "LINE1L"},
        {"Left Line1L Mux", "differential", "LINE1L"},
@@ -680,74 +669,6 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"Right ADC", NULL, "Right PGA Mixer"},
        {"Right ADC", NULL, "GPIO1 dmic modclk"},
 
-       /* Left PGA Bypass */
-       {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
-       {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
-
-       {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
-       {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
-       {"Left HPCOM Mux", "single-ended", "Left PGA Bypass Mixer"},
-
-       {"Left Line Out", NULL, "Left PGA Bypass Mixer"},
-       {"Mono Out", NULL, "Left PGA Bypass Mixer"},
-       {"Left HP Out", NULL, "Left PGA Bypass Mixer"},
-
-       /* Right PGA Bypass */
-       {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
-       {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
-
-       {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
-       {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
-       {"Right HPCOM Mux", "single-ended", "Right PGA Bypass Mixer"},
-       {"Right HPCOM Mux", "differential of HPLCOM", "Right PGA Bypass Mixer"},
-       {"Right HPCOM Mux", "external feedback", "Right PGA Bypass Mixer"},
-
-       {"Right Line Out", NULL, "Right PGA Bypass Mixer"},
-       {"Mono Out", NULL, "Right PGA Bypass Mixer"},
-       {"Right HP Out", NULL, "Right PGA Bypass Mixer"},
-
-       /* Left Line2 Bypass */
-       {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
-       {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
-       {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
-       {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
-       {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
-
-       {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
-       {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
-       {"Left HPCOM Mux", "single-ended", "Left Line2 Bypass Mixer"},
-
-       {"Left Line Out", NULL, "Left Line2 Bypass Mixer"},
-       {"Mono Out", NULL, "Left Line2 Bypass Mixer"},
-       {"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
-
-       /* Right Line2 Bypass */
-       {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
-       {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
-       {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
-       {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
-       {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
-
-       {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
-       {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
-       {"Right HPCOM Mux", "single-ended", "Right Line2 Bypass Mixer"},
-       {"Right HPCOM Mux", "differential of HPLCOM", "Right Line2 Bypass Mixer"},
-       {"Right HPCOM Mux", "external feedback", "Right Line2 Bypass Mixer"},
-
-       {"Right Line Out", NULL, "Right Line2 Bypass Mixer"},
-       {"Mono Out", NULL, "Right Line2 Bypass Mixer"},
-       {"Right HP Out", NULL, "Right Line2 Bypass Mixer"},
-
        /*
         * Logical path between digital mic enable and GPIO1 modulator clock
         * output function
@@ -755,16 +676,131 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
        {"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
        {"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
+
+       /* Left DAC Output */
+       {"Left DAC Mux", "DAC_L1", "Left DAC"},
+       {"Left DAC Mux", "DAC_L2", "Left DAC"},
+       {"Left DAC Mux", "DAC_L3", "Left DAC"},
+
+       /* Right DAC Output */
+       {"Right DAC Mux", "DAC_R1", "Right DAC"},
+       {"Right DAC Mux", "DAC_R2", "Right DAC"},
+       {"Right DAC Mux", "DAC_R3", "Right DAC"},
+
+       /* Left Line Output */
+       {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Left Line Out", NULL, "Left Line Mixer"},
+       {"Left Line Out", NULL, "Left DAC Mux"},
+       {"LLOUT", NULL, "Left Line Out"},
+
+       /* Right Line Output */
+       {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Right Line Out", NULL, "Right Line Mixer"},
+       {"Right Line Out", NULL, "Right DAC Mux"},
+       {"RLOUT", NULL, "Right Line Out"},
+
+       /* Mono Output */
+       {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Mono Out", NULL, "Mono Mixer"},
+       {"MONO_LOUT", NULL, "Mono Out"},
+
+       /* Left HP Output */
+       {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Left HP Out", NULL, "Left HP Mixer"},
+       {"Left HP Out", NULL, "Left DAC Mux"},
+       {"HPLOUT", NULL, "Left HP Out"},
+
+       /* Right HP Output */
+       {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Right HP Out", NULL, "Right HP Mixer"},
+       {"Right HP Out", NULL, "Right DAC Mux"},
+       {"HPROUT", NULL, "Right HP Out"},
+
+       /* Left HPCOM Output */
+       {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Left HPCOM Mux", "differential of HPLOUT", "Left HP Mixer"},
+       {"Left HPCOM Mux", "constant VCM", "Left HPCOM Mixer"},
+       {"Left HPCOM Mux", "single-ended", "Left HPCOM Mixer"},
+       {"Left HP Com", NULL, "Left HPCOM Mux"},
+       {"HPLCOM", NULL, "Left HP Com"},
+
+       /* Right HPCOM Output */
+       {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
+       {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
+       {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
+       {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
+       {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
+       {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
+
+       {"Right HPCOM Mux", "differential of HPROUT", "Right HP Mixer"},
+       {"Right HPCOM Mux", "constant VCM", "Right HPCOM Mixer"},
+       {"Right HPCOM Mux", "single-ended", "Right HPCOM Mixer"},
+       {"Right HPCOM Mux", "differential of HPLCOM", "Left HPCOM Mixer"},
+       {"Right HPCOM Mux", "external feedback", "Right HPCOM Mixer"},
+       {"Right HP Com", NULL, "Right HPCOM Mux"},
+       {"HPRCOM", NULL, "Right HP Com"},
+};
+
+static const struct snd_soc_dapm_route intercon_3007[] = {
+       /* Class-D outputs */
+       {"Left Class-D Out", NULL, "Left Line Out"},
+       {"Right Class-D Out", NULL, "Left Line Out"},
+       {"SPOP", NULL, "Left Class-D Out"},
+       {"SPOM", NULL, "Right Class-D Out"},
 };
 
 static int aic3x_add_widgets(struct snd_soc_codec *codec)
 {
+       struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+
        snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
                                  ARRAY_SIZE(aic3x_dapm_widgets));
 
        /* set up audio path interconnects */
        snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
 
+       if (aic3x->model == AIC3X_MODEL_3007) {
+               snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets,
+                       ARRAY_SIZE(aic3007_dapm_widgets));
+               snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007));
+       }
+
        return 0;
 }
 
@@ -773,8 +809,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec =rtd->codec;
        struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
        int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
        u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
@@ -783,8 +818,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        int clk;
 
        /* select data word length */
-       data =
-           aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
+       data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                break;
@@ -798,7 +832,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
                data |= (0x03 << 4);
                break;
        }
-       aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data);
+       snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, data);
 
        /* Fsref can be 44100 or 48000 */
        fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
@@ -813,17 +847,17 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
 
        if (bypass_pll) {
                pll_q &= 0xf;
-               aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
-               aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
+               snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
+               snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
                /* disable PLL if it is bypassed */
-               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
-               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+               reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+               snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
 
        } else {
-               aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
+               snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
                /* enable PLL when it is used */
-               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
-               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+               reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+               snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
        }
 
        /* Route Left DAC to left channel input and
@@ -832,7 +866,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
        if (params_rate(params) >= 64000)
                data |= DUAL_RATE_MODE;
-       aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
+       snd_soc_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
 
        /* codec sample rate select */
        data = (fsref * 20) / params_rate(params);
@@ -841,7 +875,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        data /= 5;
        data -= 2;
        data |= (data << 4);
-       aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
+       snd_soc_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
 
        if (bypass_pll)
                return 0;
@@ -910,13 +944,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        }
 
 found:
-       data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
-       aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT));
-       aic3x_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT);
-       aic3x_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
-       aic3x_write(codec, AIC3X_PLL_PROGC_REG, (pll_d >> 6) << PLLD_MSB_SHIFT);
-       aic3x_write(codec, AIC3X_PLL_PROGD_REG,
-                   (pll_d & 0x3F) << PLLD_LSB_SHIFT);
+       data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+       snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+                     data | (pll_p << PLLP_SHIFT));
+       snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG,
+                     pll_r << PLLR_SHIFT);
+       snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
+       snd_soc_write(codec, AIC3X_PLL_PROGC_REG,
+                     (pll_d >> 6) << PLLD_MSB_SHIFT);
+       snd_soc_write(codec, AIC3X_PLL_PROGD_REG,
+                     (pll_d & 0x3F) << PLLD_LSB_SHIFT);
 
        return 0;
 }
@@ -924,15 +961,15 @@ found:
 static int aic3x_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON;
-       u8 rdac_reg = aic3x_read_reg_cache(codec, RDAC_VOL) & ~MUTE_ON;
+       u8 ldac_reg = snd_soc_read(codec, LDAC_VOL) & ~MUTE_ON;
+       u8 rdac_reg = snd_soc_read(codec, RDAC_VOL) & ~MUTE_ON;
 
        if (mute) {
-               aic3x_write(codec, LDAC_VOL, ldac_reg | MUTE_ON);
-               aic3x_write(codec, RDAC_VOL, rdac_reg | MUTE_ON);
+               snd_soc_write(codec, LDAC_VOL, ldac_reg | MUTE_ON);
+               snd_soc_write(codec, RDAC_VOL, rdac_reg | MUTE_ON);
        } else {
-               aic3x_write(codec, LDAC_VOL, ldac_reg);
-               aic3x_write(codec, RDAC_VOL, rdac_reg);
+               snd_soc_write(codec, LDAC_VOL, ldac_reg);
+               snd_soc_write(codec, RDAC_VOL, rdac_reg);
        }
 
        return 0;
@@ -956,8 +993,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
        u8 iface_areg, iface_breg;
        int delay = 0;
 
-       iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
-       iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
+       iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
+       iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -996,13 +1033,98 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
        }
 
        /* set iface */
-       aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
-       aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
-       aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
+       snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
+       snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
+       snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
+
+       return 0;
+}
+
+static int aic3x_init_3007(struct snd_soc_codec *codec)
+{
+       u8 tmp1, tmp2, *cache = codec->reg_cache;
+
+       /*
+        * There is no need to cache writes to undocumented page 0xD but
+        * respective page 0 register cache entries must be preserved
+        */
+       tmp1 = cache[0xD];
+       tmp2 = cache[0x8];
+       /* Class-D speaker driver init; datasheet p. 46 */
+       snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
+       snd_soc_write(codec, 0xD, 0x0D);
+       snd_soc_write(codec, 0x8, 0x5C);
+       snd_soc_write(codec, 0x8, 0x5D);
+       snd_soc_write(codec, 0x8, 0x5C);
+       snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
+       cache[0xD] = tmp1;
+       cache[0x8] = tmp2;
 
        return 0;
 }
 
+static int aic3x_regulator_event(struct notifier_block *nb,
+                                unsigned long event, void *data)
+{
+       struct aic3x_disable_nb *disable_nb =
+               container_of(nb, struct aic3x_disable_nb, nb);
+       struct aic3x_priv *aic3x = disable_nb->aic3x;
+
+       if (event & REGULATOR_EVENT_DISABLE) {
+               /*
+                * Put codec to reset and require cache sync as at least one
+                * of the supplies was disabled
+                */
+               if (aic3x->gpio_reset >= 0)
+                       gpio_set_value(aic3x->gpio_reset, 0);
+               aic3x->codec->cache_sync = 1;
+       }
+
+       return 0;
+}
+
+static int aic3x_set_power(struct snd_soc_codec *codec, int power)
+{
+       struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+       int i, ret;
+       u8 *cache = codec->reg_cache;
+
+       if (power) {
+               ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
+                                           aic3x->supplies);
+               if (ret)
+                       goto out;
+               aic3x->power = 1;
+               /*
+                * Reset release and cache sync is necessary only if some
+                * supply was off or if there were cached writes
+                */
+               if (!codec->cache_sync)
+                       goto out;
+
+               if (aic3x->gpio_reset >= 0) {
+                       udelay(1);
+                       gpio_set_value(aic3x->gpio_reset, 1);
+               }
+
+               /* Sync reg_cache with the hardware */
+               codec->cache_only = 0;
+               for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++)
+                       snd_soc_write(codec, i, cache[i]);
+               if (aic3x->model == AIC3X_MODEL_3007)
+                       aic3x_init_3007(codec);
+               codec->cache_sync = 0;
+       } else {
+               aic3x->power = 0;
+               /* HW writes are needless when bias is off */
+               codec->cache_only = 1;
+               ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
+                                            aic3x->supplies);
+       }
+out:
+       return ret;
+}
+
 static int aic3x_set_bias_level(struct snd_soc_codec *codec,
                                enum snd_soc_bias_level level)
 {
@@ -1013,23 +1135,29 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_ON:
                break;
        case SND_SOC_BIAS_PREPARE:
-               if (aic3x->master) {
+               if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
+                   aic3x->master) {
                        /* enable pll */
-                       reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
-                       aic3x_write(codec, AIC3X_PLL_PROGA_REG,
-                                   reg | PLL_ENABLE);
+                       reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+                       snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+                                     reg | PLL_ENABLE);
                }
                break;
        case SND_SOC_BIAS_STANDBY:
-               /* fall through and disable pll */
-       case SND_SOC_BIAS_OFF:
-               if (aic3x->master) {
+               if (!aic3x->power)
+                       aic3x_set_power(codec, 1);
+               if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
+                   aic3x->master) {
                        /* disable pll */
-                       reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
-                       aic3x_write(codec, AIC3X_PLL_PROGA_REG,
-                                   reg & ~PLL_ENABLE);
+                       reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
+                       snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
+                                     reg & ~PLL_ENABLE);
                }
                break;
+       case SND_SOC_BIAS_OFF:
+               if (aic3x->power)
+                       aic3x_set_power(codec, 0);
+               break;
        }
        codec->bias_level = level;
 
@@ -1040,8 +1168,8 @@ void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
 {
        u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
        u8 bit = gpio ? 3: 0;
-       u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit);
-       aic3x_write(codec, reg, val | (!!state << bit));
+       u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
+       snd_soc_write(codec, reg, val | (!!state << bit));
 }
 EXPORT_SYMBOL_GPL(aic3x_set_gpio);
 
@@ -1070,7 +1198,7 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
        if (detect & AIC3X_HEADSET_DETECT_MASK)
                val |= AIC3X_HEADSET_DETECT_ENABLED;
 
-       aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
+       snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
 }
 EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
 
@@ -1101,8 +1229,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = {
        .set_fmt        = aic3x_set_dai_fmt,
 };
 
-struct snd_soc_dai aic3x_dai = {
-       .name = "tlv320aic3x",
+static struct snd_soc_dai_driver aic3x_dai = {
+       .name = "tlv320aic3x-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1116,34 +1244,18 @@ struct snd_soc_dai aic3x_dai = {
                .rates = AIC3X_RATES,
                .formats = AIC3X_FORMATS,},
        .ops = &aic3x_dai_ops,
+       .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(aic3x_dai);
 
-static int aic3x_suspend(struct platform_device *pdev, pm_message_t state)
+static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int aic3x_resume(struct platform_device *pdev)
+static int aic3x_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int i;
-       u8 data[2];
-       u8 *cache = codec->reg_cache;
-
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
-               data[0] = i;
-               data[1] = cache[i];
-               codec->hw_write(codec->control_data, data, 2);
-       }
-
        aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -1155,152 +1267,203 @@ static int aic3x_resume(struct platform_device *pdev)
  */
 static int aic3x_init(struct snd_soc_codec *codec)
 {
+       struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
        int reg;
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "tlv320aic3x";
-       codec->owner = THIS_MODULE;
-       codec->read = aic3x_read_reg_cache;
-       codec->write = aic3x_write;
-       codec->set_bias_level = aic3x_set_bias_level;
-       codec->dai = &aic3x_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(aic3x_reg);
-       codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
-
-       aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
-       aic3x_write(codec, AIC3X_RESET, SOFT_RESET);
+       snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
+       snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
 
        /* DAC default volume and mute */
-       aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
-       aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
+       snd_soc_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
+       snd_soc_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
 
        /* DAC to HP default volume and route to Output mixer */
-       aic3x_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON);
-       aic3x_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON);
-       aic3x_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON);
-       aic3x_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON);
        /* DAC to Line Out default volume and route to Output mixer */
-       aic3x_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       aic3x_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
        /* DAC to Mono Line Out default volume and route to Output mixer */
-       aic3x_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
-       aic3x_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
+       snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
 
        /* unmute all outputs */
-       reg = aic3x_read_reg_cache(codec, LLOPM_CTRL);
-       aic3x_write(codec, LLOPM_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, RLOPM_CTRL);
-       aic3x_write(codec, RLOPM_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL);
-       aic3x_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL);
-       aic3x_write(codec, HPLOUT_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, HPROUT_CTRL);
-       aic3x_write(codec, HPROUT_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL);
-       aic3x_write(codec, HPLCOM_CTRL, reg | UNMUTE);
-       reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL);
-       aic3x_write(codec, HPRCOM_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, LLOPM_CTRL);
+       snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, RLOPM_CTRL);
+       snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, MONOLOPM_CTRL);
+       snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, HPLOUT_CTRL);
+       snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, HPROUT_CTRL);
+       snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, HPLCOM_CTRL);
+       snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
+       reg = snd_soc_read(codec, HPRCOM_CTRL);
+       snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
 
        /* ADC default volume and unmute */
-       aic3x_write(codec, LADC_VOL, DEFAULT_GAIN);
-       aic3x_write(codec, RADC_VOL, DEFAULT_GAIN);
+       snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
+       snd_soc_write(codec, RADC_VOL, DEFAULT_GAIN);
        /* By default route Line1 to ADC PGA mixer */
-       aic3x_write(codec, LINE1L_2_LADC_CTRL, 0x0);
-       aic3x_write(codec, LINE1R_2_RADC_CTRL, 0x0);
+       snd_soc_write(codec, LINE1L_2_LADC_CTRL, 0x0);
+       snd_soc_write(codec, LINE1R_2_RADC_CTRL, 0x0);
 
        /* PGA to HP Bypass default volume, disconnect from Output Mixer */
-       aic3x_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL);
-       aic3x_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL);
-       aic3x_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL);
        /* PGA to Line Out default volume, disconnect from Output Mixer */
-       aic3x_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
        /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
-       aic3x_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
 
        /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
-       aic3x_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
-       aic3x_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
-       aic3x_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
        /* Line2 Line Out default volume, disconnect from Output Mixer */
-       aic3x_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
        /* Line2 to Mono Out default volume, disconnect from Output Mixer */
-       aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
-       aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
+       snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
 
-       /* off, with power on */
-       aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       if (aic3x->model == AIC3X_MODEL_3007) {
+               aic3x_init_3007(codec);
+               snd_soc_write(codec, CLASSD_CTRL, 0);
+       }
 
        return 0;
 }
 
-static struct snd_soc_codec *aic3x_codec;
-
-static int aic3x_register(struct snd_soc_codec *codec)
+static int aic3x_probe(struct snd_soc_codec *codec)
 {
-       int ret;
+       struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+       int ret, i;
 
-       ret = aic3x_init(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to initialise device\n");
+       codec->control_data = aic3x->control_data;
+       aic3x->codec = codec;
+       codec->idle_bias_off = 1;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       aic3x_codec = codec;
+       if (aic3x->gpio_reset >= 0) {
+               ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
+               if (ret != 0)
+                       goto err_gpio;
+               gpio_direction_output(aic3x->gpio_reset, 0);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+               aic3x->supplies[i].supply = aic3x_supply_names[i];
 
-       ret = snd_soc_register_codec(codec);
-       if (ret) {
-               dev_err(codec->dev, "Failed to register codec\n");
-               return ret;
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
+                                aic3x->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err_get;
+       }
+       for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
+               aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
+               aic3x->disable_nb[i].aic3x = aic3x;
+               ret = regulator_register_notifier(aic3x->supplies[i].consumer,
+                                                 &aic3x->disable_nb[i].nb);
+               if (ret) {
+                       dev_err(codec->dev,
+                               "Failed to request regulator notifier: %d\n",
+                                ret);
+                       goto err_notif;
+               }
        }
 
-       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;
+       codec->cache_only = 1;
+       aic3x_init(codec);
+
+       if (aic3x->setup) {
+               /* setup GPIO functions */
+               snd_soc_write(codec, AIC3X_GPIO1_REG,
+                             (aic3x->setup->gpio_func[0] & 0xf) << 4);
+               snd_soc_write(codec, AIC3X_GPIO2_REG,
+                             (aic3x->setup->gpio_func[1] & 0xf) << 4);
        }
 
+       snd_soc_add_controls(codec, aic3x_snd_controls,
+                            ARRAY_SIZE(aic3x_snd_controls));
+       if (aic3x->model == AIC3X_MODEL_3007)
+               snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+
+       aic3x_add_widgets(codec);
+
        return 0;
+
+err_notif:
+       while (i--)
+               regulator_unregister_notifier(aic3x->supplies[i].consumer,
+                                             &aic3x->disable_nb[i].nb);
+       regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+err_get:
+       if (aic3x->gpio_reset >= 0)
+               gpio_free(aic3x->gpio_reset);
+err_gpio:
+       kfree(aic3x);
+       return ret;
 }
 
-static int aic3x_unregister(struct aic3x_priv *aic3x)
+static int aic3x_remove(struct snd_soc_codec *codec)
 {
-       aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF);
-
-       snd_soc_unregister_dai(&aic3x_dai);
-       snd_soc_unregister_codec(&aic3x->codec);
+       struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
+       int i;
 
+       aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        if (aic3x->gpio_reset >= 0) {
                gpio_set_value(aic3x->gpio_reset, 0);
                gpio_free(aic3x->gpio_reset);
        }
-       regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
+       for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
+               regulator_unregister_notifier(aic3x->supplies[i].consumer,
+                                             &aic3x->disable_nb[i].nb);
        regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
 
-       kfree(aic3x);
-       aic3x_codec = NULL;
-
        return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
+       .set_bias_level = aic3x_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(aic3x_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = aic3x_reg,
+       .probe = aic3x_probe,
+       .remove = aic3x_remove,
+       .suspend = aic3x_suspend,
+       .resume = aic3x_resume,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
  * AIC3X 2 wire address can be up to 4 devices with device addresses
  * 0x18, 0x19, 0x1A, 0x1B
  */
 
+static const struct i2c_device_id aic3x_i2c_id[] = {
+       [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
+       [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
+       [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
+
 /*
  * If the i2c layer weren't so broken, we could pass this kind of data
  * around
@@ -1308,10 +1471,10 @@ 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;
        struct aic3x_pdata *pdata = i2c->dev.platform_data;
-       int ret, i;
+       struct aic3x_priv *aic3x;
+       int ret;
+       const struct i2c_device_id *tbl;
 
        aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
        if (aic3x == NULL) {
@@ -1319,75 +1482,41 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
        }
 
-       codec = &aic3x->codec;
-       codec->dev = &i2c->dev;
-       snd_soc_codec_set_drvdata(codec, aic3x);
-       codec->control_data = i2c;
-       codec->hw_write = (hw_write_t) i2c_master_send;
+       aic3x->control_data = i2c;
+       aic3x->control_type = SND_SOC_I2C;
 
        i2c_set_clientdata(i2c, aic3x);
-
-       aic3x->gpio_reset = -1;
-       if (pdata && pdata->gpio_reset >= 0) {
-               ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
-               if (ret != 0)
-                       goto err_gpio;
+       if (pdata) {
                aic3x->gpio_reset = pdata->gpio_reset;
-               gpio_direction_output(aic3x->gpio_reset, 0);
-       }
-
-       for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
-               aic3x->supplies[i].supply = aic3x_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
-                                aic3x->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err_get;
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
-                                   aic3x->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_enable;
+               aic3x->setup = pdata->setup;
+       } else {
+               aic3x->gpio_reset = -1;
        }
 
-       if (aic3x->gpio_reset >= 0) {
-               udelay(1);
-               gpio_set_value(aic3x->gpio_reset, 1);
+       for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
+               if (!strcmp(tbl->name, id->name))
+                       break;
        }
+       aic3x->model = tbl - aic3x_i2c_id;
 
-       return aic3x_register(codec);
-
-err_enable:
-       regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
-err_get:
-       if (aic3x->gpio_reset >= 0)
-               gpio_free(aic3x->gpio_reset);
-err_gpio:
-       kfree(aic3x);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_aic3x, &aic3x_dai, 1);
+       if (ret < 0)
+               kfree(aic3x);
        return ret;
 }
 
 static int aic3x_i2c_remove(struct i2c_client *client)
 {
-       struct aic3x_priv *aic3x = i2c_get_clientdata(client);
-
-       return aic3x_unregister(aic3x);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
 }
 
-static const struct i2c_device_id aic3x_i2c_id[] = {
-       { "tlv320aic3x", 0 },
-       { "tlv320aic33", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
-
 /* machine i2c codec control layer */
 static struct i2c_driver aic3x_i2c_driver = {
        .driver = {
-               .name = "aic3x I2C Codec",
+               .name = "tlv320aic3x-codec",
                .owner = THIS_MODULE,
        },
        .probe  = aic3x_i2c_probe,
@@ -1409,90 +1538,27 @@ static inline void aic3x_i2c_exit(void)
 {
        i2c_del_driver(&aic3x_i2c_driver);
 }
-#else
-static inline void aic3x_i2c_init(void) { }
-static inline void aic3x_i2c_exit(void) { }
 #endif
 
-static int aic3x_probe(struct platform_device *pdev)
+static int __init aic3x_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct aic3x_setup_data *setup;
-       struct snd_soc_codec *codec;
        int ret = 0;
-
-       codec = aic3x_codec;
-       if (!codec) {
-               dev_err(&pdev->dev, "Codec not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = codec;
-       setup = socdev->codec_data;
-
-       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;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&aic3x_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
+                      ret);
        }
-
-       snd_soc_add_controls(codec, aic3x_snd_controls,
-                            ARRAY_SIZE(aic3x_snd_controls));
-
-       aic3x_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       kfree(codec->reg_cache);
+#endif
        return ret;
 }
-
-static int aic3x_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       /* power down chip */
-       if (codec->control_data)
-               aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
-       kfree(codec->reg_cache);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_aic3x = {
-       .probe = aic3x_probe,
-       .remove = aic3x_remove,
-       .suspend = aic3x_suspend,
-       .resume = aic3x_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
-
-static int __init aic3x_modinit(void)
-{
-       aic3x_i2c_init();
-
-       return 0;
-}
 module_init(aic3x_modinit);
 
 static void __exit aic3x_exit(void)
 {
-       aic3x_i2c_exit();
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&aic3x_i2c_driver);
+#endif
 }
 module_exit(aic3x_exit);
 
index 9af1c88..06a1978 100644 (file)
 /* DAC Digital control registers */
 #define LDAC_VOL                       43
 #define RDAC_VOL                       44
-/* High Power Output control registers */
+/* Left High Power Output control registers */
 #define LINE2L_2_HPLOUT_VOL            45
-#define LINE2R_2_HPROUT_VOL            62
 #define PGAL_2_HPLOUT_VOL              46
-#define PGAL_2_HPROUT_VOL              60
-#define PGAR_2_HPLOUT_VOL              49
-#define PGAR_2_HPROUT_VOL              63
 #define DACL1_2_HPLOUT_VOL             47
-#define DACR1_2_HPROUT_VOL             64
+#define LINE2R_2_HPLOUT_VOL            48
+#define PGAR_2_HPLOUT_VOL              49
+#define DACR1_2_HPLOUT_VOL             50
 #define HPLOUT_CTRL                    51
-#define HPROUT_CTRL                    65
-/* High Power COM control registers */
+/* Left High Power COM control registers */
 #define LINE2L_2_HPLCOM_VOL            52
-#define LINE2R_2_HPRCOM_VOL            69
 #define PGAL_2_HPLCOM_VOL              53
+#define DACL1_2_HPLCOM_VOL             54
+#define LINE2R_2_HPLCOM_VOL            55
 #define PGAR_2_HPLCOM_VOL              56
+#define DACR1_2_HPLCOM_VOL             57
+#define HPLCOM_CTRL                    58
+/* Right High Power Output control registers */
+#define LINE2L_2_HPROUT_VOL            59
+#define PGAL_2_HPROUT_VOL              60
+#define DACL1_2_HPROUT_VOL             61
+#define LINE2R_2_HPROUT_VOL            62
+#define PGAR_2_HPROUT_VOL              63
+#define DACR1_2_HPROUT_VOL             64
+#define HPROUT_CTRL                    65
+/* Right High Power COM control registers */
+#define LINE2L_2_HPRCOM_VOL            66
 #define PGAL_2_HPRCOM_VOL              67
+#define DACL1_2_HPRCOM_VOL             68
+#define LINE2R_2_HPRCOM_VOL            69
 #define PGAR_2_HPRCOM_VOL              70
-#define DACL1_2_HPLCOM_VOL             54
 #define DACR1_2_HPRCOM_VOL             71
-#define HPLCOM_CTRL                    58
 #define HPRCOM_CTRL                    72
 /* Mono Line Output Plus/Minus control registers */
 #define LINE2L_2_MONOLOPM_VOL          73
-#define LINE2R_2_MONOLOPM_VOL          76
 #define PGAL_2_MONOLOPM_VOL            74
-#define PGAR_2_MONOLOPM_VOL            77
 #define DACL1_2_MONOLOPM_VOL           75
+#define LINE2R_2_MONOLOPM_VOL          76
+#define PGAR_2_MONOLOPM_VOL            77
 #define DACR1_2_MONOLOPM_VOL           78
 #define MONOLOPM_CTRL                  79
-/* Line Output Plus/Minus control registers */
+/* Class-D speaker driver on tlv320aic3007 */
+#define CLASSD_CTRL                    73
+/* Left Line Output Plus/Minus control registers */
 #define LINE2L_2_LLOPM_VOL             80
-#define LINE2L_2_RLOPM_VOL             87
-#define LINE2R_2_LLOPM_VOL             83
-#define LINE2R_2_RLOPM_VOL             90
 #define PGAL_2_LLOPM_VOL               81
-#define PGAL_2_RLOPM_VOL               88
-#define PGAR_2_LLOPM_VOL               84
-#define PGAR_2_RLOPM_VOL               91
 #define DACL1_2_LLOPM_VOL              82
-#define DACL1_2_RLOPM_VOL              89
-#define DACR1_2_RLOPM_VOL              92
+#define LINE2R_2_LLOPM_VOL             83
+#define PGAR_2_LLOPM_VOL               84
 #define DACR1_2_LLOPM_VOL              85
 #define LLOPM_CTRL                     86
+/* Right Line Output Plus/Minus control registers */
+#define LINE2L_2_RLOPM_VOL             87
+#define PGAL_2_RLOPM_VOL               88
+#define DACL1_2_RLOPM_VOL              89
+#define LINE2R_2_RLOPM_VOL             90
+#define PGAR_2_RLOPM_VOL               91
+#define DACR1_2_RLOPM_VOL              92
 #define RLOPM_CTRL                     93
 /* GPIO/IRQ registers */
 #define AIC3X_STICKY_IRQ_FLAGS_REG     96
 /* Default input volume */
 #define DEFAULT_GAIN    0x20
 
-/* GPIO API */
-enum {
-       AIC3X_GPIO1_FUNC_DISABLED               = 0,
-       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC      = 1,
-       AIC3X_GPIO1_FUNC_CLOCK_MUX              = 2,
-       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2         = 3,
-       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4         = 4,
-       AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8         = 5,
-       AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ      = 6,
-       AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ          = 7,
-       AIC3X_GPIO1_FUNC_INPUT                  = 8,
-       AIC3X_GPIO1_FUNC_OUTPUT                 = 9,
-       AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK     = 10,
-       AIC3X_GPIO1_FUNC_AUDIO_WORDCLK          = 11,
-       AIC3X_GPIO1_FUNC_BUTTON_IRQ             = 12,
-       AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ     = 13,
-       AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ   = 14,
-       AIC3X_GPIO1_FUNC_ALL_IRQ                = 16
-};
-
-enum {
-       AIC3X_GPIO2_FUNC_DISABLED               = 0,
-       AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ     = 2,
-       AIC3X_GPIO2_FUNC_INPUT                  = 3,
-       AIC3X_GPIO2_FUNC_OUTPUT                 = 4,
-       AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT      = 5,
-       AIC3X_GPIO2_FUNC_AUDIO_BITCLK           = 8,
-       AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
-       AIC3X_GPIO2_FUNC_ALL_IRQ                = 10,
-       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
-       AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
-       AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ      = 13,
-       AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ          = 14,
-       AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ       = 15
-};
-
 void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
 int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
 
@@ -281,11 +258,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
 int aic3x_headset_detected(struct snd_soc_codec *codec);
 int aic3x_button_pressed(struct snd_soc_codec *codec);
 
-struct aic3x_setup_data {
-       unsigned int gpio_func[2];
-};
-
-extern struct snd_soc_dai aic3x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_aic3x;
-
 #endif /* _AIC3X_H */
index 8651b01..d251ff5 100644 (file)
@@ -66,8 +66,6 @@
 static void dac33_calculate_times(struct snd_pcm_substream *substream);
 static int dac33_prepare_chip(struct snd_pcm_substream *substream);
 
-static struct snd_soc_codec *tlv320dac33_codec;
-
 enum dac33_state {
        DAC33_IDLE = 0,
        DAC33_PREFILL,
@@ -93,7 +91,7 @@ struct tlv320dac33_priv {
        struct mutex mutex;
        struct workqueue_struct *dac33_wq;
        struct work_struct work;
-       struct snd_soc_codec codec;
+       struct snd_soc_codec *codec;
        struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
        struct snd_pcm_substream *substream;
        int power_gpio;
@@ -128,6 +126,8 @@ struct tlv320dac33_priv {
        unsigned int uthr;
 
        enum dac33_state state;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
@@ -524,6 +524,22 @@ static const struct soc_enum dac33_fifo_mode_enum =
        SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts),
                            dac33_fifo_mode_texts);
 
+/* L/R Line Output Gain */
+static const char *lr_lineout_gain_texts[] = {
+       "Line -12dB DAC 0dB", "Line -6dB DAC 6dB",
+       "Line 0dB DAC 12dB", "Line 6dB DAC 18dB",
+};
+
+static const struct soc_enum l_lineout_gain_enum =
+       SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0,
+                       ARRAY_SIZE(lr_lineout_gain_texts),
+                       lr_lineout_gain_texts);
+
+static const struct soc_enum r_lineout_gain_enum =
+       SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0,
+                       ARRAY_SIZE(lr_lineout_gain_texts),
+                       lr_lineout_gain_texts);
+
 /*
  * DACL/R digital volume control:
  * from 0 dB to -63.5 in 0.5 dB steps
@@ -541,6 +557,8 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
                 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
        SOC_DOUBLE_R("Line to Line Out Volume",
                 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
+       SOC_ENUM("Left Line Output Gain", l_lineout_gain_enum),
+       SOC_ENUM("Right Line Output Gain", r_lineout_gain_enum),
 };
 
 static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
@@ -650,9 +668,8 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
 
 static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
 {
-       struct snd_soc_codec *codec;
-
-       codec = &dac33->codec;
+       struct snd_soc_codec *codec = dac33->codec;
+       unsigned int delay;
 
        switch (dac33->fifo_mode) {
        case DAC33_FIFO_MODE1:
@@ -668,8 +685,9 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
                dac33_write16(codec, DAC33_PREFILL_MSB,
                                DAC33_THRREG(dac33->alarm_threshold));
                /* Enable Alarm Threshold IRQ with a delay */
-               udelay(SAMPLES_TO_US(dac33->burst_rate,
-                                    dac33->alarm_threshold));
+               delay = SAMPLES_TO_US(dac33->burst_rate,
+                                    dac33->alarm_threshold) + 1000;
+               usleep_range(delay, delay + 500);
                dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT);
                break;
        case DAC33_FIFO_MODE7:
@@ -695,9 +713,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
 
 static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33)
 {
-       struct snd_soc_codec *codec;
-
-       codec = &dac33->codec;
+       struct snd_soc_codec *codec = dac33->codec;
 
        switch (dac33->fifo_mode) {
        case DAC33_FIFO_MODE1:
@@ -726,7 +742,7 @@ static void dac33_work(struct work_struct *work)
        u8 reg;
 
        dac33 = container_of(work, struct tlv320dac33_priv, work);
-       codec = &dac33->codec;
+       codec = dac33->codec;
 
        mutex_lock(&dac33->mutex);
        switch (dac33->state) {
@@ -771,11 +787,11 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
 
 static void dac33_oscwait(struct snd_soc_codec *codec)
 {
-       int timeout = 20;
+       int timeout = 60;
        u8 reg;
 
        do {
-               msleep(1);
+               usleep_range(1000, 2000);
                dac33_read(codec, DAC33_INT_OSC_STATUS, &reg);
        } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--);
        if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL)
@@ -787,8 +803,7 @@ static int dac33_startup(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        /* Stream started, save the substream pointer */
@@ -801,8 +816,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
                             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 snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        dac33->substream = NULL;
@@ -817,8 +831,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
 
        /* Check parameters for validity */
        switch (params_rate(params)) {
@@ -856,8 +869,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
 static int dac33_prepare_chip(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;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
        u8 aictrl_a, aictrl_b, fifoctrl_a;
@@ -1049,8 +1061,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
 static void dac33_calculate_times(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;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned int period_size = substream->runtime->period_size;
        unsigned int rate = substream->runtime->rate;
@@ -1129,8 +1140,7 @@ static int dac33_pcm_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_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
@@ -1163,8 +1173,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
                        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 snd_soc_codec *codec = rtd->codec;
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        unsigned long long t0, t1, t_now;
        unsigned int time_delta, uthr;
@@ -1389,24 +1398,46 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
-static int dac33_soc_probe(struct platform_device *pdev)
+static int dac33_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct tlv320dac33_priv *dac33;
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       BUG_ON(!tlv320dac33_codec);
+       codec->control_data = dac33->control_data;
+       codec->hw_write = (hw_write_t) i2c_master_send;
+       codec->idle_bias_off = 1;
+       dac33->codec = codec;
 
-       codec = tlv320dac33_codec;
-       socdev->card->codec = codec;
-       dac33 = snd_soc_codec_get_drvdata(codec);
+       /* Read the tlv320dac33 ID registers */
+       ret = dac33_hard_power(codec, 1);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
+               goto err_power;
+       }
+       dac33_read_id(codec);
+       dac33_hard_power(codec, 0);
+
+       /* Check if the IRQ number is valid and request it */
+       if (dac33->irq >= 0) {
+               ret = request_irq(dac33->irq, dac33_interrupt_handler,
+                                 IRQF_TRIGGER_RISING | IRQF_DISABLED,
+                                 codec->name, codec);
+               if (ret < 0) {
+                       dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
+                                               dac33->irq, ret);
+                       dac33->irq = -1;
+               }
+               if (dac33->irq != -1) {
+                       /* Setup work queue */
+                       dac33->dac33_wq =
+                               create_singlethread_workqueue("tlv320dac33");
+                       if (dac33->dac33_wq == NULL) {
+                               free_irq(dac33->irq, codec);
+                               return -ENOMEM;
+                       }
 
-       /* 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\n");
-               goto pcm_err;
+                       INIT_WORK(&dac33->work, dac33_work);
+               }
        }
 
        snd_soc_add_controls(codec, dac33_snd_controls,
@@ -1420,56 +1451,51 @@ static int dac33_soc_probe(struct platform_device *pdev)
                        snd_soc_add_controls(codec, dac33_fifo_snd_controls,
                                        ARRAY_SIZE(dac33_fifo_snd_controls));
        }
-
        dac33_add_widgets(codec);
 
-       return 0;
-
-pcm_err:
-       dac33_hard_power(codec, 0);
+err_power:
        return ret;
 }
 
-static int dac33_soc_remove(struct platform_device *pdev)
+static int dac33_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
        dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       if (dac33->irq >= 0) {
+               free_irq(dac33->irq, dac33->codec);
+               destroy_workqueue(dac33->dac33_wq);
+       }
        return 0;
 }
 
-static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int dac33_soc_resume(struct platform_device *pdev)
+static int dac33_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = {
+static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
+       .read = dac33_read_reg_cache,
+       .write = dac33_write_locked,
+       .set_bias_level = dac33_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(dac33_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = dac33_reg,
        .probe = dac33_soc_probe,
        .remove = dac33_soc_remove,
        .suspend = dac33_soc_suspend,
        .resume = dac33_soc_resume,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
 
 #define DAC33_RATES    (SNDRV_PCM_RATE_44100 | \
                         SNDRV_PCM_RATE_48000)
@@ -1485,8 +1511,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = {
        .set_fmt        = dac33_set_dai_fmt,
 };
 
-struct snd_soc_dai dac33_dai = {
-       .name = "tlv320dac33",
+static struct snd_soc_dai_driver dac33_dai = {
+       .name = "tlv320dac33-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -1495,14 +1521,12 @@ struct snd_soc_dai dac33_dai = {
                .formats = DAC33_FORMATS,},
        .ops = &dac33_dai_ops,
 };
-EXPORT_SYMBOL_GPL(dac33_dai);
 
 static int __devinit dac33_i2c_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        struct tlv320dac33_platform_data *pdata;
        struct tlv320dac33_priv *dac33;
-       struct snd_soc_codec *codec;
        int ret, i;
 
        if (client->dev.platform_data == NULL) {
@@ -1515,33 +1539,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
        if (dac33 == NULL)
                return -ENOMEM;
 
-       codec = &dac33->codec;
-       snd_soc_codec_set_drvdata(codec, dac33);
-       codec->control_data = client;
-
-       mutex_init(&codec->mutex);
+       dac33->control_data = client;
        mutex_init(&dac33->mutex);
        spin_lock_init(&dac33->lock);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "tlv320dac33";
-       codec->owner = THIS_MODULE;
-       codec->read = dac33_read_reg_cache;
-       codec->write = dac33_write_locked;
-       codec->hw_write = (hw_write_t) i2c_master_send;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = dac33_set_bias_level;
-       codec->idle_bias_off = 1;
-       codec->dai = &dac33_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
-       codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto error_reg;
-       }
 
        i2c_set_clientdata(client, dac33);
 
@@ -1561,125 +1561,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
        /* Disable FIFO use by default */
        dac33->fifo_mode = DAC33_FIFO_BYPASS;
 
-       tlv320dac33_codec = codec;
-
-       codec->dev = &client->dev;
-       dac33_dai.dev = codec->dev;
-
        /* Check if the reset GPIO number is valid and request it */
        if (dac33->power_gpio >= 0) {
                ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
                if (ret < 0) {
-                       dev_err(codec->dev,
+                       dev_err(&client->dev,
                                "Failed to request reset GPIO (%d)\n",
                                dac33->power_gpio);
-                       snd_soc_unregister_dai(&dac33_dai);
-                       snd_soc_unregister_codec(codec);
-                       goto error_gpio;
+                       goto err_gpio;
                }
                gpio_direction_output(dac33->power_gpio, 0);
        }
 
-       /* Check if the IRQ number is valid and request it */
-       if (dac33->irq >= 0) {
-               ret = request_irq(dac33->irq, dac33_interrupt_handler,
-                                 IRQF_TRIGGER_RISING | IRQF_DISABLED,
-                                 codec->name, codec);
-               if (ret < 0) {
-                       dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
-                                               dac33->irq, ret);
-                       dac33->irq = -1;
-               }
-               if (dac33->irq != -1) {
-                       /* Setup work queue */
-                       dac33->dac33_wq =
-                               create_singlethread_workqueue("tlv320dac33");
-                       if (dac33->dac33_wq == NULL) {
-                               free_irq(dac33->irq, &dac33->codec);
-                               ret = -ENOMEM;
-                               goto error_wq;
-                       }
-
-                       INIT_WORK(&dac33->work, dac33_work);
-               }
-       }
-
        for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
                dac33->supplies[i].supply = dac33_supply_names[i];
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies),
+       ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
                                 dac33->supplies);
 
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               dev_err(&client->dev, "Failed to request supplies: %d\n", ret);
                goto err_get;
        }
 
-       /* Read the tlv320dac33 ID registers */
-       ret = dac33_hard_power(codec, 1);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
-               goto error_codec;
-       }
-       dac33_read_id(codec);
-       dac33_hard_power(codec, 0);
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto error_codec;
-       }
-
-       ret = snd_soc_register_dai(&dac33_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               goto error_codec;
-       }
+       ret = snd_soc_register_codec(&client->dev,
+                       &soc_codec_dev_tlv320dac33, &dac33_dai, 1);
+       if (ret < 0)
+               goto err_register;
 
        return ret;
-
-error_codec:
+err_register:
        regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
 err_get:
-       if (dac33->irq >= 0) {
-               free_irq(dac33->irq, &dac33->codec);
-               destroy_workqueue(dac33->dac33_wq);
-       }
-error_wq:
        if (dac33->power_gpio >= 0)
                gpio_free(dac33->power_gpio);
-error_gpio:
-       kfree(codec->reg_cache);
-error_reg:
-       tlv320dac33_codec = NULL;
+err_gpio:
        kfree(dac33);
-
        return ret;
 }
 
 static int __devexit dac33_i2c_remove(struct i2c_client *client)
 {
-       struct tlv320dac33_priv *dac33;
-
-       dac33 = i2c_get_clientdata(client);
+       struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
 
        if (unlikely(dac33->chip_power))
-               dac33_hard_power(&dac33->codec, 0);
+               dac33_hard_power(dac33->codec, 0);
 
        if (dac33->power_gpio >= 0)
                gpio_free(dac33->power_gpio);
-       if (dac33->irq >= 0)
-               free_irq(dac33->irq, &dac33->codec);
 
        regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
 
-       destroy_workqueue(dac33->dac33_wq);
-       snd_soc_unregister_dai(&dac33_dai);
-       snd_soc_unregister_codec(&dac33->codec);
-       kfree(dac33->codec.reg_cache);
+       snd_soc_unregister_codec(&client->dev);
        kfree(dac33);
-       tlv320dac33_codec = NULL;
 
        return 0;
 }
@@ -1694,7 +1628,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
 
 static struct i2c_driver tlv320dac33_i2c_driver = {
        .driver = {
-               .name = "tlv320dac33",
+               .name = "tlv320dac33-codec",
                .owner = THIS_MODULE,
        },
        .probe          = dac33_i2c_probe,
index eb8ae07..7c318b5 100644 (file)
 #define TLV320DAC33_MCLK               0
 #define TLV320DAC33_SLEEPCLK           1
 
-extern struct snd_soc_dai dac33_dai;
-extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33;
-
 #endif /* __TLV320DAC33_H */
index 99b70e5..329acc1 100644 (file)
@@ -98,16 +98,21 @@ static u8 tpa6130a2_read(int reg)
        return data->regs[reg];
 }
 
-static void tpa6130a2_initialize(void)
+static int tpa6130a2_initialize(void)
 {
        struct tpa6130a2_data *data;
-       int i;
+       int i, ret = 0;
 
        BUG_ON(tpa6130a2_client == NULL);
        data = i2c_get_clientdata(tpa6130a2_client);
 
-       for (i = 1; i < TPA6130A2_REG_VERSION; i++)
-               tpa6130a2_i2c_write(i, data->regs[i]);
+       for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
+               ret = tpa6130a2_i2c_write(i, data->regs[i]);
+               if (ret < 0)
+                       break;
+       }
+
+       return ret;
 }
 
 static int tpa6130a2_power(int power)
@@ -133,7 +138,16 @@ static int tpa6130a2_power(int power)
                }
 
                data->power_state = 1;
-               tpa6130a2_initialize();
+               ret = tpa6130a2_initialize();
+               if (ret < 0) {
+                       dev_err(&tpa6130a2_client->dev,
+                               "Failed to initialize chip\n");
+                       if (data->power_gpio >= 0)
+                               gpio_set_value(data->power_gpio, 0);
+                       regulator_disable(data->supply);
+                       data->power_state = 0;
+                       goto exit;
+               }
 
                /* Clear SWS */
                val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
@@ -375,7 +389,9 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
 {
        struct  tpa6130a2_data *data;
 
-       BUG_ON(tpa6130a2_client == NULL);
+       if (tpa6130a2_client == NULL)
+               return -ENODEV;
+
        data = i2c_get_clientdata(tpa6130a2_client);
 
        snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
index 7b618bb..cbebec6 100644 (file)
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include "twl4030.h"
+/* Register descriptions are here */
+#include <linux/mfd/twl4030-codec.h>
+
+/* Shadow register used by the audio driver */
+#define TWL4030_REG_SW_SHADOW          0x4A
+#define TWL4030_CACHEREGNUM    (TWL4030_REG_SW_SHADOW + 1)
+
+/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
+#define TWL4030_HFL_EN                 0x01
+#define TWL4030_HFR_EN                 0x02
 
 /*
  * twl4030 register cache & default register settings
@@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
 
 }
 
-static void twl4030_init_chip(struct platform_device *pdev)
+static void twl4030_init_chip(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct twl4030_setup_data *setup = socdev->codec_data;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 reg, byte;
        int i = 0;
 
        /* Check defaults, if instructed before anything else */
-       if (setup && setup->check_defaults)
+       if (pdata && pdata->check_defaults)
                twl4030_check_defaults(codec);
 
        /* Reset registers, if no setup data or if instructed to do so */
-       if (!setup || (setup && setup->reset_registers))
+       if (!pdata || (pdata && pdata->reset_registers))
                twl4030_reset_registers(codec);
 
        /* Refresh APLL_CTL register from HW */
@@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev)
        twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);
 
        /* Machine dependent setup */
-       if (!setup)
+       if (!pdata)
                return;
 
-       twl4030->digimic_delay = setup->digimic_delay;
-
-       /* Configuration for headset ramp delay from setup data */
-       if (setup->sysclk != twl4030->sysclk)
-               dev_warn(codec->dev,
-                               "Mismatch in APLL mclk: %u (configured: %u)\n",
-                               setup->sysclk, twl4030->sysclk);
+       twl4030->digimic_delay = pdata->digimic_delay;
 
        reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
        reg &= ~TWL4030_RAMP_DELAY;
-       reg |= (setup->ramp_delay_value << 2);
+       reg |= (pdata->ramp_delay_value << 2);
        twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);
 
        /* initiate offset cancellation */
@@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev)
 
        reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
        reg &= ~TWL4030_OFFSET_CNCL_SEL;
-       reg |= setup->offset_cncl_path;
+       reg |= pdata->offset_cncl_path;
        twl4030_write(codec, TWL4030_REG_ANAMICL,
                reg | TWL4030_CNCL_OFFSET_START);
 
@@ -718,9 +719,7 @@ static int aif_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;
-
+       struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
        unsigned char hs_gain, hs_pop;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        /* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
 
        /* 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);
+       if (pdata && pdata->hs_extmute) {
+               if (pdata->set_hs_extmute) {
+                       pdata->set_hs_extmute(1);
                } else {
                        hs_pop |= TWL4030_EXTMUTE;
                        twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
        }
 
        /* Disable external mute */
-       if (setup && setup->hs_extmute) {
-               if (setup->set_hs_extmute) {
-                       setup->set_hs_extmute(0);
+       if (pdata && pdata->hs_extmute) {
+               if (pdata->set_hs_extmute) {
+                       pdata->set_hs_extmute(0);
                } else {
                        hs_pop &= ~TWL4030_EXTMUTE;
                        twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
        if (twl4030->master_substream) {
@@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
                             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 snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
 
        if (twl4030->master_substream == substream)
@@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
                           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 snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 mode, old_mode, format, old_format;
 
@@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
                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 snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 mode;
 
@@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
 
        /* Enable voice digital filters */
        twl4030_voice_enable(codec, substream->stream, 0);
@@ -2044,8 +2038,7 @@ static int twl4030_voice_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 snd_soc_codec *codec = rtd->codec;
        struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
        u8 old_mode, mode;
 
@@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
 #define TWL4030_RATES   (SNDRV_PCM_RATE_8000_48000)
 #define TWL4030_FORMATS         (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
 
-static struct snd_soc_dai_ops twl4030_dai_ops = {
+static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
        .startup        = twl4030_startup,
        .shutdown       = twl4030_shutdown,
        .hw_params      = twl4030_hw_params,
@@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
        .set_tristate   = twl4030_voice_set_tristate,
 };
 
-struct snd_soc_dai twl4030_dai[] = {
+static struct snd_soc_dai_driver twl4030_dai[] = {
 {
-       .name = "twl4030",
+       .name = "twl4030-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 2,
@@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = {
                .channels_max = 4,
                .rates = TWL4030_RATES,
                .formats = TWL4030_FORMATS,},
-       .ops = &twl4030_dai_ops,
+       .ops = &twl4030_dai_hifi_ops,
 },
 {
-       .name = "twl4030 Voice",
+       .name = "twl4030-voice",
        .playback = {
                .stream_name = "Voice Playback",
                .channels_min = 1,
@@ -2227,164 +2220,91 @@ struct snd_soc_dai twl4030_dai[] = {
        .ops = &twl4030_dai_voice_ops,
 },
 };
-EXPORT_SYMBOL_GPL(twl4030_dai);
 
-static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
        return 0;
 }
 
-static int twl4030_soc_resume(struct platform_device *pdev)
+static int twl4030_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
 
-static struct snd_soc_codec *twl4030_codec;
-
-static int twl4030_soc_probe(struct platform_device *pdev)
+static int twl4030_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       BUG_ON(!twl4030_codec);
-
-       codec = twl4030_codec;
-       socdev->card->codec = codec;
-
-       twl4030_init_chip(pdev);
+       struct twl4030_priv *twl4030;
 
-       /* 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");
-               return ret;
+       twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
+       if (twl4030 == NULL) {
+               printk("Can not allocate memroy\n");
+               return -ENOMEM;
        }
+       snd_soc_codec_set_drvdata(codec, twl4030);
+       /* Set the defaults, and power up the codec */
+       twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
+       codec->idle_bias_off = 1;
+
+       twl4030_init_chip(codec);
 
        snd_soc_add_controls(codec, twl4030_snd_controls,
                                ARRAY_SIZE(twl4030_snd_controls));
        twl4030_add_widgets(codec);
-
        return 0;
 }
 
-static int twl4030_soc_remove(struct platform_device *pdev)
+static int twl4030_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        /* Reset registers to their chip default before leaving */
        twl4030_reset_registers(codec);
        twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
        return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
+       .probe = twl4030_soc_probe,
+       .remove = twl4030_soc_remove,
+       .suspend = twl4030_soc_suspend,
+       .resume = twl4030_soc_resume,
+       .read = twl4030_read_reg_cache,
+       .write = twl4030_write,
+       .set_bias_level = twl4030_set_bias_level,
+       .reg_cache_size = sizeof(twl4030_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = twl4030_reg,
+};
+
 static int __devinit twl4030_codec_probe(struct platform_device *pdev)
 {
        struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
-       struct snd_soc_codec *codec;
-       struct twl4030_priv *twl4030;
-       int ret;
 
        if (!pdata) {
                dev_err(&pdev->dev, "platform_data is missing\n");
                return -EINVAL;
        }
 
-       twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
-       if (twl4030 == NULL) {
-               dev_err(&pdev->dev, "Can not allocate memroy\n");
-               return -ENOMEM;
-       }
-
-       codec = &twl4030->codec;
-       snd_soc_codec_set_drvdata(codec, twl4030);
-       codec->dev = &pdev->dev;
-       twl4030_dai[0].dev = &pdev->dev;
-       twl4030_dai[1].dev = &pdev->dev;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "twl4030";
-       codec->owner = THIS_MODULE;
-       codec->read = twl4030_read_reg_cache;
-       codec->write = twl4030_write;
-       codec->set_bias_level = twl4030_set_bias_level;
-       codec->idle_bias_off = 1;
-       codec->dai = twl4030_dai;
-       codec->num_dai = ARRAY_SIZE(twl4030_dai);
-       codec->reg_cache_size = sizeof(twl4030_reg);
-       codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
-                                       GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto error_cache;
-       }
-
-       platform_set_drvdata(pdev, twl4030);
-       twl4030_codec = codec;
-
-       /* Set the defaults, and power up the codec */
-       twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto error_codec;
-       }
-
-       ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               goto error_codec;
-       }
-
-       return 0;
-
-error_codec:
-       twl4030_codec_enable(codec, 0);
-       kfree(codec->reg_cache);
-error_cache:
-       kfree(twl4030);
-       return ret;
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
+                       twl4030_dai, ARRAY_SIZE(twl4030_dai));
 }
 
 static int __devexit twl4030_codec_remove(struct platform_device *pdev)
 {
-       struct twl4030_priv *twl4030 = platform_get_drvdata(pdev);
+       struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
 
-       snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
-       snd_soc_unregister_codec(&twl4030->codec);
-       kfree(twl4030->codec.reg_cache);
+       snd_soc_unregister_codec(&pdev->dev);
        kfree(twl4030);
-
-       twl4030_codec = NULL;
        return 0;
 }
 
-MODULE_ALIAS("platform:twl4030_codec_audio");
+MODULE_ALIAS("platform:twl4030-codec");
 
 static struct platform_driver twl4030_codec_driver = {
        .probe          = twl4030_codec_probe,
        .remove         = __devexit_p(twl4030_codec_remove),
        .driver         = {
-               .name   = "twl4030_codec_audio",
+               .name   = "twl4030-codec",
                .owner  = THIS_MODULE,
        },
 };
@@ -2401,14 +2321,6 @@ static void __exit twl4030_exit(void)
 }
 module_exit(twl4030_exit);
 
-struct snd_soc_codec_device soc_codec_dev_twl4030 = {
-       .probe = twl4030_soc_probe,
-       .remove = twl4030_soc_remove,
-       .suspend = twl4030_soc_suspend,
-       .resume = twl4030_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
-
 MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
 MODULE_AUTHOR("Steve Sakoman");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
deleted file mode 100644 (file)
index 6c57430..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * ALSA SoC TWL4030 codec driver
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * 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
- *
- */
-
-#ifndef __TWL4030_AUDIO_H__
-#define __TWL4030_AUDIO_H__
-
-/* Register descriptions are here */
-#include <linux/mfd/twl4030-codec.h>
-
-/* Shadow register used by the audio driver */
-#define TWL4030_REG_SW_SHADOW          0x4A
-#define TWL4030_CACHEREGNUM    (TWL4030_REG_SW_SHADOW + 1)
-
-/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
-#define TWL4030_HFL_EN                 0x01
-#define TWL4030_HFR_EN                 0x02
-
-#define TWL4030_DAI_HIFI               0
-#define TWL4030_DAI_VOICE              1
-
-extern struct snd_soc_dai twl4030_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_twl4030;
-
-struct twl4030_setup_data {
-       unsigned int ramp_delay_value;
-       unsigned int digimic_delay; /* in ms */
-       unsigned int sysclk;
-       unsigned int offset_cncl_path;
-       unsigned int check_defaults:1;
-       unsigned int reset_registers:1;
-       unsigned int hs_extmute:1;
-       void (*set_hs_extmute)(int mute);
-};
-
-#endif /* End of __TWL4030_AUDIO_H__ */
-
-
index 64a807f..10f6e52 100644 (file)
@@ -45,7 +45,6 @@
 
 /* codec private data */
 struct twl6040_data {
-       struct snd_soc_codec codec;
        int audpwron;
        int naudint;
        int codec_powered;
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
                        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 snd_soc_codec *codec = rtd->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
        if (!priv->sysclk) {
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
                        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 snd_soc_codec *codec = rtd->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        u8 lppllctl;
        int rate;
@@ -839,8 +836,7 @@ static int twl6040_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_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 
        switch (cmd) {
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
        .set_sysclk     = twl6040_set_dai_sysclk,
 };
 
-struct snd_soc_dai twl6040_dai = {
-       .name = "twl6040",
+static struct snd_soc_dai_driver twl6040_dai = {
+       .name = "twl6040-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = {
        },
        .ops = &twl6040_dai_ops,
 };
-EXPORT_SYMBOL_GPL(twl6040_dai);
 
 #ifdef CONFIG_PM
-static int twl6040_suspend(struct platform_device *pdev, pm_message_t state)
+static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int twl6040_resume(struct platform_device *pdev)
+static int twl6040_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev)
 #define twl6040_resume NULL
 #endif
 
-static struct snd_soc_codec *twl6040_codec;
-
-static int twl6040_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       BUG_ON(!twl6040_codec);
-
-       codec = twl6040_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");
-               return ret;
-       }
-
-       snd_soc_add_controls(codec, twl6040_snd_controls,
-                               ARRAY_SIZE(twl6040_snd_controls));
-       twl6040_add_widgets(codec);
-
-       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);
-       return ret;
-}
-
-static int twl6040_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_twl6040 = {
-       .probe = twl6040_probe,
-       .remove = twl6040_remove,
-       .suspend = twl6040_suspend,
-       .resume = twl6040_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
-
-static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+static int twl6040_probe(struct snd_soc_codec *codec)
 {
-       struct twl4030_codec_data *twl_codec = pdev->dev.platform_data;
-       struct snd_soc_codec *codec;
+       struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
        struct twl6040_data *priv;
        int audpwron, naudint;
        int ret = 0;
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
        priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
+       snd_soc_codec_set_drvdata(codec, priv);
 
        if (twl_codec) {
                audpwron = twl_codec->audpwron_gpio;
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
        priv->audpwron = audpwron;
        priv->naudint = naudint;
 
-       codec = &priv->codec;
-       codec->dev = &pdev->dev;
-       twl6040_dai.dev = &pdev->dev;
-
-       codec->name = "twl6040";
-       codec->owner = THIS_MODULE;
-       codec->read = twl6040_read_reg_cache;
-       codec->write = twl6040_write;
-       codec->set_bias_level = twl6040_set_bias_level;
-       snd_soc_codec_set_drvdata(codec, priv);
-       codec->dai = &twl6040_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
-       codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
-                                       GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
        init_completion(&priv->ready);
 
        if (gpio_is_valid(audpwron)) {
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
        if (ret)
                goto irq_err;
 
-       ret = snd_soc_register_codec(codec);
-       if (ret)
-               goto reg_err;
-
-       twl6040_codec = codec;
-
-       ret = snd_soc_register_dai(&twl6040_dai);
-       if (ret)
-               goto dai_err;
+       snd_soc_add_controls(codec, twl6040_snd_controls,
+                               ARRAY_SIZE(twl6040_snd_controls));
+       twl6040_add_widgets(codec);
 
        return 0;
 
-dai_err:
-       snd_soc_unregister_codec(codec);
-       twl6040_codec = NULL;
-reg_err:
-       twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
 irq_err:
        if (naudint)
                free_irq(naudint, codec);
@@ -1193,36 +1090,57 @@ gpio2_err:
        if (gpio_is_valid(audpwron))
                gpio_free(audpwron);
 gpio1_err:
-       kfree(codec->reg_cache);
-cache_err:
        kfree(priv);
        return ret;
 }
 
-static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+static int twl6040_remove(struct snd_soc_codec *codec)
 {
-       struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec);
+       struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
        int audpwron = priv->audpwron;
        int naudint = priv->naudint;
 
+       twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
        if (gpio_is_valid(audpwron))
                gpio_free(audpwron);
 
        if (naudint)
-               free_irq(naudint, twl6040_codec);
+               free_irq(naudint, codec);
 
-       snd_soc_unregister_dai(&twl6040_dai);
-       snd_soc_unregister_codec(twl6040_codec);
+       kfree(priv);
 
-       kfree(twl6040_codec);
-       twl6040_codec = NULL;
+       return 0;
+}
 
+static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
+       .probe = twl6040_probe,
+       .remove = twl6040_remove,
+       .suspend = twl6040_suspend,
+       .resume = twl6040_resume,
+       .read = twl6040_read_reg_cache,
+       .write = twl6040_write,
+       .set_bias_level = twl6040_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(twl6040_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = twl6040_reg,
+};
+
+static int __devinit twl6040_codec_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_twl6040, &twl6040_dai, 1);
+}
+
+static int __devexit twl6040_codec_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver twl6040_codec_driver = {
        .driver = {
-               .name = "twl6040_codec",
+               .name = "twl6040-codec",
                .owner = THIS_MODULE,
        },
        .probe = twl6040_codec_probe,
index c472070..f7c77fa 100644 (file)
 #define TWL6040_HPPLL_ID               1
 #define TWL6040_LPPLL_ID               2
 
-extern struct snd_soc_dai twl6040_dai;
-extern struct snd_soc_codec_device soc_codec_dev_twl6040;
-
 #endif /* End of __TWL6040_H__ */
index f3b4c1d..7540a50 100644 (file)
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec =rtd->codec;
        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
        struct snd_pcm_runtime *master_runtime;
 
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 
        if (uda134x->master_substream == substream)
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
        u8 hw_params;
 
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
                        pd->power(1);
                        /* Sync reg_cache with the hardware */
                        for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
-                               codec->write(codec, i, *cache++);
+                               codec->driver->write(codec, i, *cache++);
                }
                break;
        case SND_SOC_BIAS_STANDBY:
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = {
        .set_fmt        = uda134x_set_dai_fmt,
 };
 
-struct snd_soc_dai uda134x_dai = {
-       .name = "UDA134X",
+static struct snd_soc_dai_driver uda134x_dai = {
+       .name = "uda134x-hifi",
        /* playback capabilities */
        .playback = {
                .stream_name = "Playback",
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = {
        /* pcm operations */
        .ops = &uda134x_dai_ops,
 };
-EXPORT_SYMBOL(uda134x_dai);
 
-
-static int uda134x_soc_probe(struct platform_device *pdev)
+static int uda134x_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
        struct uda134x_priv *uda134x;
-       void *codec_setup_data = socdev->codec_data;
-       int ret = -ENOMEM;
-       struct uda134x_platform_data *pd;
+       struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
+       int ret;
 
        printk(KERN_INFO "UDA134X SoC Audio Codec\n");
 
-       if (!codec_setup_data) {
+       if (!pd) {
                printk(KERN_ERR "UDA134X SoC codec: "
                       "missing L3 bitbang function\n");
                return -ENODEV;
        }
 
-       pd = codec_setup_data;
        switch (pd->model) {
        case UDA134X_UDA1340:
        case UDA134X_UDA1341:
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (socdev->card->codec == NULL)
-               return ret;
-
-       codec = socdev->card->codec;
-
        uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
        if (uda134x == NULL)
-               goto priv_err;
+               return -ENOMEM;
        snd_soc_codec_set_drvdata(codec, uda134x);
 
-       codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               goto reg_err;
-
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache_size = sizeof(uda134x_reg);
-       codec->reg_cache_step = 1;
-
-       codec->name = "UDA134X";
-       codec->owner = THIS_MODULE;
-       codec->dai = &uda134x_dai;
-       codec->num_dai = 1;
-       codec->read = uda134x_read_reg_cache;
-       codec->write = uda134x_write;
-
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->control_data = codec_setup_data;
+       codec->control_data = pd;
 
        if (pd->power)
                pd->power(1);
 
        uda134x_reset(codec);
 
-       if (pd->is_powered_on_standby) {
-               codec->set_bias_level = NULL;
+       if (pd->is_powered_on_standby)
                uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
-       } else {
-               codec->set_bias_level = uda134x_set_bias_level;
+       else
                uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       }
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "UDA134X: failed to register pcms\n");
-               goto pcm_err;
-       }
 
        switch (pd->model) {
        case UDA134X_UDA1340:
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev)
        default:
                printk(KERN_ERR "%s unknown codec type: %d",
                        __func__, pd->model);
-       return -EINVAL;
+               kfree(uda134x);
+               return -EINVAL;
        }
 
        if (ret < 0) {
                printk(KERN_ERR "UDA134X: failed to register controls\n");
-               goto pcm_err;
+               kfree(uda134x);
+               return ret;
        }
 
        return 0;
-
-pcm_err:
-       kfree(codec->reg_cache);
-reg_err:
-       kfree(snd_soc_codec_get_drvdata(codec));
-priv_err:
-       kfree(codec);
-       return ret;
 }
 
 /* power down chip */
-static int uda134x_soc_remove(struct platform_device *pdev)
+static int uda134x_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
 
        uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec->reg_cache);
-       kfree(codec);
-
+       kfree(uda134x);
        return 0;
 }
 
 #if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct platform_device *pdev,
+static int uda134x_soc_suspend(struct snd_soc_codec *codec,
                                                pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int uda134x_soc_resume(struct platform_device *pdev)
+static int uda134x_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
        uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
        return 0;
@@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev)
 #define uda134x_soc_resume NULL
 #endif /* CONFIG_PM */
 
-struct snd_soc_codec_device soc_codec_dev_uda134x = {
+static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
        .probe =        uda134x_soc_probe,
        .remove =       uda134x_soc_remove,
        .suspend =      uda134x_soc_suspend,
        .resume =       uda134x_soc_resume,
+       .reg_cache_size = sizeof(uda134x_reg),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_step = 1,
+       .read = uda134x_read_reg_cache,
+       .write = uda134x_write,
+#ifdef POWER_OFF_ON_STANDBY
+       .set_bias_level = uda134x_set_bias_level,
+#endif
+};
+
+static int __devinit uda134x_codec_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_uda134x, &uda134x_dai, 1);
+}
+
+static int __devexit uda134x_codec_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver uda134x_codec_driver = {
+       .driver = {
+               .name = "uda134x-codec",
+               .owner = THIS_MODULE,
+       },
+       .probe = uda134x_codec_probe,
+       .remove = __devexit_p(uda134x_codec_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
 
-static int __init uda134x_init(void)
+static int __init uda134x_codec_init(void)
 {
-       return snd_soc_register_dai(&uda134x_dai);
+       return platform_driver_register(&uda134x_codec_driver);
 }
-module_init(uda134x_init);
+module_init(uda134x_codec_init);
 
-static void __exit uda134x_exit(void)
+static void __exit uda134x_codec_exit(void)
 {
-       snd_soc_unregister_dai(&uda134x_dai);
+       platform_driver_unregister(&uda134x_codec_driver);
 }
-module_exit(uda134x_exit);
+module_exit(uda134x_codec_exit);
 
 MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
 MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
index 205f03b..9faae06 100644 (file)
@@ -31,7 +31,4 @@
 #define STATUS0_DAIFMT_MASK (~(7<<1))
 #define STATUS0_SYSCLK_MASK (~(3<<4))
 
-extern struct snd_soc_dai uda134x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_uda134x;
-
 #endif
index 2f925a2..0c6c725 100644 (file)
 
 #include "uda1380.h"
 
-static struct snd_soc_codec *uda1380_codec;
-
 /* codec private data */
 struct uda1380_priv {
-       struct snd_soc_codec codec;
+       struct snd_soc_codec *codec;
        u16 reg_cache[UDA1380_CACHEREGNUM];
        unsigned int dac_clk;
        struct work_struct work;
+       void *control_data;
 };
 
 /*
@@ -131,10 +130,51 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
                return -EIO;
 }
 
-#define uda1380_reset(c)       uda1380_write(c, UDA1380_RESET, 0)
+static void uda1380_sync_cache(struct snd_soc_codec *codec)
+{
+       int reg;
+       u8 data[3];
+       u16 *cache = codec->reg_cache;
+
+       /* Sync reg_cache with the hardware */
+       for (reg = 0; reg < UDA1380_MVOL; reg++) {
+               data[0] = reg;
+               data[1] = (cache[reg] & 0xff00) >> 8;
+               data[2] = cache[reg] & 0x00ff;
+               if (codec->hw_write(codec->control_data, data, 3) != 3)
+                       dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
+                               __func__, reg);
+       }
+}
+
+static int uda1380_reset(struct snd_soc_codec *codec)
+{
+       struct uda1380_platform_data *pdata = codec->dev->platform_data;
+
+       if (gpio_is_valid(pdata->gpio_reset)) {
+               gpio_set_value(pdata->gpio_reset, 1);
+               mdelay(1);
+               gpio_set_value(pdata->gpio_reset, 0);
+       } else {
+               u8 data[3];
+
+               data[0] = UDA1380_RESET;
+               data[1] = 0;
+               data[2] = 0;
+
+               if (codec->hw_write(codec->control_data, data, 3) != 3) {
+                       dev_err(codec->dev, "%s: failed\n", __func__);
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
 
 static void uda1380_flush_work(struct work_struct *work)
 {
+       struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work);
+       struct snd_soc_codec *uda1380_codec = uda1380->codec;
        int bit, reg;
 
        for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
@@ -145,6 +185,7 @@ static void uda1380_flush_work(struct work_struct *work)
                                uda1380_read_reg_cache(uda1380_codec, reg));
                clear_bit(bit, &uda1380_cache_dirty);
        }
+
 }
 
 /* declarations of ALSA reg_elem_REAL controls */
@@ -474,8 +515,7 @@ static int uda1380_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_device *socdev = rtd->socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
        struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
        int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
 
@@ -501,8 +541,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
                                 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 snd_soc_codec *codec = rtd->codec;
        u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
 
        /* set WSPLL power and divider if running from this clock */
@@ -540,8 +579,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
                                 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 snd_soc_codec *codec = rtd->codec;
        u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
 
        /* shut down WSPLL power if running from this clock */
@@ -562,18 +600,41 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
        int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
+       int reg;
+       struct uda1380_platform_data *pdata = codec->dev->platform_data;
+
+       if (codec->bias_level == level)
+               return 0;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
+               /* ADC, DAC on */
                uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
                break;
        case SND_SOC_BIAS_STANDBY:
-               uda1380_write(codec, UDA1380_PM, R02_PON_BIAS);
-               break;
-       case SND_SOC_BIAS_OFF:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       if (gpio_is_valid(pdata->gpio_power)) {
+                               gpio_set_value(pdata->gpio_power, 1);
+                               mdelay(1);
+                               uda1380_reset(codec);
+                       }
+
+                       uda1380_sync_cache(codec);
+               }
                uda1380_write(codec, UDA1380_PM, 0x0);
                break;
+       case SND_SOC_BIAS_OFF:
+               if (!gpio_is_valid(pdata->gpio_power))
+                       break;
+
+               gpio_set_value(pdata->gpio_power, 0);
+
+               /* Mark mixer regs cache dirty to sync them with
+                * codec regs on power on.
+                */
+               for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++)
+                       set_bit(reg - 0x10, &uda1380_cache_dirty);
        }
        codec->bias_level = level;
        return 0;
@@ -604,9 +665,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
        .set_fmt        = uda1380_set_dai_fmt_capture,
 };
 
-struct snd_soc_dai uda1380_dai[] = {
+static struct snd_soc_dai_driver uda1380_dai[] = {
 {
-       .name = "UDA1380",
+       .name = "uda1380-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -622,7 +683,7 @@ struct snd_soc_dai uda1380_dai[] = {
        .ops = &uda1380_dai_ops,
 },
 { /* playback only - dual interface */
-       .name = "UDA1380",
+       .name = "uda1380-hifi-playback",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -633,7 +694,7 @@ struct snd_soc_dai uda1380_dai[] = {
        .ops = &uda1380_dai_ops_playback,
 },
 { /* capture only - dual interface*/
-       .name = "UDA1380",
+       .name = "uda1380-hifi-capture",
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
@@ -644,67 +705,69 @@ struct snd_soc_dai uda1380_dai[] = {
        .ops = &uda1380_dai_ops_capture,
 },
 };
-EXPORT_SYMBOL_GPL(uda1380_dai);
 
-static int uda1380_suspend(struct platform_device *pdev, pm_message_t state)
+static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int uda1380_resume(struct platform_device *pdev)
+static int uda1380_resume(struct snd_soc_codec *codec)
 {
-       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(uda1380_reg); i++) {
-               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
-       }
        uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
 
-static int uda1380_probe(struct platform_device *pdev)
+static int uda1380_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct uda1380_platform_data *pdata;
-       int ret = 0;
+       struct uda1380_platform_data *pdata =codec->dev->platform_data;
+       struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       if (uda1380_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
+       uda1380->codec = codec;
+
+       codec->hw_write = (hw_write_t)i2c_master_send;
+       codec->control_data = uda1380->control_data;
+
+       if (!pdata)
+               return -EINVAL;
 
-       socdev->card->codec = uda1380_codec;
-       codec = uda1380_codec;
-       pdata = codec->dev->platform_data;
+       if (gpio_is_valid(pdata->gpio_reset)) {
+               ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
+               if (ret)
+                       goto err_out;
+               ret = gpio_direction_output(pdata->gpio_reset, 0);
+               if (ret)
+                       goto err_gpio_reset_conf;
+       }
 
-       /* 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;
+       if (gpio_is_valid(pdata->gpio_power)) {
+               ret = gpio_request(pdata->gpio_power, "uda1380 power");
+               if (ret)
+                       goto err_gpio;
+               ret = gpio_direction_output(pdata->gpio_power, 0);
+               if (ret)
+                       goto err_gpio_power_conf;
+       } else {
+               ret = uda1380_reset(codec);
+               if (ret) {
+                       dev_err(codec->dev, "Failed to issue reset\n");
+                       goto err_reset;
+               }
        }
 
+       INIT_WORK(&uda1380->work, uda1380_flush_work);
+
        /* power on device */
        uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        /* set clock input */
        switch (pdata->dac_clk) {
        case UDA1380_DAC_CLK_SYSCLK:
-               uda1380_write(codec, UDA1380_CLK, 0);
+               uda1380_write_reg_cache(codec, UDA1380_CLK, 0);
                break;
        case UDA1380_DAC_CLK_WSPLL:
-               uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK);
+               uda1380_write_reg_cache(codec, UDA1380_CLK,
+                       R00_DAC_CLK);
                break;
        }
 
@@ -712,167 +775,73 @@ static int uda1380_probe(struct platform_device *pdev)
                                ARRAY_SIZE(uda1380_snd_controls));
        uda1380_add_widgets(codec);
 
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int uda1380_remove(struct platform_device *pdev)
-{
-       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);
-
        return 0;
-}
-
-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)
-{
-       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);
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, 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;
-
-       memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
-
-       ret = uda1380_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err_reset;
-       }
-
-       INIT_WORK(&uda1380->work, uda1380_flush_work);
 
-       for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
-               uda1380_dai[i].dev = codec->dev;
-
-       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;
-       }
-
-       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;
-       }
-
-       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_power_conf:
+       if (gpio_is_valid(pdata->gpio_power))
+               gpio_free(pdata->gpio_power);
+
+err_gpio_reset_conf:
 err_gpio:
-       gpio_free(pdata->gpio_power);
+       if (gpio_is_valid(pdata->gpio_reset))
+               gpio_free(pdata->gpio_reset);
 err_out:
        return ret;
 }
 
-static void uda1380_unregister(struct uda1380_priv *uda1380)
+/* power down chip */
+static int uda1380_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &uda1380->codec;
-       struct uda1380_platform_data *pdata = codec->dev->platform_data;
+       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);
+       uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-       gpio_set_value(pdata->gpio_power, 0);
        gpio_free(pdata->gpio_reset);
        gpio_free(pdata->gpio_power);
 
-       kfree(uda1380);
-       uda1380_codec = NULL;
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
+       .probe =        uda1380_probe,
+       .remove =       uda1380_remove,
+       .suspend =      uda1380_suspend,
+       .resume =       uda1380_resume,
+       .read =         uda1380_read_reg_cache,
+       .write =        uda1380_write,
+       .set_bias_level = uda1380_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(uda1380_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = uda1380_reg,
+       .reg_cache_step = 1,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct uda1380_priv *uda1380;
-       struct snd_soc_codec *codec;
        int ret;
 
        uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
        if (uda1380 == NULL)
                return -ENOMEM;
 
-       codec = &uda1380->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        i2c_set_clientdata(i2c, uda1380);
-       codec->control_data = i2c;
+       uda1380->control_data = i2c;
 
-       codec->dev = &i2c->dev;
-
-       ret = uda1380_register(uda1380);
-       if (ret != 0)
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai));
+       if (ret < 0)
                kfree(uda1380);
-
        return ret;
 }
 
 static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
 {
-       struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
-       uda1380_unregister(uda1380);
+       snd_soc_unregister_codec(&i2c->dev);
+       kfree(i2c_get_clientdata(i2c));
        return 0;
 }
 
@@ -884,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
 
 static struct i2c_driver uda1380_i2c_driver = {
        .driver = {
-               .name =  "UDA1380 I2C Codec",
+               .name =  "uda1380-codec",
                .owner = THIS_MODULE,
        },
        .probe =    uda1380_i2c_probe,
index 9cefa8a..942e392 100644 (file)
@@ -76,7 +76,4 @@
 #define UDA1380_DAI_PLAYBACK   1 /* playback DAI */
 #define UDA1380_DAI_CAPTURE    2 /* capture DAI */
 
-extern struct snd_soc_dai uda1380_dai[3];
-extern struct snd_soc_codec_device soc_codec_dev_uda1380;
-
 #endif /* _UDA1380_H */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
new file mode 100644 (file)
index 0000000..0c47c78
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * ALSA SoC WL1273 codec driver
+ *
+ * Author:      Matti Aaltonen, <matti.j.aaltonen@nokia.com>
+ *
+ * Copyright:   (C) 2010 Nokia Corporation
+ *
+ * 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 <linux/mfd/wl1273-core.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-dai.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "wl1273.h"
+
+enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX };
+
+/* codec private data */
+struct wl1273_priv {
+       enum wl1273_mode mode;
+       struct wl1273_core *core;
+       unsigned int channels;
+};
+
+static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core,
+                                     int rate, int width)
+{
+       struct device *dev = &core->i2c_dev->dev;
+       int r = 0;
+       u16 mode;
+
+       dev_dbg(dev, "rate: %d\n", rate);
+       dev_dbg(dev, "width: %d\n", width);
+
+       mutex_lock(&core->lock);
+
+       mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE;
+
+       switch (rate) {
+       case 48000:
+               mode |= WL1273_IS2_RATE_48K;
+               break;
+       case 44100:
+               mode |= WL1273_IS2_RATE_44_1K;
+               break;
+       case 32000:
+               mode |= WL1273_IS2_RATE_32K;
+               break;
+       case 22050:
+               mode |= WL1273_IS2_RATE_22_05K;
+               break;
+       case 16000:
+               mode |= WL1273_IS2_RATE_16K;
+               break;
+       case 12000:
+               mode |= WL1273_IS2_RATE_12K;
+               break;
+       case 11025:
+               mode |= WL1273_IS2_RATE_11_025;
+               break;
+       case 8000:
+               mode |= WL1273_IS2_RATE_8K;
+               break;
+       default:
+               dev_err(dev, "Sampling rate: %d not supported\n", rate);
+               r = -EINVAL;
+               goto out;
+       }
+
+       switch (width) {
+       case 16:
+               mode |= WL1273_IS2_WIDTH_32;
+               break;
+       case 20:
+               mode |= WL1273_IS2_WIDTH_40;
+               break;
+       case 24:
+               mode |= WL1273_IS2_WIDTH_48;
+               break;
+       case 25:
+               mode |= WL1273_IS2_WIDTH_50;
+               break;
+       case 30:
+               mode |= WL1273_IS2_WIDTH_60;
+               break;
+       case 32:
+               mode |= WL1273_IS2_WIDTH_64;
+               break;
+       case 40:
+               mode |= WL1273_IS2_WIDTH_80;
+               break;
+       case 48:
+               mode |= WL1273_IS2_WIDTH_96;
+               break;
+       case 64:
+               mode |= WL1273_IS2_WIDTH_128;
+               break;
+       default:
+               dev_err(dev, "Data width: %d not supported\n", width);
+               r = -EINVAL;
+               goto out;
+       }
+
+       dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n",  WL1273_I2S_DEF_MODE);
+       dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode);
+       dev_dbg(dev, "mode: 0x%04x\n", mode);
+
+       if (core->i2s_mode != mode) {
+               r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, mode);
+               if (r)
+                       goto out;
+
+               core->i2s_mode = mode;
+               r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+                                       WL1273_AUDIO_ENABLE_I2S);
+               if (r)
+                       goto out;
+       }
+out:
+       mutex_unlock(&core->lock);
+
+       return r;
+}
+
+static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core,
+                                           int channel_number)
+{
+       struct i2c_client *client = core->i2c_dev;
+       struct device *dev = &client->dev;
+       int r = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       mutex_lock(&core->lock);
+
+       if (core->channel_number == channel_number)
+               goto out;
+
+       if (channel_number == 1 && core->mode == WL1273_MODE_RX)
+               r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+                                       WL1273_RX_MONO);
+       else if (channel_number == 1 && core->mode == WL1273_MODE_TX)
+               r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
+                                       WL1273_TX_MONO);
+       else if (channel_number == 2 && core->mode == WL1273_MODE_RX)
+               r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
+                                       WL1273_RX_STEREO);
+       else if (channel_number == 2 && core->mode == WL1273_MODE_TX)
+               r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
+                                       WL1273_TX_STEREO);
+       else
+               r = -EINVAL;
+out:
+       mutex_unlock(&core->lock);
+
+       return r;
+}
+
+static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.integer.value[0] = wl1273->mode;
+
+       return 0;
+}
+
+static const char *wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
+
+static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       if (wl1273->mode == ucontrol->value.integer.value[0])
+               return 0;
+
+       /* Do not allow changes while stream is running */
+       if (codec->active)
+               return -EPERM;
+
+       if (ucontrol->value.integer.value[0] < 0 ||
+           ucontrol->value.integer.value[0] >=  ARRAY_SIZE(wl1273_audio_route))
+               return -EINVAL;
+
+       wl1273->mode = ucontrol->value.integer.value[0];
+
+       return 1;
+}
+
+static const struct soc_enum wl1273_enum =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route);
+
+static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+       ucontrol->value.integer.value[0] = wl1273->core->audio_mode;
+
+       return 0;
+}
+
+static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+       int val, r = 0;
+
+       dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+       val = ucontrol->value.integer.value[0];
+       if (wl1273->core->audio_mode == val)
+               return 0;
+
+       r = wl1273_fm_set_audio(wl1273->core, val);
+       if (r < 0)
+               return r;
+
+       return 1;
+}
+
+static const char *wl1273_audio_strings[] = { "Digital", "Analog" };
+
+static const struct soc_enum wl1273_audio_enum =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings),
+                           wl1273_audio_strings);
+
+static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+       ucontrol->value.integer.value[0] = wl1273->core->volume;
+
+       return 0;
+}
+
+static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
+                                   struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+       int r;
+
+       dev_dbg(codec->dev, "%s: enter.\n", __func__);
+
+       r = wl1273_fm_set_volume(wl1273->core,
+                                ucontrol->value.integer.value[0]);
+       if (r)
+               return r;
+
+       return 1;
+}
+
+static const struct snd_kcontrol_new wl1273_controls[] = {
+       SOC_ENUM_EXT("Codec Mode", wl1273_enum,
+                    snd_wl1273_get_audio_route, snd_wl1273_set_audio_route),
+       SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum,
+                    snd_wl1273_fm_audio_get,  snd_wl1273_fm_audio_put),
+       SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0,
+                      snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
+};
+
+static int wl1273_startup(struct snd_pcm_substream *substream,
+                         struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       switch (wl1273->mode) {
+       case WL1273_MODE_BT:
+               snd_pcm_hw_constraint_minmax(substream->runtime,
+                                            SNDRV_PCM_HW_PARAM_RATE,
+                                            8000, 8000);
+               snd_pcm_hw_constraint_minmax(substream->runtime,
+                                            SNDRV_PCM_HW_PARAM_CHANNELS, 1, 1);
+               break;
+       case WL1273_MODE_FM_RX:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       pr_err("Cannot play in RX mode.\n");
+                       return -EINVAL;
+               }
+               break;
+       case WL1273_MODE_FM_TX:
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+                       pr_err("Cannot capture in TX mode.\n");
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+
+       return 0;
+}
+
+static int wl1273_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 wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec);
+       struct wl1273_core *core = wl1273->core;
+       unsigned int rate, width, r;
+
+       if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
+               pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n");
+               return -EINVAL;
+       }
+
+       rate = params_rate(params);
+       width =  hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+
+       if (wl1273->mode == WL1273_MODE_BT) {
+               if (rate != 8000) {
+                       pr_err("Rate %d not supported.\n", params_rate(params));
+                       return -EINVAL;
+               }
+
+               if (params_channels(params) != 1) {
+                       pr_err("Only mono supported.\n");
+                       return -EINVAL;
+               }
+
+               return 0;
+       }
+
+       if (wl1273->mode == WL1273_MODE_FM_TX &&
+           substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+               pr_err("Only playback supported with TX.\n");
+               return -EINVAL;
+       }
+
+       if (wl1273->mode == WL1273_MODE_FM_RX  &&
+           substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               pr_err("Only capture supported with RX.\n");
+               return -EINVAL;
+       }
+
+       if (wl1273->mode != WL1273_MODE_FM_RX  &&
+           wl1273->mode != WL1273_MODE_FM_TX) {
+               pr_err("Unexpected mode: %d.\n", wl1273->mode);
+               return -EINVAL;
+       }
+
+       r = snd_wl1273_fm_set_i2s_mode(core, rate, width);
+       if (r)
+               return r;
+
+       wl1273->channels = params_channels(params);
+       r = snd_wl1273_fm_set_channel_number(core, wl1273->channels);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static struct snd_soc_dai_ops wl1273_dai_ops = {
+       .startup        = wl1273_startup,
+       .hw_params      = wl1273_hw_params,
+};
+
+static struct snd_soc_dai_driver wl1273_dai = {
+       .name = "wl1273-fm",
+       .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 = &wl1273_dai_ops,
+};
+
+/* Audio interface format for the soc_card driver */
+int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt)
+{
+       struct wl1273_priv *wl1273;
+
+       if (codec == NULL || fmt == NULL)
+               return -EINVAL;
+
+       wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       switch (wl1273->mode) {
+       case WL1273_MODE_FM_RX:
+       case WL1273_MODE_FM_TX:
+               *fmt =  SND_SOC_DAIFMT_I2S |
+                       SND_SOC_DAIFMT_NB_NF |
+                       SND_SOC_DAIFMT_CBM_CFM;
+
+               break;
+       case WL1273_MODE_BT:
+               *fmt =  SND_SOC_DAIFMT_DSP_A |
+                       SND_SOC_DAIFMT_IB_NF |
+                       SND_SOC_DAIFMT_CBM_CFM;
+
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wl1273_get_format);
+
+static int wl1273_probe(struct snd_soc_codec *codec)
+{
+       struct wl1273_core **core = codec->dev->platform_data;
+       struct wl1273_priv *wl1273;
+       int r;
+
+       dev_dbg(codec->dev, "%s.\n", __func__);
+
+       if (!core) {
+               dev_err(codec->dev, "Platform data is missing.\n");
+               return -EINVAL;
+       }
+
+       wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
+       if (wl1273 == NULL) {
+               dev_err(codec->dev, "Cannot allocate memory.\n");
+               return -ENOMEM;
+       }
+
+       wl1273->mode = WL1273_MODE_BT;
+       wl1273->core = *core;
+
+       snd_soc_codec_set_drvdata(codec, wl1273);
+       mutex_init(&codec->mutex);
+
+       r = snd_soc_add_controls(codec, wl1273_controls,
+                                ARRAY_SIZE(wl1273_controls));
+       if (r)
+               kfree(wl1273);
+
+       return r;
+}
+
+static int wl1273_remove(struct snd_soc_codec *codec)
+{
+       struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "%s\n", __func__);
+       kfree(wl1273);
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
+       .probe = wl1273_probe,
+       .remove = wl1273_remove,
+};
+
+static int __devinit wl1273_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
+                                     &wl1273_dai, 1);
+}
+
+static int __devexit wl1273_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+MODULE_ALIAS("platform:wl1273-codec");
+
+static struct platform_driver wl1273_platform_driver = {
+       .driver         = {
+               .name   = "wl1273-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wl1273_platform_probe,
+       .remove         = __devexit_p(wl1273_platform_remove),
+};
+
+static int __init wl1273_init(void)
+{
+       return platform_driver_register(&wl1273_platform_driver);
+}
+module_init(wl1273_init);
+
+static void __exit wl1273_exit(void)
+{
+       platform_driver_unregister(&wl1273_platform_driver);
+}
+module_exit(wl1273_exit);
+
+MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
+MODULE_DESCRIPTION("ASoC WL1273 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wl1273.h b/sound/soc/codecs/wl1273.h
new file mode 100644 (file)
index 0000000..14ed027
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * sound/soc/codec/wl1273.h
+ *
+ * ALSA SoC WL1273 codec driver
+ *
+ * Copyright (C) Nokia Corporation
+ * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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
+ *
+ */
+
+#ifndef __WL1273_CODEC_H__
+#define __WL1273_CODEC_H__
+
+/* I2S protocol, left channel first, data width 16 bits */
+#define WL1273_PCM_DEF_MODE            0x00
+
+/* Rx */
+#define WL1273_AUDIO_ENABLE_I2S                (1 << 0)
+#define WL1273_AUDIO_ENABLE_ANALOG     (1 << 1)
+
+/* Tx */
+#define WL1273_AUDIO_IO_SET_ANALOG     0
+#define WL1273_AUDIO_IO_SET_I2S                1
+
+#define WL1273_POWER_SET_OFF           0
+#define WL1273_POWER_SET_FM            (1 << 0)
+#define WL1273_POWER_SET_RDS           (1 << 1)
+#define WL1273_POWER_SET_RETENTION     (1 << 4)
+
+#define WL1273_PUPD_SET_OFF            0x00
+#define WL1273_PUPD_SET_ON             0x01
+#define WL1273_PUPD_SET_RETENTION      0x10
+
+/* I2S mode */
+#define WL1273_IS2_WIDTH_32    0x0
+#define WL1273_IS2_WIDTH_40    0x1
+#define WL1273_IS2_WIDTH_22_23 0x2
+#define WL1273_IS2_WIDTH_23_22 0x3
+#define WL1273_IS2_WIDTH_48    0x4
+#define WL1273_IS2_WIDTH_50    0x5
+#define WL1273_IS2_WIDTH_60    0x6
+#define WL1273_IS2_WIDTH_64    0x7
+#define WL1273_IS2_WIDTH_80    0x8
+#define WL1273_IS2_WIDTH_96    0x9
+#define WL1273_IS2_WIDTH_128   0xa
+#define WL1273_IS2_WIDTH       0xf
+
+#define WL1273_IS2_FORMAT_STD  (0x0 << 4)
+#define WL1273_IS2_FORMAT_LEFT (0x1 << 4)
+#define WL1273_IS2_FORMAT_RIGHT        (0x2 << 4)
+#define WL1273_IS2_FORMAT_USER (0x3 << 4)
+
+#define WL1273_IS2_MASTER      (0x0 << 6)
+#define WL1273_IS2_SLAVEW      (0x1 << 6)
+
+#define WL1273_IS2_TRI_AFTER_SENDING   (0x0 << 7)
+#define WL1273_IS2_TRI_ALWAYS_ACTIVE   (0x1 << 7)
+
+#define WL1273_IS2_SDOWS_RR    (0x0 << 8)
+#define WL1273_IS2_SDOWS_RF    (0x1 << 8)
+#define WL1273_IS2_SDOWS_FR    (0x2 << 8)
+#define WL1273_IS2_SDOWS_FF    (0x3 << 8)
+
+#define WL1273_IS2_TRI_OPT     (0x0 << 10)
+#define WL1273_IS2_TRI_ALWAYS  (0x1 << 10)
+
+#define WL1273_IS2_RATE_48K    (0x0 << 12)
+#define WL1273_IS2_RATE_44_1K  (0x1 << 12)
+#define WL1273_IS2_RATE_32K    (0x2 << 12)
+#define WL1273_IS2_RATE_22_05K (0x4 << 12)
+#define WL1273_IS2_RATE_16K    (0x5 << 12)
+#define WL1273_IS2_RATE_12K    (0x8 << 12)
+#define WL1273_IS2_RATE_11_025 (0x9 << 12)
+#define WL1273_IS2_RATE_8K     (0xa << 12)
+#define WL1273_IS2_RATE                (0xf << 12)
+
+#define WL1273_I2S_DEF_MODE    (WL1273_IS2_WIDTH_32 | \
+                                WL1273_IS2_FORMAT_STD | \
+                                WL1273_IS2_MASTER | \
+                                WL1273_IS2_TRI_AFTER_SENDING | \
+                                WL1273_IS2_SDOWS_RR | \
+                                WL1273_IS2_TRI_OPT | \
+                                WL1273_IS2_RATE_48K)
+
+int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt);
+
+#endif /* End of __WL1273_CODEC_H__ */
index c18e261..0b6f056 100644 (file)
@@ -16,9 +16,6 @@ struct wm2000_setup_data {
 
 extern int wm2000_add_controls(struct snd_soc_codec *codec);
 
-extern struct snd_soc_dai wm2000_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm2000;
-
 #define WM2000_REG_SYS_START       0x8000
 #define WM2000_REG_SPEECH_CLARITY   0x8fef
 #define WM2000_REG_SYS_WATCHDOG     0x8ff6
index 0221ca7..f4f1fba 100644 (file)
@@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm8350_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8350_resume(struct platform_device *pdev)
+static int wm8350_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
 
-static struct snd_soc_codec *wm8350_codec;
+#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
+
+#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                       SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8350_dai_ops = {
+        .hw_params     = wm8350_pcm_hw_params,
+        .digital_mute  = wm8350_mute,
+        .trigger       = wm8350_pcm_trigger,
+        .set_fmt       = wm8350_set_dai_fmt,
+        .set_sysclk    = wm8350_set_dai_sysclk,
+        .set_pll       = wm8350_set_fll,
+        .set_clkdiv    = wm8350_set_clkdiv,
+};
+
+static struct snd_soc_dai_driver wm8350_dai = {
+       .name = "wm8350-hifi",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8350_RATES,
+               .formats = WM8350_FORMATS,
+       },
+       .capture = {
+                .stream_name = "Capture",
+                .channels_min = 1,
+                .channels_max = 2,
+                .rates = WM8350_RATES,
+                .formats = WM8350_FORMATS,
+        },
+       .ops = &wm8350_dai_ops,
+};
 
-static int wm8350_probe(struct platform_device *pdev)
+static  int wm8350_codec_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct wm8350 *wm8350;
+       struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
        struct wm8350_data *priv;
-       int ret;
        struct wm8350_output *out1;
        struct wm8350_output *out2;
+       int ret, i;
 
-       BUG_ON(!wm8350_codec);
+       if (wm8350->codec.platform_data == NULL) {
+               dev_err(codec->dev, "No audio platform data supplied\n");
+               return -EINVAL;
+       }
+
+       priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+       if (priv == NULL)
+               return -ENOMEM;
+       snd_soc_codec_set_drvdata(codec, priv);
+
+       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+               priv->supplies[i].supply = supply_names[i];
+
+       ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
+                                priv->supplies);
+       if (ret != 0)
+               goto err_priv;
+
+       wm8350->codec.codec = codec;
+       codec->control_data = wm8350;
 
-       socdev->card->codec = wm8350_codec;
-       codec = socdev->card->codec;
-       wm8350 = codec->control_data;
-       priv = snd_soc_codec_get_drvdata(codec);
+       /* Put the codec into reset if it wasn't already */
+       wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
+
+       INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
 
        /* Enable the codec */
        wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev)
        wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
                            wm8350_mic_handler, 0, "Microphone detect", priv);
 
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to create pcms\n");
-               return ret;
-       }
 
        snd_soc_add_controls(codec, wm8350_snd_controls,
                                ARRAY_SIZE(wm8350_snd_controls));
@@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev)
        wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
+
+err_priv:
+       kfree(priv);
+       return ret;
 }
 
-static int wm8350_remove(struct platform_device *pdev)
+static int  wm8350_codec_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-       struct wm8350 *wm8350 = codec->control_data;
        struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
+       struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
        int ret;
 
        wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
@@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev)
 
        wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
 
+       regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
+       kfree(priv);
        return 0;
 }
 
-#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
-
-#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
-                       SNDRV_PCM_FMTBIT_S20_3LE |\
-                       SNDRV_PCM_FMTBIT_S24_LE)
-
-static struct snd_soc_dai_ops wm8350_dai_ops = {
-        .hw_params     = wm8350_pcm_hw_params,
-        .digital_mute  = wm8350_mute,
-        .trigger       = wm8350_pcm_trigger,
-        .set_fmt       = wm8350_set_dai_fmt,
-        .set_sysclk    = wm8350_set_dai_sysclk,
-        .set_pll       = wm8350_set_fll,
-        .set_clkdiv    = wm8350_set_clkdiv,
-};
-
-struct snd_soc_dai wm8350_dai = {
-       .name = "WM8350",
-       .playback = {
-               .stream_name = "Playback",
-               .channels_min = 1,
-               .channels_max = 2,
-               .rates = WM8350_RATES,
-               .formats = WM8350_FORMATS,
-       },
-       .capture = {
-                .stream_name = "Capture",
-                .channels_min = 1,
-                .channels_max = 2,
-                .rates = WM8350_RATES,
-                .formats = WM8350_FORMATS,
-        },
-       .ops = &wm8350_dai_ops,
-};
-EXPORT_SYMBOL_GPL(wm8350_dai);
-
-struct snd_soc_codec_device soc_codec_dev_wm8350 = {
-       .probe =        wm8350_probe,
-       .remove =       wm8350_remove,
+static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
+       .probe =        wm8350_codec_probe,
+       .remove =       wm8350_codec_remove,
        .suspend =      wm8350_suspend,
        .resume =       wm8350_resume,
+       .read = wm8350_codec_read,
+       .write = wm8350_codec_write,
+       .set_bias_level = wm8350_set_bias_level,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
 
-static __devinit int wm8350_codec_probe(struct platform_device *pdev)
+static int __devinit wm8350_probe(struct platform_device *pdev)
 {
-       struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-       struct wm8350_data *priv;
-       struct snd_soc_codec *codec;
-       int ret, i;
-
-       if (wm8350->codec.platform_data == NULL) {
-               dev_err(&pdev->dev, "No audio platform data supplied\n");
-               return -EINVAL;
-       }
-
-       priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
-       if (priv == NULL)
-               return -ENOMEM;
-
-       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
-               priv->supplies[i].supply = supply_names[i];
-
-       ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
-                                priv->supplies);
-       if (ret != 0)
-               goto err_priv;
-
-       codec = &priv->codec;
-       wm8350->codec.codec = codec;
-
-       wm8350_dai.dev = &pdev->dev;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       codec->dev = &pdev->dev;
-       codec->name = "WM8350";
-       codec->owner = THIS_MODULE;
-       codec->read = wm8350_codec_read;
-       codec->write = wm8350_codec_write;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8350_set_bias_level;
-       codec->dai = &wm8350_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8350_MAX_REGISTER;
-       snd_soc_codec_set_drvdata(codec, priv);
-       codec->control_data = wm8350;
-
-       /* Put the codec into reset if it wasn't already */
-       wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
-
-       INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0)
-               goto err_supply;
-
-       wm8350_codec = codec;
-
-       ret = snd_soc_register_dai(&wm8350_dai);
-       if (ret != 0)
-               goto err_codec;
-       return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err_supply:
-       regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-err_priv:
-       kfree(priv);
-       wm8350_codec = NULL;
-       return ret;
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
+                       &wm8350_dai, 1);
 }
 
-static int __devexit wm8350_codec_remove(struct platform_device *pdev)
+static int __devexit wm8350_remove(struct platform_device *pdev)
 {
-       struct wm8350 *wm8350 = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = wm8350->codec.codec;
-       struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
-
-       snd_soc_unregister_dai(&wm8350_dai);
-       snd_soc_unregister_codec(codec);
-       regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
-       kfree(priv);
-       wm8350_codec = NULL;
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
@@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = {
                   .name = "wm8350-codec",
                   .owner = THIS_MODULE,
                   },
-       .probe = wm8350_codec_probe,
-       .remove = __devexit_p(wm8350_codec_remove),
+       .probe = wm8350_probe,
+       .remove = __devexit_p(wm8350_remove),
 };
 
 static __init int wm8350_init(void)
index 9ed0467..74108eb 100644 (file)
@@ -15,9 +15,6 @@
 #include <sound/soc.h>
 #include <linux/mfd/wm8350/audio.h>
 
-extern struct snd_soc_dai wm8350_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8350;
-
 enum wm8350_jack {
        WM8350_JDL = 1,
        WM8350_JDR = 2,
index 8f29406..8502997 100644 (file)
@@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = {
 
 /* codec private data */
 struct wm8400_priv {
-       struct snd_soc_codec codec;
+       struct snd_soc_codec *codec;
        struct wm8400 *wm8400;
        u16 fake_register;
        unsigned int sysclk;
@@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
 
        audio1 &= ~WM8400_AIF_WL_MASK;
@@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = {
  * 1. ADC/DAC on Primary Interface
  * 2. ADC on Primary Interface/DAC on secondary
  */
-struct snd_soc_dai wm8400_dai = {
+static struct snd_soc_dai_driver wm8400_dai = {
 /* ADC/DAC on primary */
-       .name = "WM8400 ADC/DAC Primary",
-       .id = 1,
+       .name = "wm8400-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = {
        },
        .ops = &wm8400_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8400_dai);
 
-static int wm8400_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8400_resume(struct platform_device *pdev)
+static int wm8400_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
 
-static struct snd_soc_codec *wm8400_codec;
-
-static int wm8400_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret;
-
-       if (!wm8400_codec) {
-               dev_err(&pdev->dev, "wm8400 not yet discovered\n");
-               return -ENODEV;
-       }
-       codec = wm8400_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;
-       }
-
-       wm8400_add_controls(codec);
-       wm8400_add_widgets(codec);
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8400_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_wm8400 = {
-       .probe =        wm8400_probe,
-       .remove =       wm8400_remove,
-       .suspend =      wm8400_suspend,
-       .resume =       wm8400_resume,
-};
-
 static void wm8400_probe_deferred(struct work_struct *work)
 {
        struct wm8400_priv *priv = container_of(work, struct wm8400_priv,
                                                work);
-       struct snd_soc_codec *codec = &priv->codec;
-       int ret;
+       struct snd_soc_codec *codec = priv->codec;
 
        /* charge output caps */
        wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       /* We're done, tell the subsystem. */
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(priv->wm8400->dev,
-                       "Failed to register codec: %d\n", ret);
-               goto err;
-       }
-
-       ret = snd_soc_register_dai(&wm8400_dai);
-       if (ret != 0) {
-               dev_err(priv->wm8400->dev,
-                       "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
-
-       return;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
 
-static int wm8400_codec_probe(struct platform_device *dev)
+static int wm8400_codec_probe(struct snd_soc_codec *codec)
 {
+       struct wm8400 *wm8400 = dev_get_platdata(codec->dev);
        struct wm8400_priv *priv;
        int ret;
        u16 reg;
-       struct snd_soc_codec *codec;
 
        priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
 
-       codec = &priv->codec;
        snd_soc_codec_set_drvdata(codec, priv);
-       codec->control_data = dev_get_drvdata(&dev->dev);
-       priv->wm8400 = dev_get_drvdata(&dev->dev);
+       codec->control_data = priv->wm8400 = wm8400;
+       priv->codec = codec;
 
-       ret = regulator_bulk_get(priv->wm8400->dev,
+       ret = regulator_bulk_get(wm8400->dev,
                                 ARRAY_SIZE(power), &power[0]);
        if (ret != 0) {
-               dev_err(&dev->dev, "Failed to get regulators: %d\n", ret);
+               dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
                goto err;
        }
 
-       codec->dev = &dev->dev;
-       wm8400_dai.dev = &dev->dev;
-
-       codec->name = "WM8400";
-       codec->owner = THIS_MODULE;
-       codec->read = wm8400_read;
-       codec->write = wm8400_write;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8400_set_bias_level;
-       codec->dai = &wm8400_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8400_REGISTER_COUNT;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
        INIT_WORK(&priv->work, wm8400_probe_deferred);
 
        wm8400_codec_reset(codec);
@@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev)
        wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
        wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
-       wm8400_codec = codec;
-
        if (!schedule_work(&priv->work)) {
                ret = -EINVAL;
                goto err_regulator;
        }
-
+       wm8400_add_controls(codec);
+       wm8400_add_widgets(codec);
        return 0;
 
 err_regulator:
-       wm8400_codec = NULL;
        regulator_bulk_free(ARRAY_SIZE(power), power);
 err:
        kfree(priv);
        return ret;
 }
 
-static int __exit wm8400_codec_remove(struct platform_device *dev)
+static int  wm8400_codec_remove(struct snd_soc_codec *codec)
 {
-       struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec);
+       struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);
        u16 reg;
 
-       snd_soc_unregister_dai(&wm8400_dai);
-       snd_soc_unregister_codec(wm8400_codec);
-
-       reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1);
-       wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1,
+       reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
+       wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
                     reg & (~WM8400_CODEC_ENA));
 
        regulator_bulk_free(ARRAY_SIZE(power), power);
        kfree(priv);
 
-       wm8400_codec = NULL;
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
+       .probe =        wm8400_codec_probe,
+       .remove =       wm8400_codec_remove,
+       .suspend =      wm8400_suspend,
+       .resume =       wm8400_resume,
+       .read = wm8400_read,
+       .write = wm8400_write,
+       .set_bias_level = wm8400_set_bias_level,
+};
+
+static int __devinit wm8400_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
+                       &wm8400_dai, 1);
+}
 
+static int __devexit wm8400_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver wm8400_codec_driver = {
        .driver = {
-               .name = "wm8400-codec",
-               .owner = THIS_MODULE,
-       },
-       .probe = wm8400_codec_probe,
-       .remove = __exit_p(wm8400_codec_remove),
+                  .name = "wm8400-codec",
+                  .owner = THIS_MODULE,
+                  },
+       .probe = wm8400_probe,
+       .remove = __devexit_p(wm8400_remove),
 };
 
-static int __init wm8400_codec_init(void)
+static __init int wm8400_init(void)
 {
        return platform_driver_register(&wm8400_codec_driver);
 }
-module_init(wm8400_codec_init);
+module_init(wm8400_init);
 
-static void __exit wm8400_codec_exit(void)
+static __exit void wm8400_exit(void)
 {
        platform_driver_unregister(&wm8400_codec_driver);
 }
-module_exit(wm8400_codec_exit);
-
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400);
+module_exit(wm8400_exit);
 
 MODULE_DESCRIPTION("ASoC WM8400 driver");
 MODULE_AUTHOR("Mark Brown");
index 79c5934..521adb1 100644 (file)
@@ -56,7 +56,4 @@
 #define WM8400_BCLK_DIV_44                      (0xE << 1)
 #define WM8400_BCLK_DIV_48                      (0xF << 1)
 
-extern struct snd_soc_dai wm8400_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8400;
-
 #endif
index 0f7bcb6..8f10709 100644 (file)
 
 #include "wm8510.h"
 
-#define WM8510_VERSION "0.6"
-
-struct snd_soc_codec_device soc_codec_dev_wm8510;
-
 /*
  * wm8510 register cache
  * We can't read the WM8510 register space when we are
@@ -61,6 +57,11 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
 
 #define wm8510_reset(c)        snd_soc_write(c, WM8510_RESET, 0)
 
+/* codec private data */
+struct wm8510_priv {
+       enum snd_soc_control_type control_type;
+};
+
 static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
 static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
 static const char *wm8510_alc[] = { "ALC", "Limiter" };
@@ -403,8 +404,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
        u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
        u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
 
@@ -514,8 +514,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = {
        .set_pll        = wm8510_set_dai_pll,
 };
 
-struct snd_soc_dai wm8510_dai = {
-       .name = "WM8510 HiFi",
+static struct snd_soc_dai_driver wm8510_dai = {
+       .name = "wm8510-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -531,21 +531,15 @@ struct snd_soc_dai wm8510_dai = {
        .ops = &wm8510_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8510_dai);
 
-static int wm8510_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8510_resume(struct platform_device *pdev)
+static int wm8510_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -561,256 +555,158 @@ static int wm8510_resume(struct platform_device *pdev)
        return 0;
 }
 
-/*
- * 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_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret = 0;
-
-       codec->name = "WM8510";
-       codec->owner = THIS_MODULE;
-       codec->set_bias_level = wm8510_set_bias_level;
-       codec->dai = &wm8510_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
-       codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
-
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9,  wm8510->control_type);
        if (ret < 0) {
-               printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
-                      ret);
-               goto err;
+               printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
        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;
-       }
-
        /* power on device */
-       codec->bias_level = SND_SOC_BIAS_OFF;
        wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        snd_soc_add_controls(codec, wm8510_snd_controls,
                                ARRAY_SIZE(wm8510_snd_controls));
        wm8510_add_widgets(codec);
 
        return ret;
-
-err:
-       kfree(codec->reg_cache);
-       return ret;
 }
 
-static struct snd_soc_device *wm8510_socdev;
+/* power down chip */
+static int wm8510_remove(struct snd_soc_codec *codec)
+{
+       struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       kfree(wm8510);
+       return 0;
+}
 
-/*
- * WM8510 2 wire address is 0x1a
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
+       .probe =        wm8510_probe,
+       .remove =       wm8510_remove,
+       .suspend =      wm8510_suspend,
+       .resume =       wm8510_resume,
+       .set_bias_level = wm8510_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8510_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default =wm8510_reg,
+};
 
-static int wm8510_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8510_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_device *socdev = wm8510_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8510_priv *wm8510;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
+       if (wm8510 == NULL)
+               return -ENOMEM;
 
-       ret = wm8510_init(socdev, SND_SOC_I2C);
-       if (ret < 0)
-               pr_err("failed to initialise WM8510\n");
+       wm8510->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8510);
 
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8510, &wm8510_dai, 1);
+       if (ret < 0)
+               kfree(wm8510);
        return ret;
 }
 
-static int wm8510_i2c_remove(struct i2c_client *client)
+static int __devexit wm8510_spi_remove(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&spi->dev);
        return 0;
 }
 
-static const struct i2c_device_id wm8510_i2c_id[] = {
-       { "wm8510", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
-
-static struct i2c_driver wm8510_i2c_driver = {
+static struct spi_driver wm8510_spi_driver = {
        .driver = {
-               .name = "WM8510 I2C Codec",
-               .owner = THIS_MODULE,
+               .name   = "wm8510",
+               .owner  = THIS_MODULE,
        },
-       .probe =    wm8510_i2c_probe,
-       .remove =   wm8510_i2c_remove,
-       .id_table = wm8510_i2c_id,
+       .probe          = wm8510_spi_probe,
+       .remove         = __devexit_p(wm8510_spi_remove),
 };
+#endif /* CONFIG_SPI_MASTER */
 
-static int wm8510_add_i2c_device(struct platform_device *pdev,
-                                const struct wm8510_setup_data *setup)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
+       struct wm8510_priv *wm8510;
        int ret;
 
-       ret = i2c_add_driver(&wm8510_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "wm8510", 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(&wm8510_i2c_driver);
-       return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8510_spi_probe(struct spi_device *spi)
-{
-       struct snd_soc_device *socdev = wm8510_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret;
+       wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
+       if (wm8510 == NULL)
+               return -ENOMEM;
 
-       codec->control_data = spi;
+       i2c_set_clientdata(i2c, wm8510);
+       wm8510->control_type = SND_SOC_I2C;
 
-       ret = wm8510_init(socdev, SND_SOC_SPI);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8510, &wm8510_dai, 1);
        if (ret < 0)
-               dev_err(&spi->dev, "failed to initialise WM8510\n");
-
+               kfree(wm8510);
        return ret;
 }
 
-static int __devexit wm8510_spi_remove(struct spi_device *spi)
+static __devexit int wm8510_i2c_remove(struct i2c_client *client)
 {
+       snd_soc_unregister_codec(&client->dev);
        return 0;
 }
 
-static struct spi_driver wm8510_spi_driver = {
+static const struct i2c_device_id wm8510_i2c_id[] = {
+       { "wm8510", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
+
+static struct i2c_driver wm8510_i2c_driver = {
        .driver = {
-               .name   = "wm8510",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
+               .name = "wm8510-codec",
+               .owner = THIS_MODULE,
        },
-       .probe          = wm8510_spi_probe,
-       .remove         = __devexit_p(wm8510_spi_remove),
+       .probe =    wm8510_i2c_probe,
+       .remove =   __devexit_p(wm8510_i2c_remove),
+       .id_table = wm8510_i2c_id,
 };
-#endif /* CONFIG_SPI_MASTER */
+#endif
 
-static int wm8510_probe(struct platform_device *pdev)
+static int __init wm8510_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct wm8510_setup_data *setup;
-       struct snd_soc_codec *codec;
        int ret = 0;
-
-       pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       wm8510_socdev = socdev;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               ret = wm8510_add_i2c_device(pdev, setup);
+       ret = i2c_add_driver(&wm8510_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
+                      ret);
        }
 #endif
 #if defined(CONFIG_SPI_MASTER)
-       if (setup->spi) {
-               ret = spi_register_driver(&wm8510_spi_driver);
-               if (ret != 0)
-                       printk(KERN_ERR "can't add spi driver");
+       ret = spi_register_driver(&wm8510_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n",
+                      ret);
        }
 #endif
-
-       if (ret != 0)
-               kfree(codec);
        return ret;
 }
+module_init(wm8510_modinit);
 
-/* power down chip */
-static int wm8510_remove(struct platform_device *pdev)
+static void __exit wm8510_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               wm8510_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(&wm8510_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
        spi_unregister_driver(&wm8510_spi_driver);
 #endif
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8510 = {
-       .probe =        wm8510_probe,
-       .remove =       wm8510_remove,
-       .suspend =      wm8510_suspend,
-       .resume =       wm8510_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
-
-static int __init wm8510_modinit(void)
-{
-       return snd_soc_register_dai(&wm8510_dai);
-}
-module_init(wm8510_modinit);
-
-static void __exit wm8510_exit(void)
-{
-       snd_soc_unregister_dai(&wm8510_dai);
 }
 module_exit(wm8510_exit);
 
index bdefcf5..b3e26ed 100644 (file)
@@ -99,7 +99,4 @@ struct wm8510_setup_data {
        unsigned short i2c_address;
 };
 
-extern struct snd_soc_dai wm8510_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8510;
-
 #endif
index 0ad039b..712ef7c 100644 (file)
@@ -30,9 +30,6 @@
 
 #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",
@@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8523_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        u16 reg_cache[WM8523_REGISTER_COUNT];
        struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
        unsigned int sysclk;
@@ -162,8 +159,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
        int i;
        u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
@@ -387,8 +383,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = {
        .set_fmt        = wm8523_set_dai_fmt,
 };
 
-struct snd_soc_dai wm8523_dai = {
-       .name = "WM8523",
+static struct snd_soc_dai_driver wm8523_dai = {
+       .name = "wm8523-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,  /* Mono modes not yet supported */
@@ -398,25 +394,17 @@ struct snd_soc_dai wm8523_dai = {
        },
        .ops = &wm8523_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8523_dai);
 
 #ifdef CONFIG_PM
-static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8523_suspend(struct snd_soc_codec *codec, 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)
+static int wm8523_resume(struct snd_soc_codec *codec)
 {
-       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
@@ -424,93 +412,20 @@ static int wm8523_resume(struct platform_device *pdev)
 #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);
-
-       return ret;
-
-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)
+static int wm8523_probe(struct snd_soc_codec *codec)
 {
-       int ret;
-       struct snd_soc_codec *codec = &wm8523->codec;
-       int i;
-
-       if (wm8523_codec) {
-               dev_err(codec->dev, "Another WM8523 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, 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;
+       struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+       int ret, i;
 
+       codec->hw_write = (hw_write_t)i2c_master_send;
        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);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
@@ -520,7 +435,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,
                                 wm8523->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
@@ -555,8 +470,6 @@ static int wm8523_register(struct wm8523_priv *wm8523,
                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;
@@ -566,69 +479,67 @@ static int wm8523_register(struct wm8523_priv *wm8523,
        /* 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);
-               goto err_enable;
-       }
-
-       ret = snd_soc_register_dai(&wm8523_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+       snd_soc_add_controls(codec, wm8523_snd_controls,
+                            ARRAY_SIZE(wm8523_snd_controls));
+       wm8523_add_widgets(codec);
 
        return 0;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
 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)
+static int wm8523_remove(struct snd_soc_codec *codec)
 {
-       wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
+       struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+
+       wm8523_set_bias_level(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;
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
+       .probe =        wm8523_probe,
+       .remove =       wm8523_remove,
+       .suspend =      wm8523_suspend,
+       .resume =       wm8523_resume,
+       .set_bias_level = wm8523_set_bias_level,
+       .reg_cache_size = WM8523_REGISTER_COUNT,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8523_reg,
+       .volatile_register = wm8523_volatile_register,
+};
+
 #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;
+       int ret;
 
        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;
+       wm8523->control_type = SND_SOC_I2C;
 
-       codec->dev = &i2c->dev;
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8523, &wm8523_dai, 1);
+       if (ret < 0)
+               kfree(wm8523);
+       return ret;
 
-       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);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -640,7 +551,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
 
 static struct i2c_driver wm8523_i2c_driver = {
        .driver = {
-               .name = "WM8523",
+               .name = "wm8523-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8523_i2c_probe,
index 1aa9ce3..4d5b1eb 100644 (file)
 #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
index 72deeab..a2e0ed5 100644 (file)
@@ -94,6 +94,8 @@
 
 #define WM8580_MAX_REGISTER                  0x35
 
+#define WM8580_DACOSR 0x40
+
 /* PLLB4 (register 7h) */
 #define WM8580_PLLB4_MCLKOUTSRC_MASK   0x60
 #define WM8580_PLLB4_MCLKOUTSRC_PLLA   0x20
 
 /* AIF control 1 (registers 9h-bh) */
 #define WM8580_AIF_RATE_MASK       0x7
-#define WM8580_AIF_RATE_128        0x0
-#define WM8580_AIF_RATE_192        0x1
-#define WM8580_AIF_RATE_256        0x2
-#define WM8580_AIF_RATE_384        0x3
-#define WM8580_AIF_RATE_512        0x4
-#define WM8580_AIF_RATE_768        0x5
-#define WM8580_AIF_RATE_1152       0x6
-
 #define WM8580_AIF_BCLKSEL_MASK   0x18
-#define WM8580_AIF_BCLKSEL_64     0x00
-#define WM8580_AIF_BCLKSEL_128    0x08
-#define WM8580_AIF_BCLKSEL_256    0x10
-#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
 
 #define WM8580_AIF_MS             0x20
 
@@ -199,11 +189,12 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8580_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
        u16 reg_cache[WM8580_MAX_REGISTER + 1];
        struct pll_state a;
        struct pll_state b;
+       int sysclk[2];
 };
 
 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
@@ -273,8 +264,8 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
 SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
 SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),
 
-SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0),
-SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
+SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),
+SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
 };
 
 static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
@@ -476,6 +467,10 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        return 0;
 }
 
+static const int wm8580_sysclk_ratios[] = {
+       128, 192, 256, 384, 512, 768, 1152,
+};
+
 /*
  * Set PCM DAI bit size and sample rate.
  */
@@ -484,29 +479,68 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                                 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;
-       u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
+       struct snd_soc_codec *codec = rtd->codec;
+       struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+       u16 paifa = 0;
+       u16 paifb = 0;
+       int i, ratio, osr;
 
-       paifb &= ~WM8580_AIF_LENGTH_MASK;
        /* bit size */
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
+               paifa |= 0x8;
                break;
        case SNDRV_PCM_FORMAT_S20_3LE:
+               paifa |= 0x10;
                paifb |= WM8580_AIF_LENGTH_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
+               paifa |= 0x10;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        case SNDRV_PCM_FORMAT_S32_LE:
+               paifa |= 0x10;
                paifb |= WM8580_AIF_LENGTH_24;
                break;
        default:
                return -EINVAL;
        }
 
-       snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
+       /* Look up the SYSCLK ratio; accept only exact matches */
+       ratio = wm8580->sysclk[dai->id] / params_rate(params);
+       for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
+               if (ratio == wm8580_sysclk_ratios[i])
+                       break;
+       if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
+               dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
+                       wm8580->sysclk[dai->id], params_rate(params));
+               return -EINVAL;
+       }
+       paifa |= i;
+       dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n",
+               wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (ratio) {
+               case 128:
+               case 192:
+                       osr = WM8580_DACOSR;
+                       dev_dbg(codec->dev, "Selecting 64x OSR\n");
+                       break;
+               default:
+                       osr = 0;
+                       dev_dbg(codec->dev, "Selecting 128x OSR\n");
+                       break;
+               }
+
+               snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr);
+       }
+
+       snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id,
+                           WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK,
+                           paifa);
+       snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id,
+                           WM8580_AIF_LENGTH_MASK, paifb);
        return 0;
 }
 
@@ -518,8 +552,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 = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id);
+       aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id);
 
        aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
 
@@ -585,8 +619,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);
+       snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa);
+       snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb);
 
        return 0;
 }
@@ -624,28 +658,6 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                snd_soc_write(codec, WM8580_PLLB4, reg);
                break;
 
-       case WM8580_DAC_CLKSEL:
-               reg = snd_soc_read(codec, WM8580_CLKSEL);
-               reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
-
-               switch (div) {
-               case WM8580_CLKSRC_MCLK:
-                       break;
-
-               case WM8580_CLKSRC_PLLA:
-                       reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
-                       break;
-
-               case WM8580_CLKSRC_PLLB:
-                       reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-               snd_soc_write(codec, WM8580_CLKSEL, reg);
-               break;
-
        case WM8580_CLKOUTSRC:
                reg = snd_soc_read(codec, WM8580_PLLB4);
                reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
@@ -679,6 +691,55 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                            unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+       int sel, sel_mask, sel_shift;
+
+       switch (dai->driver->id) {
+       case WM8580_DAI_PAIFRX:
+               sel_mask = 0x3;
+               sel_shift = 0;
+               break;
+
+       case WM8580_DAI_PAIFTX:
+               sel_mask = 0xc;
+               sel_shift = 2;
+               break;
+
+       default:
+               BUG_ON("Unknown DAI driver ID\n");
+               return -EINVAL;
+       }
+
+       switch (clk_id) {
+       case WM8580_CLKSRC_ADCMCLK:
+               if (dai->id != WM8580_DAI_PAIFTX)
+                       return -EINVAL;
+               sel = 0 << sel_shift;
+               break;
+       case WM8580_CLKSRC_PLLA:
+               sel = 1 << sel_shift;
+               break;
+       case WM8580_CLKSRC_PLLB:
+               sel = 2 << sel_shift;
+               break;
+       case WM8580_CLKSRC_MCLK:
+               sel = 3 << sel_shift;
+               break;
+       default:
+               dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       /* We really should validate PLL settings but not yet */
+       wm8580->sysclk[dai->id] = freq;
+
+       return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
+}
+
 static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
@@ -732,6 +793,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+       .set_sysclk     = wm8580_set_sysclk,
        .hw_params      = wm8580_paif_hw_params,
        .set_fmt        = wm8580_set_paif_dai_fmt,
        .set_clkdiv     = wm8580_set_dai_clkdiv,
@@ -740,16 +802,17 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
 };
 
 static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+       .set_sysclk     = wm8580_set_sysclk,
        .hw_params      = wm8580_paif_hw_params,
        .set_fmt        = wm8580_set_paif_dai_fmt,
        .set_clkdiv     = wm8580_set_dai_clkdiv,
        .set_pll        = wm8580_set_dai_pll,
 };
 
-struct snd_soc_dai wm8580_dai[] = {
+static struct snd_soc_dai_driver wm8580_dai[] = {
        {
-               .name = "WM8580 PAIFRX",
-               .id = 0,
+               .name = "wm8580-hifi-playback",
+               .id     = WM8580_DAI_PAIFRX,
                .playback = {
                        .stream_name = "Playback",
                        .channels_min = 1,
@@ -760,8 +823,8 @@ struct snd_soc_dai wm8580_dai[] = {
                .ops = &wm8580_dai_ops_playback,
        },
        {
-               .name = "WM8580 PAIFTX",
-               .id = 1,
+               .name = "wm8580-hifi-capture",
+               .id     =       WM8580_DAI_PAIFTX,
                .capture = {
                        .stream_name = "Capture",
                        .channels_min = 2,
@@ -772,90 +835,16 @@ struct snd_soc_dai wm8580_dai[] = {
                .ops = &wm8580_dai_ops_capture,
        },
 };
-EXPORT_SYMBOL_GPL(wm8580_dai);
-
-static struct snd_soc_codec *wm8580_codec;
 
-static int wm8580_probe(struct platform_device *pdev)
+static int wm8580_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8580_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8580_codec;
-       codec = wm8580_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, wm8580_snd_controls,
-                            ARRAY_SIZE(wm8580_snd_controls));
-       wm8580_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8580_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_wm8580 = {
-       .probe =        wm8580_probe,
-       .remove =       wm8580_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
-
-static int wm8580_register(struct wm8580_priv *wm8580,
-                          enum snd_soc_control_type control)
-{
-       int ret, i;
-       struct snd_soc_codec *codec = &wm8580->codec;
-
-       if (wm8580_codec) {
-               dev_err(codec->dev, "Another WM8580 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8580);
-       codec->name = "WM8580";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8580_set_bias_level;
-       codec->dai = wm8580_dai;
-       codec->num_dai = ARRAY_SIZE(wm8580_dai);
-       codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
-       codec->reg_cache = &wm8580->reg_cache;
-
-       memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
+       struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0,i;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
@@ -865,7 +854,7 @@ static int wm8580_register(struct wm8580_priv *wm8580,
                                 wm8580->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
@@ -882,74 +871,68 @@ static int wm8580_register(struct wm8580_priv *wm8580,
                goto err_regulator_enable;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
-               wm8580_dai[i].dev = codec->dev;
-
        wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       wm8580_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err_regulator_enable;
-       }
-
-       ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+       snd_soc_add_controls(codec, wm8580_snd_controls,
+                            ARRAY_SIZE(wm8580_snd_controls));
+       wm8580_add_widgets(codec);
 
        return 0;
 
-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;
 }
 
-static void wm8580_unregister(struct wm8580_priv *wm8580)
+/* power down chip */
+static int wm8580_remove(struct snd_soc_codec *codec)
 {
-       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);
+       struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
+
+       wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
        regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
        regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
-       kfree(wm8580);
-       wm8580_codec = NULL;
+
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
+       .probe =        wm8580_probe,
+       .remove =       wm8580_remove,
+       .set_bias_level = wm8580_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8580_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = &wm8580_reg,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static int wm8580_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm8580_priv *wm8580;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
        if (wm8580 == NULL)
                return -ENOMEM;
 
-       codec = &wm8580->codec;
-
        i2c_set_clientdata(i2c, wm8580);
-       codec->control_data = i2c;
+       wm8580->control_type = SND_SOC_I2C;
 
-       codec->dev = &i2c->dev;
-
-       return wm8580_register(wm8580, SND_SOC_I2C);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai));
+       if (ret < 0)
+               kfree(wm8580);
+       return ret;
 }
 
 static int wm8580_i2c_remove(struct i2c_client *client)
 {
-       struct wm8580_priv *wm8580 = i2c_get_clientdata(client);
-       wm8580_unregister(wm8580);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -961,7 +944,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
 
 static struct i2c_driver wm8580_i2c_driver = {
        .driver = {
-               .name = "wm8580",
+               .name = "wm8580-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8580_i2c_probe,
@@ -972,7 +955,7 @@ static struct i2c_driver wm8580_i2c_driver = {
 
 static int __init wm8580_modinit(void)
 {
-       int ret;
+       int ret = 0;
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8580_i2c_driver);
@@ -981,7 +964,7 @@ static int __init wm8580_modinit(void)
        }
 #endif
 
-       return 0;
+       return ret;
 }
 module_init(wm8580_modinit);
 
index 0dfb5dd..1d34656 100644 (file)
 #define WM8580_PLLB  2
 
 #define WM8580_MCLK       1
-#define WM8580_DAC_CLKSEL 2
-#define WM8580_CLKOUTSRC  3
+#define WM8580_CLKOUTSRC  2
 
-#define WM8580_CLKSRC_MCLK 1
-#define WM8580_CLKSRC_PLLA 2
-#define WM8580_CLKSRC_PLLB 3
-#define WM8580_CLKSRC_OSC  4
-#define WM8580_CLKSRC_NONE 5
+#define WM8580_CLKSRC_MCLK    1
+#define WM8580_CLKSRC_PLLA    2
+#define WM8580_CLKSRC_PLLB    3
+#define WM8580_CLKSRC_OSC     4
+#define WM8580_CLKSRC_NONE    5
+#define WM8580_CLKSRC_ADCMCLK 6
 
 #define WM8580_DAI_PAIFRX 0
 #define WM8580_DAI_PAIFTX 1
 
-extern struct snd_soc_dai wm8580_dai[];
-extern struct snd_soc_codec_device soc_codec_dev_wm8580;
-
 #endif
 
index e2dba07..54fbd76 100644 (file)
 
 #include "wm8711.h"
 
-static struct snd_soc_codec *wm8711_codec;
-
 /* codec private data */
 struct wm8711_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type bus_type;
        u16 reg_cache[WM8711_CACHEREGNUM];
        unsigned int sysclk;
 };
@@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
-       struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+       struct wm8711_priv *wm8711 =  snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
        int i = get_coeff(wm8711->sysclk, params_rate(params));
        u16 srate = (coeff_div[i].sr << 2) |
@@ -227,7 +225,7 @@ static int wm8711_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 wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+       struct wm8711_priv *wm8711 =  snd_soc_codec_get_drvdata(codec);
 
        switch (freq) {
        case 11289600:
@@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = {
        .set_fmt = wm8711_set_dai_fmt,
 };
 
-struct snd_soc_dai wm8711_dai = {
-       .name = "WM8711",
+static struct snd_soc_dai_driver wm8711_dai = {
+       .name = "wm8711-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = {
        },
        .ops = &wm8711_ops,
 };
-EXPORT_SYMBOL_GPL(wm8711_dai);
 
-static int wm8711_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8711_suspend(struct snd_soc_codec *codec, 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, WM8711_ACTIVE, 0x0);
        wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8711_resume(struct platform_device *pdev)
+static int wm8711_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8711_probe(struct platform_device *pdev)
+static int wm8711_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8711_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8711_codec;
-       codec = wm8711_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, wm8711_snd_controls,
-                            ARRAY_SIZE(wm8711_snd_controls));
-       wm8711_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8711_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_wm8711 = {
-       .probe =        wm8711_probe,
-       .remove =       wm8711_remove,
-       .suspend =      wm8711_suspend,
-       .resume =       wm8711_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
-
-static int wm8711_register(struct wm8711_priv *wm8711,
-                          enum snd_soc_control_type control)
-{
-       int ret;
-       struct snd_soc_codec *codec = &wm8711->codec;
-       u16 reg;
-
-       if (wm8711_codec) {
-               dev_err(codec->dev, "Another WM8711 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8711);
-       codec->name = "WM8711";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8711_set_bias_level;
-       codec->dai = &wm8711_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8711_CACHEREGNUM;
-       codec->reg_cache = &wm8711->reg_cache;
-
-       memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
+       struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
+       int ret, reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = wm8711_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               goto err;
+               return ret;
        }
 
-       wm8711_dai.dev = codec->dev;
-
        wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
@@ -481,70 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711,
        reg = snd_soc_read(codec, WM8711_ROUT1V);
        snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
 
-       wm8711_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(&wm8711_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
-
-       return 0;
+       snd_soc_add_controls(codec, wm8711_snd_controls,
+                            ARRAY_SIZE(wm8711_snd_controls));
+       wm8711_add_widgets(codec);
 
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8711);
        return ret;
+
 }
 
-static void wm8711_unregister(struct wm8711_priv *wm8711)
+/* power down chip */
+static int wm8711_remove(struct snd_soc_codec *codec)
 {
-       wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8711_dai);
-       snd_soc_unregister_codec(&wm8711->codec);
-       kfree(wm8711);
-       wm8711_codec = NULL;
+       wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
+       .probe =        wm8711_probe,
+       .remove =       wm8711_remove,
+       .suspend =      wm8711_suspend,
+       .resume =       wm8711_resume,
+       .set_bias_level = wm8711_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8711_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8711_reg,
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8711_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec;
        struct wm8711_priv *wm8711;
+       int ret;
 
        wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
        if (wm8711 == NULL)
                return -ENOMEM;
 
-       codec = &wm8711->codec;
-       codec->control_data = spi;
-       codec->dev = &spi->dev;
+       spi_set_drvdata(spi, wm8711);
+       wm8711->bus_type = SND_SOC_SPI;
 
-       dev_set_drvdata(&spi->dev, wm8711);
-
-       return wm8711_register(wm8711, SND_SOC_SPI);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8711, &wm8711_dai, 1);
+       if (ret < 0)
+               kfree(wm8711);
+       return ret;
 }
 
 static int __devexit wm8711_spi_remove(struct spi_device *spi)
 {
-       struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev);
-
-       wm8711_unregister(wm8711);
-
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
 static struct spi_driver wm8711_spi_driver = {
        .driver = {
-               .name   = "wm8711",
-               .bus    = &spi_bus_type,
+               .name   = "wm8711-codec",
                .owner  = THIS_MODULE,
        },
        .probe          = wm8711_spi_probe,
@@ -553,31 +461,30 @@ static struct spi_driver wm8711_spi_driver = {
 #endif /* CONFIG_SPI_MASTER */
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8711_i2c_probe(struct i2c_client *i2c,
+static __devinit int wm8711_i2c_probe(struct i2c_client *client,
                                      const struct i2c_device_id *id)
 {
        struct wm8711_priv *wm8711;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
        if (wm8711 == NULL)
                return -ENOMEM;
 
-       codec = &wm8711->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
-       i2c_set_clientdata(i2c, wm8711);
-       codec->control_data = i2c;
+       i2c_set_clientdata(client, wm8711);
+       wm8711->bus_type = SND_SOC_I2C;
 
-       codec->dev = &i2c->dev;
-
-       return wm8711_register(wm8711, SND_SOC_I2C);
+       ret =  snd_soc_register_codec(&client->dev,
+                       &soc_codec_dev_wm8711, &wm8711_dai, 1);
+       if (ret < 0)
+               kfree(wm8711);
+       return ret;
 }
 
 static __devexit int wm8711_i2c_remove(struct i2c_client *client)
 {
-       struct wm8711_priv *wm8711 = i2c_get_clientdata(client);
-       wm8711_unregister(wm8711);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -589,7 +496,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
 
 static struct i2c_driver wm8711_i2c_driver = {
        .driver = {
-               .name = "WM8711 I2C Codec",
+               .name = "wm8711-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8711_i2c_probe,
index 381e84a..a61db98 100644 (file)
@@ -36,7 +36,4 @@ struct wm8711_setup_data {
        unsigned short i2c_address;
 };
 
-extern struct snd_soc_dai wm8711_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8711;
-
 #endif
index 9d1df26..7488082 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include "wm8727.h"
 /*
  * Note this is a simple chip with no configuration interface, sample rate is
  * determined automatically by examining the Master clock and Bit clock ratios
@@ -33,8 +32,8 @@
                        SNDRV_PCM_RATE_192000)
 
 
-struct snd_soc_dai wm8727_dai = {
-       .name = "WM8727",
+static struct snd_soc_dai_driver wm8727_dai = {
+       .name = "wm8727-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = {
                .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
                },
 };
-EXPORT_SYMBOL_GPL(wm8727_dai);
 
-static struct snd_soc_codec *wm8727_codec;
+static struct snd_soc_codec_driver soc_codec_dev_wm8727;
 
-static int wm8727_soc_probe(struct platform_device *pdev)
+static __devinit int wm8727_probe(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       int ret = 0;
-
-       BUG_ON(!wm8727_codec);
-
-       socdev->card->codec = wm8727_codec;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "wm8727: failed to create pcms\n");
-               goto pcm_err;
-       }
-
-       return ret;
-
-pcm_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
-       return ret;
-}
-
-static int wm8727_soc_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8727 = {
-       .probe =        wm8727_soc_probe,
-       .remove =       wm8727_soc_remove,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727);
-
-
-static __devinit int wm8727_platform_probe(struct platform_device *pdev)
-{
-       struct snd_soc_codec *codec;
-       int ret;
-
-       if (wm8727_codec) {
-               dev_err(&pdev->dev, "Another WM8727 is registered\n");
-               return -EBUSY;
-       }
-
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-       wm8727_codec = codec;
-
-       platform_set_drvdata(pdev, codec);
-
-       mutex_init(&codec->mutex);
-       codec->dev = &pdev->dev;
-       codec->name = "WM8727";
-       codec->owner = THIS_MODULE;
-       codec->dai = &wm8727_dai;
-       codec->num_dai = 1;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       wm8727_dai.dev = &pdev->dev;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret);
-               goto err;
-       }
-
-       ret = snd_soc_register_dai(&wm8727_dai);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
-
-       return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(codec);
-       return ret;
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_wm8727, &wm8727_dai, 1);
 }
 
-static int __devexit wm8727_platform_remove(struct platform_device *pdev)
+static int __devexit wm8727_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&wm8727_dai);
-       snd_soc_unregister_codec(platform_get_drvdata(pdev));
+       snd_soc_unregister_codec(&pdev->dev);
        return 0;
 }
 
@@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = {
                        .owner = THIS_MODULE,
        },
 
-       .probe = wm8727_platform_probe,
-       .remove = __devexit_p(wm8727_platform_remove),
+       .probe = wm8727_probe,
+       .remove = __devexit_p(wm8727_remove),
 };
 
 static int __init wm8727_init(void)
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h
deleted file mode 100644 (file)
index ee19aa7..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * wm8727.h
- *
- *  Created on: 15-Oct-2009
- *      Author: neil.jones@imgtec.com
- *
- * Copyright (C) 2009 Imagination Technologies Ltd.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#ifndef WM8727_H_
-#define WM8727_H_
-
-extern struct snd_soc_dai wm8727_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8727;
-
-#endif /* WM8727_H_ */
index 34be2d2..075f35e 100644 (file)
@@ -29,8 +29,6 @@
 
 #include "wm8728.h"
 
-struct snd_soc_codec_device soc_codec_dev_wm8728;
-
 /*
  * We can't read the WM8728 register space so we cache them instead.
  * Note that the defaults here aren't the physical defaults, we latch
@@ -44,6 +42,11 @@ static const u16 wm8728_reg_defaults[] = {
        0x100,
 };
 
+/* codec private data */
+struct wm8728_priv {
+       enum snd_soc_control_type control_type;
+};
+
 static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
 
 static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -96,8 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        u16 dac = snd_soc_read(codec, WM8728_DACCTL);
 
        dac &= ~0x18;
@@ -210,8 +212,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = {
        .set_fmt        = wm8728_set_dai_fmt,
 };
 
-struct snd_soc_dai wm8728_dai = {
-       .name = "WM8728",
+static struct snd_soc_dai_driver wm8728_dai = {
+       .name = "wm8728-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -221,63 +223,31 @@ struct snd_soc_dai wm8728_dai = {
        },
        .ops = &wm8728_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8728_dai);
 
-static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8728_resume(struct platform_device *pdev)
+static int wm8728_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
 }
 
-/*
- * 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_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret = 0;
-
-       codec->name = "WM8728";
-       codec->owner = THIS_MODULE;
-       codec->set_bias_level = wm8728_set_bias_level;
-       codec->dai = &wm8728_dai;
-       codec->num_dai = 1;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
-       codec->reg_cache = kmemdup(wm8728_reg_defaults,
-                                  sizeof(wm8728_reg_defaults),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type);
        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;
+               return ret;
        }
 
        /* power on device */
@@ -288,215 +258,136 @@ static int wm8728_init(struct snd_soc_device *socdev,
        wm8728_add_widgets(codec);
 
        return ret;
-
-err:
-       kfree(codec->reg_cache);
-       return ret;
 }
 
-static struct snd_soc_device *wm8728_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8728_remove(struct snd_soc_codec *codec)
+{
+       wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-/*
- * WM8728 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
+       .probe =        wm8728_probe,
+       .remove =       wm8728_remove,
+       .suspend =      wm8728_suspend,
+       .resume =       wm8728_resume,
+       .set_bias_level = wm8728_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8728_reg_defaults,
+};
 
-static int wm8728_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8728_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_device *socdev = wm8728_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8728_priv *wm8728;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
+       if (wm8728 == NULL)
+               return -ENOMEM;
+
+       wm8728->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8728);
 
-       ret = wm8728_init(socdev, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8728, &wm8728_dai, 1);
        if (ret < 0)
-               pr_err("failed to initialise WM8728\n");
-
+               kfree(wm8728);
        return ret;
 }
 
-static int wm8728_i2c_remove(struct i2c_client *client)
+static int __devexit wm8728_spi_remove(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
-static const struct i2c_device_id wm8728_i2c_id[] = {
-       { "wm8728", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
-
-static struct i2c_driver wm8728_i2c_driver = {
+static struct spi_driver wm8728_spi_driver = {
        .driver = {
-               .name = "WM8728 I2C Codec",
-               .owner = THIS_MODULE,
+               .name   = "wm8728-codec",
+               .owner  = THIS_MODULE,
        },
-       .probe =    wm8728_i2c_probe,
-       .remove =   wm8728_i2c_remove,
-       .id_table = wm8728_i2c_id,
+       .probe          = wm8728_spi_probe,
+       .remove         = __devexit_p(wm8728_spi_remove),
 };
+#endif /* CONFIG_SPI_MASTER */
 
-static int wm8728_add_i2c_device(struct platform_device *pdev,
-                                const struct wm8728_setup_data *setup)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
+       struct wm8728_priv *wm8728;
        int ret;
 
-       ret = i2c_add_driver(&wm8728_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "wm8728", 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(&wm8728_i2c_driver);
-       return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
-{
-       struct snd_soc_device *socdev = wm8728_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret;
+       wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
+       if (wm8728 == NULL)
+               return -ENOMEM;
 
-       codec->control_data = spi;
+       i2c_set_clientdata(i2c, wm8728);
+       wm8728->control_type = SND_SOC_I2C;
 
-       ret = wm8728_init(socdev, SND_SOC_SPI);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8728, &wm8728_dai, 1);
        if (ret < 0)
-               dev_err(&spi->dev, "failed to initialise WM8728\n");
-
+               kfree(wm8728);
        return ret;
 }
 
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
+static __devexit int wm8728_i2c_remove(struct i2c_client *client)
 {
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
-static struct spi_driver wm8728_spi_driver = {
+static const struct i2c_device_id wm8728_i2c_id[] = {
+       { "wm8728", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
+
+static struct i2c_driver wm8728_i2c_driver = {
        .driver = {
-               .name   = "wm8728",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
+               .name = "wm8728-codec",
+               .owner = THIS_MODULE,
        },
-       .probe          = wm8728_spi_probe,
-       .remove         = __devexit_p(wm8728_spi_remove),
+       .probe =    wm8728_i2c_probe,
+       .remove =   __devexit_p(wm8728_i2c_remove),
+       .id_table = wm8728_i2c_id,
 };
-#endif /* CONFIG_SPI_MASTER */
+#endif
 
-static int wm8728_probe(struct platform_device *pdev)
+static int __init wm8728_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct wm8728_setup_data *setup;
-       struct snd_soc_codec *codec;
        int ret = 0;
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       wm8728_socdev = socdev;
-       ret = -ENODEV;
-
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               ret = wm8728_add_i2c_device(pdev, setup);
+       ret = i2c_add_driver(&wm8728_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n",
+                      ret);
        }
 #endif
 #if defined(CONFIG_SPI_MASTER)
-       if (setup->spi) {
-               ret = spi_register_driver(&wm8728_spi_driver);
-               if (ret != 0)
-                       printk(KERN_ERR "can't add spi driver");
+       ret = spi_register_driver(&wm8728_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n",
+                      ret);
        }
 #endif
-
-       if (ret != 0)
-               kfree(codec);
-
        return ret;
 }
+module_init(wm8728_modinit);
 
-/* power down chip */
-static int wm8728_remove(struct platform_device *pdev)
+static void __exit wm8728_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               wm8728_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(&wm8728_i2c_driver);
 #endif
 #if defined(CONFIG_SPI_MASTER)
        spi_unregister_driver(&wm8728_spi_driver);
 #endif
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8728 = {
-       .probe =        wm8728_probe,
-       .remove =       wm8728_remove,
-       .suspend =      wm8728_suspend,
-       .resume =       wm8728_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
-
-static int __init wm8728_modinit(void)
-{
-       return snd_soc_register_dai(&wm8728_dai);
-}
-module_init(wm8728_modinit);
-
-static void __exit wm8728_exit(void)
-{
-       snd_soc_unregister_dai(&wm8728_dai);
 }
 module_exit(wm8728_exit);
 
index d269c13..8aea362 100644 (file)
 #define WM8728_DACCTL    0x02
 #define WM8728_IFCTL     0x03
 
-struct wm8728_setup_data {
-       int            spi;
-       int            i2c_bus;
-       unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8728_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8728;
-
 #endif
index 0ab9b63..6313858 100644 (file)
@@ -32,9 +32,6 @@
 
 #include "wm8731.h"
 
-static struct snd_soc_codec *wm8731_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8731;
-
 #define WM8731_NUM_SUPPLIES 4
 static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
        "AVDD",
@@ -45,10 +42,11 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8731_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
        u16 reg_cache[WM8731_CACHEREGNUM];
        unsigned int sysclk;
+       int sysclk_type;
 };
 
 
@@ -113,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls =
 SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
 
 static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
        &wm8731_output_mixer_controls[0],
        ARRAY_SIZE(wm8731_output_mixer_controls)),
@@ -130,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
 SND_SOC_DAPM_INPUT("LLINEIN"),
 };
 
+static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
+                           struct snd_soc_dapm_widget *sink)
+{
+       struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
+
+       return wm8731->sysclk_type == WM8731_SYSCLK_MCLK;
+}
+
 static const struct snd_soc_dapm_route intercon[] = {
+       {"DAC", NULL, "OSC", wm8731_check_osc},
+       {"ADC", NULL, "OSC", wm8731_check_osc},
+
        /* output mixer */
        {"Output Mixer", "Line Bypass Switch", "Line Input"},
        {"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -222,9 +232,7 @@ static int wm8731_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 snd_soc_codec *codec = dai->codec;
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
        int i = get_coeff(wm8731->sysclk, params_rate(params));
@@ -252,9 +260,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
 static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
                              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 snd_soc_codec *codec = dai->codec;
 
        /* set active */
        snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
@@ -265,9 +271,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
 static void wm8731_shutdown(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = dai->codec;
 
        /* deactivate */
        if (!codec->active) {
@@ -294,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
 
+       switch (clk_id) {
+       case WM8731_SYSCLK_XTAL:
+       case WM8731_SYSCLK_MCLK:
+               wm8731->sysclk_type = clk_id;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        switch (freq) {
        case 11289600:
        case 12000000:
@@ -301,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
        case 16934400:
        case 18432000:
                wm8731->sysclk = freq;
-               return 0;
+               break;
+       default:
+               return -EINVAL;
        }
-       return -EINVAL;
+
+       snd_soc_dapm_sync(codec);
+
+       return 0;
 }
 
 
@@ -428,8 +446,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = {
        .set_fmt        = wm8731_set_dai_fmt,
 };
 
-struct snd_soc_dai wm8731_dai = {
-       .name = "WM8731",
+static struct snd_soc_dai_driver wm8731_dai = {
+       .name = "wm8731-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -445,24 +463,17 @@ struct snd_soc_dai wm8731_dai = {
        .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)
+static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8731_resume(struct platform_device *pdev)
+static int wm8731_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -472,88 +483,15 @@ static int wm8731_resume(struct platform_device *pdev)
 #define wm8731_resume NULL
 #endif
 
-static int wm8731_probe(struct platform_device *pdev)
+static int wm8731_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8731_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8731_codec;
-       codec = wm8731_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, wm8731_snd_controls,
-                            ARRAY_SIZE(wm8731_snd_controls));
-       wm8731_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8731_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_wm8731 = {
-       .probe =        wm8731_probe,
-       .remove =       wm8731_remove,
-       .suspend =      wm8731_suspend,
-       .resume =       wm8731_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
-
-static int wm8731_register(struct wm8731_priv *wm8731,
-                          enum snd_soc_control_type control)
-{
-       int ret, i;
-       struct snd_soc_codec *codec = &wm8731->codec;
-
-       if (wm8731_codec) {
-               dev_err(codec->dev, "Another WM8731 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8731);
-       codec->name = "WM8731";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8731_set_bias_level;
-       codec->dai = &wm8731_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8731_CACHEREGNUM;
-       codec->reg_cache = &wm8731->reg_cache;
-
-       memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
+       struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0, i;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
@@ -563,7 +501,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
                                 wm8731->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
@@ -579,8 +517,6 @@ static int wm8731_register(struct wm8731_priv *wm8731,
                goto err_regulator_enable;
        }
 
-       wm8731_dai.dev = codec->dev;
-
        wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
@@ -592,79 +528,78 @@ static int wm8731_register(struct wm8731_priv *wm8731,
        /* Disable bypass path by default */
        snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
 
-       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_regulator_enable;
-       }
-
-       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;
-       }
+       snd_soc_add_controls(codec, wm8731_snd_controls,
+                            ARRAY_SIZE(wm8731_snd_controls));
+       wm8731_add_widgets(codec);
 
        /* Regulators will have been enabled by bias management */
        regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
 
        return 0;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
 err_regulator_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
 err_regulator_get:
        regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-err:
+
        kfree(wm8731);
        return ret;
 }
 
-static void wm8731_unregister(struct wm8731_priv *wm8731)
+/* power down chip */
+static int wm8731_remove(struct snd_soc_codec *codec)
 {
-       wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8731_dai);
-       snd_soc_unregister_codec(&wm8731->codec);
+       struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
+
+       wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
        regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
-       kfree(wm8731);
-       wm8731_codec = NULL;
+
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
+       .probe =        wm8731_probe,
+       .remove =       wm8731_remove,
+       .suspend =      wm8731_suspend,
+       .resume =       wm8731_resume,
+       .set_bias_level = wm8731_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8731_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8731_reg,
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec;
        struct wm8731_priv *wm8731;
+       int ret;
 
        wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
        if (wm8731 == NULL)
                return -ENOMEM;
 
-       codec = &wm8731->codec;
-       codec->control_data = spi;
-       codec->dev = &spi->dev;
-
-       dev_set_drvdata(&spi->dev, wm8731);
+       wm8731->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8731);
 
-       return wm8731_register(wm8731, SND_SOC_SPI);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8731, &wm8731_dai, 1);
+       if (ret < 0)
+               kfree(wm8731);
+       return ret;
 }
 
 static int __devexit wm8731_spi_remove(struct spi_device *spi)
 {
-       struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev);
-
-       wm8731_unregister(wm8731);
-
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
 static struct spi_driver wm8731_spi_driver = {
        .driver = {
-               .name   = "wm8731",
-               .bus    = &spi_bus_type,
+               .name   = "wm8731-codec",
                .owner  = THIS_MODULE,
        },
        .probe          = wm8731_spi_probe,
@@ -677,26 +612,26 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8731_priv *wm8731;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
        if (wm8731 == NULL)
                return -ENOMEM;
 
-       codec = &wm8731->codec;
-
        i2c_set_clientdata(i2c, wm8731);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
+       wm8731->control_type = SND_SOC_I2C;
 
-       return wm8731_register(wm8731, SND_SOC_I2C);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8731, &wm8731_dai, 1);
+       if (ret < 0)
+               kfree(wm8731);
+       return ret;
 }
 
 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
 {
-       struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
-       wm8731_unregister(wm8731);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -708,7 +643,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
 
 static struct i2c_driver wm8731_i2c_driver = {
        .driver = {
-               .name = "wm8731",
+               .name = "wm8731-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8731_i2c_probe,
@@ -719,7 +654,7 @@ static struct i2c_driver wm8731_i2c_driver = {
 
 static int __init wm8731_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8731_i2c_driver);
        if (ret != 0) {
@@ -734,7 +669,7 @@ static int __init wm8731_modinit(void)
                       ret);
        }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8731_modinit);
 
index cd7b806..e9c0c76 100644 (file)
 
 #define WM8731_CACHEREGNUM     10
 
-#define WM8731_SYSCLK  0
-#define WM8731_DAI             0
+#define WM8731_SYSCLK_XTAL 1
+#define WM8731_SYSCLK_MCLK 2
 
-extern struct snd_soc_dai wm8731_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8731;
+#define WM8731_DAI             0
 
 #endif
index b9ea890..90e31e9 100644 (file)
 
 #include "wm8741.h"
 
-static struct snd_soc_codec *wm8741_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8741;
-
 #define WM8741_NUM_SUPPLIES 2
 static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
        "AVDD",
        "DVDD",
 };
 
-#define WM8741_NUM_RATES 4
+#define WM8741_NUM_RATES 6
 
 /* codec private data */
 struct wm8741_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        u16 reg_cache[WM8741_REGISTER_COUNT];
        struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
        unsigned int sysclk;
-       unsigned int rate_constraint_list[WM8741_NUM_RATES];
-       struct snd_pcm_hw_constraint_list rate_constraint;
+       struct snd_pcm_hw_constraint_list *sysclk_constraints;
 };
 
 static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = {
@@ -111,10 +107,84 @@ static struct {
        int value;
        int ratio;
 } lrclk_ratios[WM8741_NUM_RATES] = {
-       { 1, 256 },
-       { 2, 384 },
-       { 3, 512 },
-       { 4, 768 },
+       { 1, 128 },
+       { 2, 192 },
+       { 3, 256 },
+       { 4, 384 },
+       { 5, 512 },
+       { 6, 768 },
+};
+
+static unsigned int rates_11289[] = {
+       44100, 88235,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_11289 = {
+       .count  = ARRAY_SIZE(rates_11289),
+       .list   = rates_11289,
+};
+
+static unsigned int rates_12288[] = {
+       32000, 48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_12288 = {
+       .count  = ARRAY_SIZE(rates_12288),
+       .list   = rates_12288,
+};
+
+static unsigned int rates_16384[] = {
+       32000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16384 = {
+       .count  = ARRAY_SIZE(rates_16384),
+       .list   = rates_16384,
+};
+
+static unsigned int rates_16934[] = {
+       44100, 88235,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_16934 = {
+       .count  = ARRAY_SIZE(rates_16934),
+       .list   = rates_16934,
+};
+
+static unsigned int rates_18432[] = {
+       48000, 96000,
+};
+
+static struct snd_pcm_hw_constraint_list constraints_18432 = {
+       .count  = ARRAY_SIZE(rates_18432),
+       .list   = rates_18432,
+};
+
+static unsigned int rates_22579[] = {
+       44100, 88235, 1764000
+};
+
+static struct snd_pcm_hw_constraint_list constraints_22579 = {
+       .count  = ARRAY_SIZE(rates_22579),
+       .list   = rates_22579,
+};
+
+static unsigned int rates_24576[] = {
+       32000, 48000, 96000, 192000
+};
+
+static struct snd_pcm_hw_constraint_list constraints_24576 = {
+       .count  = ARRAY_SIZE(rates_24576),
+       .list   = rates_24576,
+};
+
+static unsigned int rates_36864[] = {
+       48000, 96000, 19200
+};
+
+static struct snd_pcm_hw_constraint_list constraints_36864 = {
+       .count  = ARRAY_SIZE(rates_36864),
+       .list   = rates_36864,
 };
 
 
@@ -135,7 +205,7 @@ static int wm8741_startup(struct snd_pcm_substream *substream,
 
        snd_pcm_hw_constraint_list(substream->runtime, 0,
                                   SNDRV_PCM_HW_PARAM_RATE,
-                                  &wm8741->rate_constraint);
+                                  wm8741->sysclk_constraints);
 
        return 0;
 }
@@ -145,8 +215,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
        int i;
@@ -196,47 +265,52 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
-       unsigned int val;
-       int i;
 
        dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
 
-       wm8741->sysclk = freq;
-
-       wm8741->rate_constraint.count = 0;
-
-       for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
-               dev_dbg(codec->dev, "index = %d, ratio = %d, freq = %d",
-                               i, lrclk_ratios[i].ratio, freq);
-
-               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 32000:
-               case 44100:
-               case 48000:
-               case 64000:
-               case 88200:
-               case 96000:
-                       dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
-                               val);
-                       wm8741->rate_constraint_list[i] = val;
-                       wm8741->rate_constraint.count++;
-                       break;
-               default:
-                       dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
-                               val);
-               }
+       switch (freq) {
+       case 11289600:
+               wm8741->sysclk_constraints = &constraints_11289;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 12288000:
+               wm8741->sysclk_constraints = &constraints_12288;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 16384000:
+               wm8741->sysclk_constraints = &constraints_16384;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 16934400:
+               wm8741->sysclk_constraints = &constraints_16934;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 18432000:
+               wm8741->sysclk_constraints = &constraints_18432;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 22579200:
+       case 33868800:
+               wm8741->sysclk_constraints = &constraints_22579;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 24576000:
+               wm8741->sysclk_constraints = &constraints_24576;
+               wm8741->sysclk = freq;
+               return 0;
+
+       case 36864000:
+               wm8741->sysclk_constraints = &constraints_36864;
+               wm8741->sysclk = freq;
+               return 0;
        }
-
-       /* Need at least one supported rate... */
-       if (wm8741->rate_constraint.count == 0)
-               return -EINVAL;
-
-       return 0;
+       return -EINVAL;
 }
 
 static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -314,8 +388,8 @@ static struct snd_soc_dai_ops wm8741_dai_ops = {
        .set_fmt        = wm8741_set_dai_fmt,
 };
 
-struct snd_soc_dai wm8741_dai = {
-       .name = "WM8741",
+static struct snd_soc_dai_driver wm8741_dai = {
+       .name = "wm8741",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,  /* Mono modes not yet supported */
@@ -325,13 +399,10 @@ struct snd_soc_dai wm8741_dai = {
        },
        .ops = &wm8741_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8741_dai);
 
 #ifdef CONFIG_PM
-static int wm8741_resume(struct platform_device *pdev)
+static int wm8741_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        u16 *cache = codec->reg_cache;
        int i;
 
@@ -348,189 +419,99 @@ static int wm8741_resume(struct platform_device *pdev)
 #define wm8741_resume NULL
 #endif
 
-static int wm8741_probe(struct platform_device *pdev)
+static int wm8741_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
+       struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (wm8741_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
-       socdev->card->codec = wm8741_codec;
-       codec = wm8741_codec;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = wm8741_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+               dev_err(codec->dev, "Failed to issue reset\n");
+               return ret;
        }
 
+       /* Change some default settings - latch VU */
+       wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
+       wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
+       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
+       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+
        snd_soc_add_controls(codec, wm8741_snd_controls,
                             ARRAY_SIZE(wm8741_snd_controls));
        wm8741_add_widgets(codec);
 
-       return ret;
-
-pcm_err:
+       dev_dbg(codec->dev, "Successful registration\n");
        return ret;
 }
 
-static int wm8741_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_wm8741 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
        .probe =        wm8741_probe,
-       .remove =       wm8741_remove,
        .resume =       wm8741_resume,
+       .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = &wm8741_reg_defaults,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741);
 
-static int wm8741_register(struct wm8741_priv *wm8741,
-                          enum snd_soc_control_type control)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8741_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
 {
-       int ret;
-       struct snd_soc_codec *codec = &wm8741->codec;
-       int i;
-
-       if (wm8741_codec) {
-               dev_err(codec->dev, "Another WM8741 is registered\n");
-               return -EINVAL;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8741);
-       codec->name = "WM8741";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = NULL;
-       codec->dai = &wm8741_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8741_REGISTER_COUNT;
-       codec->reg_cache = &wm8741->reg_cache;
-
-       wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0];
-       wm8741->rate_constraint.count =
-               ARRAY_SIZE(wm8741->rate_constraint_list);
-
-       memcpy(codec->reg_cache, wm8741_reg_defaults,
-               sizeof(wm8741->reg_cache));
+       struct wm8741_priv *wm8741;
+       int ret, i;
 
-       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;
-       }
+       wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+       if (wm8741 == NULL)
+               return -ENOMEM;
 
        for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
                wm8741->supplies[i].supply = wm8741_supply_names[i];
 
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies),
+       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
                                 wm8741->supplies);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
                goto err;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
                                    wm8741->supplies);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
                goto err_get;
        }
 
-       ret = wm8741_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err_enable;
-       }
-
-       wm8741_dai.dev = codec->dev;
-
-       /* Change some default settings - latch VU */
-       wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
-       wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
-       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
-       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
-
-       wm8741_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(&wm8741_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               return ret;
-       }
+       i2c_set_clientdata(i2c, wm8741);
+       wm8741->control_type = SND_SOC_I2C;
 
-       dev_dbg(codec->dev, "Successful registration\n");
-       return 0;
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8741, &wm8741_dai, 1);
+       if (ret < 0)
+               goto err_enable;
+       return ret;
 
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
 
 err_get:
        regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
-
 err:
        kfree(wm8741);
        return ret;
 }
 
-static void wm8741_unregister(struct wm8741_priv *wm8741)
-{
-       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
-
-       snd_soc_unregister_dai(&wm8741_dai);
-       snd_soc_unregister_codec(&wm8741->codec);
-       kfree(wm8741);
-       wm8741_codec = NULL;
-}
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static __devinit int wm8741_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
-{
-       struct wm8741_priv *wm8741;
-       struct snd_soc_codec *codec;
-
-       wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
-       if (wm8741 == NULL)
-               return -ENOMEM;
-
-       codec = &wm8741->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
-       i2c_set_clientdata(i2c, wm8741);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
-
-       return wm8741_register(wm8741, SND_SOC_I2C);
-}
-
-static __devexit int wm8741_i2c_remove(struct i2c_client *client)
+static int wm8741_i2c_remove(struct i2c_client *client)
 {
        struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
-       wm8741_unregister(wm8741);
+
+       snd_soc_unregister_codec(&client->dev);
+       regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -540,29 +521,28 @@ static const struct i2c_device_id wm8741_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
 
-
 static struct i2c_driver wm8741_i2c_driver = {
        .driver = {
-               .name = "WM8741",
+               .name = "wm8741-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8741_i2c_probe,
-       .remove =   __devexit_p(wm8741_i2c_remove),
+       .remove =   wm8741_i2c_remove,
        .id_table = wm8741_i2c_id,
 };
 #endif
 
 static int __init wm8741_modinit(void)
 {
-       int ret;
+       int ret = 0;
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8741_i2c_driver);
-       if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n",
-                      ret);
-       }
+       if (ret != 0)
+               pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
 #endif
-       return 0;
+
+       return ret;
 }
 module_init(wm8741_modinit);
 
index fdef6ec..56c1b1d 100644 (file)
 
 #define  WM8741_SYSCLK 0
 
-extern struct snd_soc_dai wm8741_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8741;
-
 #endif
index e2c05e3..6c924cd 100644 (file)
@@ -52,7 +52,7 @@ static const u16 wm8750_reg[] = {
 /* codec private data */
 struct wm8750_priv {
        unsigned int sysclk;
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
 };
 
@@ -560,8 +560,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
        struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
        u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
@@ -649,8 +648,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = {
        .set_sysclk     = wm8750_set_dai_sysclk,
 };
 
-struct snd_soc_dai wm8750_dai = {
-       .name = "WM8750",
+static struct snd_soc_dai_driver wm8750_dai = {
+       .name = "wm8750-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -665,21 +664,15 @@ struct snd_soc_dai wm8750_dai = {
                .formats = WM8750_FORMATS,},
        .ops = &wm8750_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8750_dai);
 
-static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8750_resume(struct platform_device *pdev)
+static int wm8750_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -698,100 +691,21 @@ static int wm8750_resume(struct platform_device *pdev)
        return 0;
 }
 
-static struct snd_soc_codec *wm8750_codec;
-
-static int wm8750_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (!wm8750_codec) {
-               dev_err(&pdev->dev, "WM8750 codec not yet registered\n");
-               return -EINVAL;
-       }
-
-       socdev->card->codec = wm8750_codec;
-       codec = wm8750_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;
-       }
-
-       snd_soc_add_controls(codec, wm8750_snd_controls,
-                               ARRAY_SIZE(wm8750_snd_controls));
-       wm8750_add_widgets(codec);
-
-       return 0;
-
-err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8750_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_wm8750 = {
-       .probe          = wm8750_probe,
-       .remove         = wm8750_remove,
-       .suspend        = wm8750_suspend,
-       .resume         = wm8750_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
-
-/*
- * initialise the WM8750 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8750_register(struct wm8750_priv *wm8750,
-                       enum snd_soc_control_type control)
+static int wm8750_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &wm8750->codec;
-       int reg, ret = 0;
-
-       if (wm8750_codec) {
-               dev_err(codec->dev, "Multiple WM8750 devices not supported\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "WM8750";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_STANDBY;
-       codec->set_bias_level = wm8750_set_bias_level;
-       codec->dai = &wm8750_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1;
-       codec->reg_cache = &wm8750->reg_cache;
-       snd_soc_codec_set_drvdata(codec, wm8750);
-
-       memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache));
+       struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
+       int reg, ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = wm8750_reset(codec);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        /* charge output caps */
@@ -815,150 +729,130 @@ static int wm8750_register(struct wm8750_priv *wm8750,
        reg = snd_soc_read(codec, WM8750_RINVOL);
        snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
 
-       wm8750_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(&wm8750_dai, 1);
-       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(wm8750);
+       snd_soc_add_controls(codec, wm8750_snd_controls,
+                               ARRAY_SIZE(wm8750_snd_controls));
+       wm8750_add_widgets(codec);
        return ret;
 }
 
-static void wm8750_unregister(struct wm8750_priv *wm8750)
+static int wm8750_remove(struct snd_soc_codec *codec)
 {
-       wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dais(&wm8750_dai, 1);
-       snd_soc_unregister_codec(&wm8750->codec);
-       kfree(wm8750);
-       wm8750_codec = NULL;
+       wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8750 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x1a
- *    high = 0x1b
- */
+static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
+       .probe =        wm8750_probe,
+       .remove =       wm8750_remove,
+       .suspend =      wm8750_suspend,
+       .resume =       wm8750_resume,
+       .set_bias_level = wm8750_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8750_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8750_reg,
+};
 
-static int wm8750_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8750_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec;
        struct wm8750_priv *wm8750;
+       int ret;
 
        wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
        if (wm8750 == NULL)
                return -ENOMEM;
 
-       codec = &wm8750->codec;
-       codec->control_data = i2c;
-       i2c_set_clientdata(i2c, wm8750);
-
-       codec->dev = &i2c->dev;
+       wm8750->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8750);
 
-       return wm8750_register(wm8750, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8750, &wm8750_dai, 1);
+       if (ret < 0)
+               kfree(wm8750);
+       return ret;
 }
 
-static int wm8750_i2c_remove(struct i2c_client *client)
+static int __devexit wm8750_spi_remove(struct spi_device *spi)
 {
-       struct wm8750_priv *wm8750 = i2c_get_clientdata(client);
-       wm8750_unregister(wm8750);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
-static const struct i2c_device_id wm8750_i2c_id[] = {
-       { "wm8750", 0 },
-       { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
-
-static struct i2c_driver wm8750_i2c_driver = {
+static struct spi_driver wm8750_spi_driver = {
        .driver = {
-               .name = "WM8750 I2C Codec",
-               .owner = THIS_MODULE,
+               .name   = "wm8750-codec",
+               .owner  = THIS_MODULE,
        },
-       .probe =    wm8750_i2c_probe,
-       .remove =   wm8750_i2c_remove,
-       .id_table = wm8750_i2c_id,
+       .probe          = wm8750_spi_probe,
+       .remove         = __devexit_p(wm8750_spi_remove),
 };
-#endif
+#endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8750_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct snd_soc_codec *codec;
        struct wm8750_priv *wm8750;
+       int ret;
 
        wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
        if (wm8750 == NULL)
                return -ENOMEM;
 
-       codec = &wm8750->codec;
-       codec->control_data = spi;
-       codec->dev = &spi->dev;
-
-       dev_set_drvdata(&spi->dev, wm8750);
+       i2c_set_clientdata(i2c, wm8750);
+       wm8750->control_type = SND_SOC_I2C;
 
-       return wm8750_register(wm8750, SND_SOC_SPI);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8750, &wm8750_dai, 1);
+       if (ret < 0)
+               kfree(wm8750);
+       return ret;
 }
 
-static int __devexit wm8750_spi_remove(struct spi_device *spi)
+static __devexit int wm8750_i2c_remove(struct i2c_client *client)
 {
-       struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev);
-       wm8750_unregister(wm8750);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
-static const struct spi_device_id wm8750_spi_id[] = {
+static const struct i2c_device_id wm8750_i2c_id[] = {
        { "wm8750", 0 },
        { "wm8987", 0 },
        { }
 };
-MODULE_DEVICE_TABLE(spi, wm8750_spi_id);
+MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
 
-static struct spi_driver wm8750_spi_driver = {
+static struct i2c_driver wm8750_i2c_driver = {
        .driver = {
-               .name   = "WM8750 SPI Codec",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
+               .name = "wm8750-codec",
+               .owner = THIS_MODULE,
        },
-       .probe          = wm8750_spi_probe,
-       .remove         = __devexit_p(wm8750_spi_remove),
-       .id_table       = wm8750_spi_id,
+       .probe =    wm8750_i2c_probe,
+       .remove =   __devexit_p(wm8750_i2c_remove),
+       .id_table = wm8750_i2c_id,
 };
 #endif
 
 static int __init wm8750_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8750_i2c_driver);
-       if (ret != 0)
-               pr_err("Failed to register WM8750 I2C driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
+                      ret);
+       }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        ret = spi_register_driver(&wm8750_spi_driver);
-       if (ret != 0)
-               pr_err("Failed to register WM8750 SPI driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n",
+                      ret);
+       }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8750_modinit);
 
index 1dc100e..121427c 100644 (file)
 
 #define WM8750_SYSCLK  0
 
-struct wm8750_setup_data {
-       int spi;
-       int i2c_bus;
-       unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8750_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8750;
-
 #endif
index b59f349..8f679a1 100644 (file)
@@ -57,7 +57,7 @@ module_param(caps_charge, int, 0);
 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
 
 static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
-       unsigned int mode);
+               struct snd_soc_dai *dai, unsigned int hifi);
 
 /*
  * wm8753 register cache
@@ -85,10 +85,11 @@ static const u16 wm8753_reg[] = {
 
 /* codec private data */
 struct wm8753_priv {
+       enum snd_soc_control_type control_type;
        unsigned int sysclk;
        unsigned int pcmclk;
-       struct snd_soc_codec codec;
        u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
+       int dai_func;
 };
 
 /*
@@ -228,6 +229,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
        int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+       struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
        if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
                return 0;
@@ -235,8 +237,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        mode &= 0xfff3;
        mode |= (ucontrol->value.integer.value[0] << 2);
 
-       wm8753_write(codec, WM8753_IOCTL, mode);
-       wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
+       wm8753->dai_func =  ucontrol->value.integer.value[0];
        return 1;
 }
 
@@ -904,6 +905,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int wm8753_pcm_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       wm8753_set_dai_mode(dai->codec, dai, 0);
+       return 0;
+}
+
 /*
  * Set PCM DAI bit size and sample rate.
  */
@@ -912,8 +920,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
        u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
@@ -1138,6 +1145,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int wm8753_i2s_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       wm8753_set_dai_mode(dai->codec, dai, 1);
+       return 0;
+}
+
 /*
  * Set PCM DAI bit size and sample rate.
  */
@@ -1146,8 +1160,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
        u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
@@ -1240,12 +1253,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
        u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+       struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
        /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
         * make sure we check if they are not both active when we mute */
-       if (mute && dai->id == 1) {
-               if (!wm8753_dai[WM8753_DAI_VOICE].playback.active ||
-                       !wm8753_dai[WM8753_DAI_HIFI].playback.active)
+       if (mute && wm8753->dai_func == 1) {
+               if (!codec->active)
                        wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
        } else {
                if (mute)
@@ -1303,6 +1316,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
 static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
+       .startup = wm8753_i2s_startup,
        .hw_params      = wm8753_i2s_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_mode1h_set_dai_fmt,
@@ -1312,6 +1326,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
 };
 
 static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
+       .startup = wm8753_pcm_startup,
        .hw_params      = wm8753_pcm_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_mode1v_set_dai_fmt,
@@ -1321,6 +1336,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
 };
 
 static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
+       .startup = wm8753_pcm_startup,
        .hw_params      = wm8753_pcm_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_mode2_set_dai_fmt,
@@ -1330,6 +1346,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
 };
 
 static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3        = {
+       .startup = wm8753_i2s_startup,
        .hw_params      = wm8753_i2s_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_mode3_4_set_dai_fmt,
@@ -1339,6 +1356,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3   = {
 };
 
 static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4        = {
+       .startup = wm8753_i2s_startup,
        .hw_params      = wm8753_i2s_hw_params,
        .digital_mute   = wm8753_mute,
        .set_fmt        = wm8753_mode3_4_set_dai_fmt,
@@ -1347,10 +1365,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4  = {
        .set_sysclk     = wm8753_set_dai_sysclk,
 };
 
-static const struct snd_soc_dai wm8753_all_dai[] = {
+static struct snd_soc_dai_driver wm8753_all_dai[] = {
 /* DAI HiFi mode 1 */
-{      .name = "WM8753 HiFi",
-       .id = 1,
+{      .name = "wm8753-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -1366,8 +1383,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
        .ops = &wm8753_dai_ops_hifi_mode1,
 },
 /* DAI Voice mode 1 */
-{      .name = "WM8753 Voice",
-       .id = 1,
+{      .name = "wm8753-voice",
        .playback = {
                .stream_name = "Voice Playback",
                .channels_min = 1,
@@ -1383,12 +1399,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
        .ops = &wm8753_dai_ops_voice_mode1,
 },
 /* DAI HiFi mode 2 - dummy */
-{      .name = "WM8753 HiFi",
-       .id = 2,
+{      .name = "wm8753-hifi",
 },
 /* DAI Voice mode 2 */
-{      .name = "WM8753 Voice",
-       .id = 2,
+{      .name = "wm8753-voice",
        .playback = {
                .stream_name = "Voice Playback",
                .channels_min = 1,
@@ -1404,8 +1418,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
        .ops = &wm8753_dai_ops_voice_mode2,
 },
 /* DAI HiFi mode 3 */
-{      .name = "WM8753 HiFi",
-       .id = 3,
+{      .name = "wm8753-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -1421,12 +1434,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
        .ops = &wm8753_dai_ops_hifi_mode3,
 },
 /* DAI Voice mode 3 - dummy */
-{      .name = "WM8753 Voice",
-       .id = 3,
+{      .name = "wm8753-voice",
 },
 /* DAI HiFi mode 4 */
-{      .name = "WM8753 HiFi",
-       .id = 4,
+{      .name = "wm8753-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -1442,58 +1453,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
        .ops = &wm8753_dai_ops_hifi_mode4,
 },
 /* DAI Voice mode 4 - dummy */
-{      .name = "WM8753 Voice",
-       .id = 4,
+{      .name = "wm8753-voice",
 },
 };
 
-struct snd_soc_dai wm8753_dai[] = {
+static struct snd_soc_dai_driver wm8753_dai[] = {
        {
-               .name = "WM8753 DAI 0",
+               .name = "wm8753-aif0",
        },
        {
-               .name = "WM8753 DAI 1",
+               .name = "wm8753-aif1",
        },
 };
-EXPORT_SYMBOL_GPL(wm8753_dai);
 
-static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
+static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
+               struct snd_soc_dai *dai, unsigned int hifi)
 {
-       if (mode < 4) {
-               int playback_active, capture_active, codec_active, pop_wait;
-               void *private_data;
-               struct list_head list;
-
-               playback_active = wm8753_dai[0].playback.active;
-               capture_active = wm8753_dai[0].capture.active;
-               codec_active = wm8753_dai[0].active;
-               private_data = wm8753_dai[0].private_data;
-               pop_wait = wm8753_dai[0].pop_wait;
-               list = wm8753_dai[0].list;
-               wm8753_dai[0] = wm8753_all_dai[mode << 1];
-               wm8753_dai[0].playback.active = playback_active;
-               wm8753_dai[0].capture.active = capture_active;
-               wm8753_dai[0].active = codec_active;
-               wm8753_dai[0].private_data = private_data;
-               wm8753_dai[0].pop_wait = pop_wait;
-               wm8753_dai[0].list = list;
-
-               playback_active = wm8753_dai[1].playback.active;
-               capture_active = wm8753_dai[1].capture.active;
-               codec_active = wm8753_dai[1].active;
-               private_data = wm8753_dai[1].private_data;
-               pop_wait = wm8753_dai[1].pop_wait;
-               list = wm8753_dai[1].list;
-               wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
-               wm8753_dai[1].playback.active = playback_active;
-               wm8753_dai[1].capture.active = capture_active;
-               wm8753_dai[1].active = codec_active;
-               wm8753_dai[1].private_data = private_data;
-               wm8753_dai[1].pop_wait = pop_wait;
-               wm8753_dai[1].list = list;
+       struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+
+       if (wm8753->dai_func < 4) {
+               if (hifi)
+                       dai->driver = &wm8753_all_dai[wm8753->dai_func << 1];
+               else
+                       dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
        }
-       wm8753_dai[0].codec = codec;
-       wm8753_dai[1].codec = codec;
+       wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
 }
 
 static void wm8753_work(struct work_struct *work)
@@ -1503,19 +1487,14 @@ static void wm8753_work(struct work_struct *work)
        wm8753_set_bias_level(codec, codec->bias_level);
 }
 
-static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8753_resume(struct platform_device *pdev)
+static int wm8753_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -1547,41 +1526,6 @@ static int wm8753_resume(struct platform_device *pdev)
        return 0;
 }
 
-static struct snd_soc_codec *wm8753_codec;
-
-static int wm8753_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (!wm8753_codec) {
-               dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
-               return -EINVAL;
-       }
-
-       socdev->card->codec = wm8753_codec;
-       codec = wm8753_codec;
-
-       wm8753_set_dai_mode(codec, 0);
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "wm8753: failed to create pcms\n");
-               goto pcm_err;
-       }
-
-       snd_soc_add_controls(codec, wm8753_snd_controls,
-                            ARRAY_SIZE(wm8753_snd_controls));
-       wm8753_add_widgets(codec);
-
-       return 0;
-
-pcm_err:
-       return ret;
-}
-
 /*
  * This function forces any delayed work to be queued and run.
  */
@@ -1601,62 +1545,28 @@ static int run_delayed_work(struct delayed_work *dwork)
        return ret;
 }
 
-/* power down chip */
-static int wm8753_remove(struct platform_device *pdev)
+static int wm8753_probe(struct snd_soc_codec *codec)
 {
-       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_wm8753 = {
-       .probe =        wm8753_probe,
-       .remove =       wm8753_remove,
-       .suspend =      wm8753_suspend,
-       .resume =       wm8753_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+       struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0, reg;
 
-static int wm8753_register(struct wm8753_priv *wm8753)
-{
-       int ret, i;
-       struct snd_soc_codec *codec = &wm8753->codec;
-       u16 reg;
+       INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
 
-       if (wm8753_codec) {
-               dev_err(codec->dev, "Multiple WM8753 devices not supported\n");
-               ret = -EINVAL;
-               goto err;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "WM8753";
-       codec->owner = THIS_MODULE;
-       codec->read = wm8753_read_reg_cache;
-       codec->write = wm8753_write;
-       codec->bias_level = SND_SOC_BIAS_STANDBY;
-       codec->set_bias_level = wm8753_set_bias_level;
-       codec->dai = wm8753_dai;
-       codec->num_dai = 2;
-       codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
-       codec->reg_cache = &wm8753->reg_cache;
-       snd_soc_codec_set_drvdata(codec, wm8753);
-
-       memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
-       INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
-
        ret = wm8753_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err;
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               return ret;
        }
 
+       wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8753->dai_func = 0;
+
        /* charge output caps */
        wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
        schedule_delayed_work(&codec->delayed_work,
@@ -1684,165 +1594,133 @@ static int wm8753_register(struct wm8753_priv *wm8753)
        reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
        wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
 
-       wm8753_codec = codec;
-
-       for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++)
-               wm8753_dai[i].dev = codec->dev;
-
-       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(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
-               goto err_codec;
-       }
+       snd_soc_add_controls(codec, wm8753_snd_controls,
+                            ARRAY_SIZE(wm8753_snd_controls));
+       wm8753_add_widgets(codec);
 
        return 0;
-
-err_codec:
-       run_delayed_work(&codec->delayed_work);
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8753);
-       return ret;
 }
 
-static void wm8753_unregister(struct wm8753_priv *wm8753)
+/* power down chip */
+static int wm8753_remove(struct snd_soc_codec *codec)
 {
-       wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF);
-       run_delayed_work(&wm8753->codec.delayed_work);
-       snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
-       snd_soc_unregister_codec(&wm8753->codec);
-       kfree(wm8753);
-       wm8753_codec = NULL;
+       run_delayed_work(&codec->delayed_work);
+       wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
 }
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
+       .probe =        wm8753_probe,
+       .remove =       wm8753_remove,
+       .suspend =      wm8753_suspend,
+       .resume =       wm8753_resume,
+       .set_bias_level = wm8753_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8753_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8753_reg,
+};
 
-static int wm8753_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8753_spi_probe(struct spi_device *spi)
 {
-       struct snd_soc_codec *codec;
        struct wm8753_priv *wm8753;
+       int ret;
 
        wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
        if (wm8753 == NULL)
                return -ENOMEM;
 
-        codec = &wm8753->codec;
-        codec->hw_write = (hw_write_t)i2c_master_send;
-        codec->control_data = i2c;
-        i2c_set_clientdata(i2c, wm8753);
-
-        codec->dev = &i2c->dev;
+       wm8753->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8753);
 
-       return wm8753_register(wm8753);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
+       if (ret < 0)
+               kfree(wm8753);
+       return ret;
 }
 
-static int wm8753_i2c_remove(struct i2c_client *client)
+static int __devexit wm8753_spi_remove(struct spi_device *spi)
 {
-        struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
-        wm8753_unregister(wm8753);
-        return 0;
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
 }
 
-static const struct i2c_device_id wm8753_i2c_id[] = {
-       { "wm8753", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
-
-static struct i2c_driver wm8753_i2c_driver = {
+static struct spi_driver wm8753_spi_driver = {
        .driver = {
-               .name = "wm8753",
-               .owner = THIS_MODULE,
+               .name   = "wm8753-codec",
+               .owner  = THIS_MODULE,
        },
-       .probe =    wm8753_i2c_probe,
-       .remove =   wm8753_i2c_remove,
-       .id_table = wm8753_i2c_id,
+       .probe          = wm8753_spi_probe,
+       .remove         = __devexit_p(wm8753_spi_remove),
 };
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int wm8753_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;
+#endif /* CONFIG_SPI_MASTER */
 
-       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 wm8753_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct snd_soc_codec *codec;
        struct wm8753_priv *wm8753;
+       int ret;
 
        wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
        if (wm8753 == NULL)
                return -ENOMEM;
 
-       codec = &wm8753->codec;
-       codec->control_data = spi;
-       codec->hw_write = (hw_write_t)wm8753_spi_write;
-       codec->dev = &spi->dev;
+       i2c_set_clientdata(i2c, wm8753);
+       wm8753->control_type = SND_SOC_I2C;
 
-       dev_set_drvdata(&spi->dev, wm8753);
-
-       return wm8753_register(wm8753);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
+       if (ret < 0)
+               kfree(wm8753);
+       return ret;
 }
 
-static int __devexit wm8753_spi_remove(struct spi_device *spi)
+static __devexit int wm8753_i2c_remove(struct i2c_client *client)
 {
-       struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev);
-       wm8753_unregister(wm8753);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
-static struct spi_driver wm8753_spi_driver = {
+static const struct i2c_device_id wm8753_i2c_id[] = {
+       { "wm8753", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
+
+static struct i2c_driver wm8753_i2c_driver = {
        .driver = {
-               .name   = "wm8753",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
+               .name = "wm8753-codec",
+               .owner = THIS_MODULE,
        },
-       .probe          = wm8753_spi_probe,
-       .remove         = __devexit_p(wm8753_spi_remove),
+       .probe =    wm8753_i2c_probe,
+       .remove =   __devexit_p(wm8753_i2c_remove),
+       .id_table = wm8753_i2c_id,
 };
 #endif
 
 static int __init wm8753_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8753_i2c_driver);
-       if (ret != 0)
-               pr_err("Failed to register WM8753 I2C driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n",
+                      ret);
+       }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        ret = spi_register_driver(&wm8753_spi_driver);
-       if (ret != 0)
-               pr_err("Failed to register WM8753 SPI driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n",
+                      ret);
+       }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8753_modinit);
 
index 57b2ba2..94edac1 100644 (file)
 #define WM8753_DAI_HIFI                0
 #define WM8753_DAI_VOICE               1
 
-extern struct snd_soc_dai wm8753_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm8753;
-
 #endif
index f8154e6..04182c4 100644 (file)
 
 #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;
+       enum snd_soc_control_type control_type;
        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 */
@@ -144,7 +137,7 @@ 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) {
+       switch (dai->driver->id) {
        case WM8776_DAI_DAC:
                reg = WM8776_DACIFCTRL;
                master = 0x80;
@@ -226,7 +219,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
 
        iface = 0;
 
-       switch (dai->id) {
+       switch (dai->driver->id) {
        case WM8776_DAI_DAC:
                iface_reg = WM8776_DACIFCTRL;
                master = 0x80;
@@ -260,7 +253,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
        /* 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)
+                       if (wm8776->sysclk[dai->driver->id] / params_rate(params)
                            == mclk_ratios[i])
                                break;
                }
@@ -268,7 +261,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
                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));
+                               wm8776->sysclk[dai->driver->id], params_rate(params));
                        return -EINVAL;
                }
 
@@ -298,9 +291,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai,
        struct snd_soc_codec *codec = dai->codec;
        struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
 
-       BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
+       BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk));
 
-       wm8776->sysclk[dai->id] = freq;
+       wm8776->sysclk[dai->driver->id] = freq;
 
        return 0;
 }
@@ -350,10 +343,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = {
        .set_sysclk     = wm8776_set_sysclk,
 };
 
-struct snd_soc_dai wm8776_dai[] = {
+static struct snd_soc_dai_driver wm8776_dai[] = {
        {
-               .name = "WM8776 Playback",
-               .id = WM8776_DAI_DAC,
+               .name = "wm8776-hifi-playback",
+               .id     = WM8776_DAI_DAC,
                .playback = {
                        .stream_name = "Playback",
                        .channels_min = 2,
@@ -364,8 +357,8 @@ struct snd_soc_dai wm8776_dai[] = {
                .ops = &wm8776_dac_ops,
        },
        {
-               .name = "WM8776 Capture",
-               .id = WM8776_DAI_ADC,
+               .name = "wm8776-hifi-capture",
+               .id     = WM8776_DAI_ADC,
                .capture = {
                        .stream_name = "Capture",
                        .channels_min = 2,
@@ -376,23 +369,17 @@ struct snd_soc_dai wm8776_dai[] = {
                .ops = &wm8776_adc_ops,
        },
 };
-EXPORT_SYMBOL_GPL(wm8776_dai);
 
 #ifdef CONFIG_PM
-static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8776_suspend(struct snd_soc_codec *codec, 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)
+static int wm8776_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -415,27 +402,30 @@ static int wm8776_resume(struct platform_device *pdev)
 #define wm8776_resume NULL
 #endif
 
-static int wm8776_probe(struct platform_device *pdev)
+static int wm8776_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
+       struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (wm8776_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
-       socdev->card->codec = wm8776_codec;
-       codec = wm8776_codec;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = wm8776_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               return ret;
        }
 
+       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);
+
        snd_soc_add_controls(codec, wm8776_snd_controls,
                             ARRAY_SIZE(wm8776_snd_controls));
        snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
@@ -443,169 +433,56 @@ static int wm8776_probe(struct platform_device *pdev)
        snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
 
        return ret;
-
-pcm_err:
-       return ret;
 }
 
 /* power down chip */
-static int wm8776_remove(struct platform_device *pdev)
+static int wm8776_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm8776 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
        .probe =        wm8776_probe,
        .remove =       wm8776_remove,
        .suspend =      wm8776_suspend,
        .resume =       wm8776_resume,
+       .set_bias_level = wm8776_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8776_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8776_reg,
 };
-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);
-
-       snd_soc_codec_set_drvdata(codec, 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;
+       int ret;
 
        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;
+       wm8776->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8776);
 
-       dev_set_drvdata(&spi->dev, wm8776);
-
-       return wm8776_register(wm8776, SND_SOC_SPI);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
+       if (ret < 0)
+               kfree(wm8776);
+       return ret;
 }
 
 static int __devexit wm8776_spi_remove(struct spi_device *spi)
 {
-       struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
-
-       wm8776_unregister(wm8776);
-
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
 static struct spi_driver wm8776_spi_driver = {
        .driver = {
-               .name   = "wm8776",
-               .bus    = &spi_bus_type,
+               .name   = "wm8776-codec",
                .owner  = THIS_MODULE,
        },
        .probe          = wm8776_spi_probe,
@@ -618,27 +495,26 @@ 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;
+       int ret;
 
        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;
+       wm8776->control_type = SND_SOC_I2C;
 
-       return wm8776_register(wm8776, SND_SOC_I2C);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
+       if (ret < 0)
+               kfree(wm8776);
+       return ret;
 }
 
 static __devexit int wm8776_i2c_remove(struct i2c_client *client)
 {
-       struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
-       wm8776_unregister(wm8776);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -650,7 +526,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
 
 static struct i2c_driver wm8776_i2c_driver = {
        .driver = {
-               .name = "wm8776",
+               .name = "wm8776-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8776_i2c_probe,
@@ -661,22 +537,22 @@ static struct i2c_driver wm8776_i2c_driver = {
 
 static int __init wm8776_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #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",
+               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",
+               printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n",
                       ret);
        }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8776_modinit);
 
index 6606d25..4cf1c8e 100644 (file)
@@ -45,7 +45,4 @@
 #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/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
new file mode 100644 (file)
index 0000000..4599e8e
--- /dev/null
@@ -0,0 +1,833 @@
+/*
+ * wm8804.c  --  WM8804 S/PDIF transceiver driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8804.h"
+
+#define WM8804_NUM_SUPPLIES 2
+static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
+       "PVDD",
+       "DVDD"
+};
+
+static const u8 wm8804_reg_defs[] = {
+       0x05,     /* R0  - RST/DEVID1 */
+       0x88,     /* R1  - DEVID2 */
+       0x04,     /* R2  - DEVREV */
+       0x21,     /* R3  - PLL1 */
+       0xFD,     /* R4  - PLL2 */
+       0x36,     /* R5  - PLL3 */
+       0x07,     /* R6  - PLL4 */
+       0x16,     /* R7  - PLL5 */
+       0x18,     /* R8  - PLL6 */
+       0xFF,     /* R9  - SPDMODE */
+       0x00,     /* R10 - INTMASK */
+       0x00,     /* R11 - INTSTAT */
+       0x00,     /* R12 - SPDSTAT */
+       0x00,     /* R13 - RXCHAN1 */
+       0x00,     /* R14 - RXCHAN2 */
+       0x00,     /* R15 - RXCHAN3 */
+       0x00,     /* R16 - RXCHAN4 */
+       0x00,     /* R17 - RXCHAN5 */
+       0x00,     /* R18 - SPDTX1 */
+       0x00,     /* R19 - SPDTX2 */
+       0x00,     /* R20 - SPDTX3 */
+       0x71,     /* R21 - SPDTX4 */
+       0x0B,     /* R22 - SPDTX5 */
+       0x70,     /* R23 - GPO0 */
+       0x57,     /* R24 - GPO1 */
+       0x00,     /* R25 */
+       0x42,     /* R26 - GPO2 */
+       0x06,     /* R27 - AIFTX */
+       0x06,     /* R28 - AIFRX */
+       0x80,     /* R29 - SPDRX1 */
+       0x07,     /* R30 - PWRDN */
+};
+
+struct wm8804_priv {
+       enum snd_soc_control_type control_type;
+       struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
+       struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
+       struct snd_soc_codec *codec;
+};
+
+static int txsrc_get(struct snd_kcontrol *kcontrol,
+                    struct snd_ctl_elem_value *ucontrol);
+
+static int txsrc_put(struct snd_kcontrol *kcontrol,
+                    struct snd_ctl_elem_value *ucontrol);
+
+/*
+ * We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8804_REGULATOR_EVENT(n) \
+static int wm8804_regulator_event_##n(struct notifier_block *nb, \
+                                     unsigned long event, void *data)    \
+{ \
+       struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
+                                                 disable_nb[n]); \
+       if (event & REGULATOR_EVENT_DISABLE) { \
+               wm8804->codec->cache_sync = 1; \
+       } \
+       return 0; \
+}
+
+WM8804_REGULATOR_EVENT(0)
+WM8804_REGULATOR_EVENT(1)
+
+static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
+static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
+
+static const struct snd_kcontrol_new wm8804_snd_controls[] = {
+       SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put),
+       SOC_SINGLE("TX Playback Switch", WM8804_PWRDN, 2, 1, 1),
+       SOC_SINGLE("AIF Playback Switch", WM8804_PWRDN, 4, 1, 1)
+};
+
+static int txsrc_get(struct snd_kcontrol *kcontrol,
+                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec;
+       unsigned int src;
+
+       codec = snd_kcontrol_chip(kcontrol);
+       src = snd_soc_read(codec, WM8804_SPDTX4);
+       if (src & 0x40)
+               ucontrol->value.integer.value[0] = 1;
+       else
+               ucontrol->value.integer.value[0] = 0;
+
+       return 0;
+}
+
+static int txsrc_put(struct snd_kcontrol *kcontrol,
+                    struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec;
+       unsigned int src, txpwr;
+
+       codec = snd_kcontrol_chip(kcontrol);
+
+       if (ucontrol->value.integer.value[0] != 0
+                       && ucontrol->value.integer.value[0] != 1)
+               return -EINVAL;
+
+       src = snd_soc_read(codec, WM8804_SPDTX4);
+       switch ((src & 0x40) >> 6) {
+       case 0:
+               if (!ucontrol->value.integer.value[0])
+                       return 0;
+               break;
+       case 1:
+               if (ucontrol->value.integer.value[1])
+                       return 0;
+               break;
+       }
+
+       /* save the current power state of the transmitter */
+       txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4;
+       /* power down the transmitter */
+       snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4);
+       /* set the tx source */
+       snd_soc_update_bits(codec, WM8804_SPDTX4, 0x40,
+                           ucontrol->value.integer.value[0] << 6);
+
+       if (ucontrol->value.integer.value[0]) {
+               /* power down the receiver */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0x2);
+               /* power up the AIF */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0);
+       } else {
+               /* don't power down the AIF -- may be used as an output */
+               /* power up the receiver */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0);
+       }
+
+       /* restore the transmitter's configuration */
+       snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr);
+
+       return 0;
+}
+
+static int wm8804_volatile(unsigned int reg)
+{
+       switch (reg) {
+       case WM8804_RST_DEVID1:
+       case WM8804_DEVID2:
+       case WM8804_DEVREV:
+       case WM8804_INTSTAT:
+       case WM8804_SPDSTAT:
+       case WM8804_RXCHAN1:
+       case WM8804_RXCHAN2:
+       case WM8804_RXCHAN3:
+       case WM8804_RXCHAN4:
+       case WM8804_RXCHAN5:
+               return 1;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int wm8804_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0);
+}
+
+static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec;
+       u16 format, master, bcp, lrp;
+
+       codec = dai->codec;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               format = 0x2;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               format = 0x0;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               format = 0x1;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               format = 0x3;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown dai format\n");
+               return -EINVAL;
+       }
+
+       /* set data format */
+       snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format);
+       snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               master = 0;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown master/slave configuration\n");
+               return -EINVAL;
+       }
+
+       /* set master/slave mode */
+       snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6);
+
+       bcp = lrp = 0;
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bcp = lrp = 1;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bcp = 1;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrp = 1;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown polarity configuration\n");
+               return -EINVAL;
+       }
+
+       /* set frame inversion */
+       snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20,
+                           (bcp << 4) | (lrp << 5));
+       snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20,
+                           (bcp << 4) | (lrp << 5));
+       return 0;
+}
+
+static int wm8804_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec;
+       u16 blen;
+
+       codec = dai->codec;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               blen = 0x0;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               blen = 0x1;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               blen = 0x2;
+               break;
+       default:
+               dev_err(dai->dev, "Unsupported word length: %u\n",
+                       params_format(params));
+               return -EINVAL;
+       }
+
+       /* set word length */
+       snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2);
+       snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2);
+
+       return 0;
+}
+
+struct pll_div {
+       u32 prescale:1;
+       u32 mclkdiv:1;
+       u32 freqmode:2;
+       u32 n:4;
+       u32 k:22;
+};
+
+/* PLL rate to output rate divisions */
+static struct {
+       unsigned int div;
+       unsigned int freqmode;
+       unsigned int mclkdiv;
+} post_table[] = {
+       {  2,  0, 0 },
+       {  4,  0, 1 },
+       {  4,  1, 0 },
+       {  8,  1, 1 },
+       {  8,  2, 0 },
+       { 16,  2, 1 },
+       { 12,  3, 0 },
+       { 24,  3, 1 }
+};
+
+#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
+static int pll_factors(struct pll_div *pll_div, unsigned int target,
+                      unsigned int source)
+{
+       u64 Kpart;
+       unsigned long int K, Ndiv, Nmod, tmp;
+       int i;
+
+       /*
+        * Scale the output frequency up; the PLL should run in the
+        * region of 90-100MHz.
+        */
+       for (i = 0; i < ARRAY_SIZE(post_table); i++) {
+               tmp = target * post_table[i].div;
+               if (tmp >= 90000000 && tmp <= 100000000) {
+                       pll_div->freqmode = post_table[i].freqmode;
+                       pll_div->mclkdiv = post_table[i].mclkdiv;
+                       target *= post_table[i].div;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(post_table)) {
+               pr_err("%s: Unable to scale output frequency: %uHz\n",
+                      __func__, target);
+               return -EINVAL;
+       }
+
+       pll_div->prescale = 0;
+       Ndiv = target / source;
+       if (Ndiv < 5) {
+               source >>= 1;
+               pll_div->prescale = 1;
+               Ndiv = target / source;
+       }
+
+       if (Ndiv < 5 || Ndiv > 13) {
+               pr_err("%s: WM8804 N value is not within the recommended range: %lu\n",
+                      __func__, Ndiv);
+               return -EINVAL;
+       }
+       pll_div->n = Ndiv;
+
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (u64)Nmod;
+
+       do_div(Kpart, source);
+
+       K = Kpart & 0xffffffff;
+       if ((K % 10) >= 5)
+               K += 5;
+       K /= 10;
+       pll_div->k = K;
+
+       return 0;
+}
+
+static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
+                         int source, unsigned int freq_in,
+                         unsigned int freq_out)
+{
+       struct snd_soc_codec *codec;
+
+       codec = dai->codec;
+       if (!freq_in || !freq_out) {
+               /* disable the PLL */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
+               return 0;
+       } else {
+               int ret;
+               struct pll_div pll_div;
+
+               ret = pll_factors(&pll_div, freq_out, freq_in);
+               if (ret)
+                       return ret;
+
+               /* power down the PLL before reprogramming it */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
+
+               if (!freq_in || !freq_out)
+                       return 0;
+
+               /* set PLLN and PRESCALE */
+               snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10,
+                                   pll_div.n | (pll_div.prescale << 4));
+               /* set mclkdiv and freqmode */
+               snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8,
+                                   pll_div.freqmode | (pll_div.mclkdiv << 3));
+               /* set PLLK */
+               snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff);
+               snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff);
+               snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16);
+
+               /* power up the PLL */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0);
+       }
+
+       return 0;
+}
+
+static int wm8804_set_sysclk(struct snd_soc_dai *dai,
+                            int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec;
+
+       codec = dai->codec;
+
+       switch (clk_id) {
+       case WM8804_TX_CLKSRC_MCLK:
+               if ((freq >= 10000000 && freq <= 14400000)
+                               || (freq >= 16280000 && freq <= 27000000))
+                       snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80);
+               else {
+                       dev_err(dai->dev, "OSCCLOCK is not within the "
+                               "recommended range: %uHz\n", freq);
+                       return -EINVAL;
+               }
+               break;
+       case WM8804_TX_CLKSRC_PLL:
+               snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0);
+               break;
+       case WM8804_CLKOUT_SRC_CLK1:
+               snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0);
+               break;
+       case WM8804_CLKOUT_SRC_OSCCLK:
+               snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8);
+               break;
+       default:
+               dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
+                            int div_id, int div)
+{
+       struct snd_soc_codec *codec;
+
+       codec = dai->codec;
+       switch (div_id) {
+       case WM8804_CLKOUT_DIV:
+               snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
+                                   (div & 0x3) << 4);
+               break;
+       default:
+               dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void wm8804_sync_cache(struct snd_soc_codec *codec)
+{
+       short i;
+       u8 *cache;
+
+       if (!codec->cache_sync)
+               return;
+
+       codec->cache_only = 0;
+       cache = codec->reg_cache;
+       for (i = 0; i < codec->driver->reg_cache_size; i++) {
+               if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
+                       continue;
+               snd_soc_write(codec, i, cache[i]);
+       }
+       codec->cache_sync = 0;
+}
+
+static int wm8804_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       int ret;
+       struct wm8804_priv *wm8804;
+
+       wm8804 = snd_soc_codec_get_drvdata(codec);
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               /* power up the OSC and the PLL */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0);
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
+                                                   wm8804->supplies);
+                       if (ret) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+                       wm8804_sync_cache(codec);
+               }
+               /* power down the OSC and the PLL */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* power down the OSC and the PLL */
+               snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
+               regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies),
+                                      wm8804->supplies);
+               break;
+       }
+
+       codec->bias_level = level;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8804_resume(struct snd_soc_codec *codec)
+{
+       wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define wm8804_suspend NULL
+#define wm8804_resume NULL
+#endif
+
+static int wm8804_remove(struct snd_soc_codec *codec)
+{
+       struct wm8804_priv *wm8804;
+       int i;
+
+       wm8804 = snd_soc_codec_get_drvdata(codec);
+       wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
+               regulator_unregister_notifier(wm8804->supplies[i].consumer,
+                                             &wm8804->disable_nb[i]);
+       regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+       return 0;
+}
+
+static int wm8804_probe(struct snd_soc_codec *codec)
+{
+       struct wm8804_priv *wm8804;
+       int i, id1, id2, ret;
+
+       wm8804 = snd_soc_codec_get_drvdata(codec);
+       wm8804->codec = codec;
+
+       codec->idle_bias_off = 1;
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
+               wm8804->supplies[i].supply = wm8804_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
+                                wm8804->supplies);
+       if (ret) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
+       wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
+               ret = regulator_register_notifier(wm8804->supplies[i].consumer,
+                                                 &wm8804->disable_nb[i]);
+               if (ret != 0) {
+                       dev_err(codec->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
+                                   wm8804->supplies);
+       if (ret) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_reg_get;
+       }
+
+       id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
+       if (id1 < 0) {
+               dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
+               ret = id1;
+               goto err_reg_enable;
+       }
+
+       id2 = snd_soc_read(codec, WM8804_DEVID2);
+       if (id2 < 0) {
+               dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
+               ret = id2;
+               goto err_reg_enable;
+       }
+
+       id2 = (id2 << 8) | id1;
+
+       if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
+                       | wm8804_reg_defs[WM8804_RST_DEVID1])) {
+               dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
+               ret = -EINVAL;
+               goto err_reg_enable;
+       }
+
+       ret = snd_soc_read(codec, WM8804_DEVREV);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_reg_enable;
+       }
+       dev_info(codec->dev, "revision %c\n", ret + 'A');
+
+       ret = wm8804_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               goto err_reg_enable;
+       }
+
+       wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       snd_soc_add_controls(codec, wm8804_snd_controls,
+                            ARRAY_SIZE(wm8804_snd_controls));
+       return 0;
+
+err_reg_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+err_reg_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
+       return ret;
+}
+
+static struct snd_soc_dai_ops wm8804_dai_ops = {
+       .hw_params = wm8804_hw_params,
+       .set_fmt = wm8804_set_fmt,
+       .set_sysclk = wm8804_set_sysclk,
+       .set_clkdiv = wm8804_set_clkdiv,
+       .set_pll = wm8804_set_pll
+};
+
+#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+                       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_driver wm8804_dai = {
+       .name = "wm8804-spdif",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_192000,
+               .formats = WM8804_FORMATS,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_192000,
+               .formats = WM8804_FORMATS,
+       },
+       .ops = &wm8804_dai_ops,
+       .symmetric_rates = 1
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
+       .probe = wm8804_probe,
+       .remove = wm8804_remove,
+       .suspend = wm8804_suspend,
+       .resume = wm8804_resume,
+       .set_bias_level = wm8804_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
+       .reg_word_size = sizeof(u8),
+       .reg_cache_default = wm8804_reg_defs,
+       .volatile_register = wm8804_volatile
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8804_spi_probe(struct spi_device *spi)
+{
+       struct wm8804_priv *wm8804;
+       int ret;
+
+       wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+       if (!wm8804)
+               return -ENOMEM;
+
+       wm8804->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8804);
+
+       ret = snd_soc_register_codec(&spi->dev,
+                                    &soc_codec_dev_wm8804, &wm8804_dai, 1);
+       if (ret < 0)
+               kfree(wm8804);
+       return ret;
+}
+
+static int __devexit wm8804_spi_remove(struct spi_device *spi)
+{
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
+}
+
+static struct spi_driver wm8804_spi_driver = {
+       .driver = {
+               .name = "wm8804",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm8804_spi_probe,
+       .remove = __devexit_p(wm8804_spi_remove)
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8804_priv *wm8804;
+       int ret;
+
+       wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+       if (!wm8804)
+               return -ENOMEM;
+
+       wm8804->control_type = SND_SOC_I2C;
+       i2c_set_clientdata(i2c, wm8804);
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm8804, &wm8804_dai, 1);
+       if (ret < 0)
+               kfree(wm8804);
+       return ret;
+}
+
+static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm8804_i2c_id[] = {
+       { "wm8804", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
+
+static struct i2c_driver wm8804_i2c_driver = {
+       .driver = {
+               .name = "wm8804",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm8804_i2c_probe,
+       .remove = __devexit_p(wm8804_i2c_remove),
+       .id_table = wm8804_i2c_id
+};
+#endif
+
+static int __init wm8804_modinit(void)
+{
+       int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8804_i2c_driver);
+       if (ret) {
+               printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       ret = spi_register_driver(&wm8804_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
+                      ret);
+       }
+#endif
+       return ret;
+}
+module_init(wm8804_modinit);
+
+static void __exit wm8804_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8804_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8804_spi_driver);
+#endif
+}
+module_exit(wm8804_exit);
+
+MODULE_DESCRIPTION("ASoC WM8804 driver");
+MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
new file mode 100644 (file)
index 0000000..8ec14f5
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * wm8804.h  --  WM8804 S/PDIF transceiver driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8804_H
+#define _WM8804_H
+
+/*
+ * Register values.
+ */
+#define WM8804_RST_DEVID1                      0x00
+#define WM8804_DEVID2                          0x01
+#define WM8804_DEVREV                          0x02
+#define WM8804_PLL1                            0x03
+#define WM8804_PLL2                            0x04
+#define WM8804_PLL3                            0x05
+#define WM8804_PLL4                            0x06
+#define WM8804_PLL5                            0x07
+#define WM8804_PLL6                            0x08
+#define WM8804_SPDMODE                         0x09
+#define WM8804_INTMASK                         0x0A
+#define WM8804_INTSTAT                         0x0B
+#define WM8804_SPDSTAT                         0x0C
+#define WM8804_RXCHAN1                         0x0D
+#define WM8804_RXCHAN2                         0x0E
+#define WM8804_RXCHAN3                         0x0F
+#define WM8804_RXCHAN4                         0x10
+#define WM8804_RXCHAN5                         0x11
+#define WM8804_SPDTX1                          0x12
+#define WM8804_SPDTX2                          0x13
+#define WM8804_SPDTX3                          0x14
+#define WM8804_SPDTX4                          0x15
+#define WM8804_SPDTX5                          0x16
+#define WM8804_GPO0                            0x17
+#define WM8804_GPO1                            0x18
+#define WM8804_GPO2                            0x1A
+#define WM8804_AIFTX                           0x1B
+#define WM8804_AIFRX                           0x1C
+#define WM8804_SPDRX1                          0x1D
+#define WM8804_PWRDN                           0x1E
+
+#define WM8804_REGISTER_COUNT                  30
+#define WM8804_MAX_REGISTER                    0x1E
+
+#define WM8804_TX_CLKSRC_MCLK                  1
+#define WM8804_TX_CLKSRC_PLL                   2
+
+#define WM8804_CLKOUT_SRC_CLK1                 3
+#define WM8804_CLKOUT_SRC_OSCCLK               4
+
+#define WM8804_CLKOUT_DIV                      1
+
+#endif  /* _WM8804_H */
index 5da17a7..b4f1172 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 
 #define WM8900_LRC_MASK 0xfc00
 
-struct snd_soc_codec_device soc_codec_dev_wm8900;
-
 struct wm8900_priv {
-       struct snd_soc_codec codec;
-
+       enum snd_soc_control_type control_type;
        u16 reg_cache[WM8900_MAXREG];
 
        u32 fll_in; /* FLL input frequency */
@@ -627,8 +625,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        u16 reg;
 
        reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
@@ -1015,8 +1012,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = {
        .digital_mute   = wm8900_digital_mute,
 };
 
-struct snd_soc_dai wm8900_dai = {
-       .name = "WM8900 HiFi",
+static struct snd_soc_dai_driver wm8900_dai = {
+       .name = "wm8900-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -1033,7 +1030,6 @@ struct snd_soc_dai wm8900_dai = {
         },
        .ops = &wm8900_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8900_dai);
 
 static int wm8900_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
@@ -1128,10 +1124,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
        int fll_out = wm8900->fll_out;
        int fll_in  = wm8900->fll_in;
@@ -1140,7 +1134,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
        /* Stop the FLL in an orderly fashion */
        ret = wm8900_set_fll(codec, 0, 0, 0);
        if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to stop FLL\n");
+               dev_err(codec->dev, "Failed to stop FLL\n");
                return ret;
        }
 
@@ -1152,10 +1146,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int wm8900_resume(struct platform_device *pdev)
+static int wm8900_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
        u16 *cache;
        int i, ret;
@@ -1176,7 +1168,7 @@ static int wm8900_resume(struct platform_device *pdev)
 
                ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
                if (ret != 0) {
-                       dev_err(&pdev->dev, "Failed to restart FLL\n");
+                       dev_err(codec->dev, "Failed to restart FLL\n");
                        return ret;
                }
        }
@@ -1186,60 +1178,32 @@ static int wm8900_resume(struct platform_device *pdev)
                        snd_soc_write(codec, i, cache[i]);
                kfree(cache);
        } else
-               dev_err(&pdev->dev, "Unable to allocate register cache\n");
+               dev_err(codec->dev, "Unable to allocate register cache\n");
 
        return 0;
 }
 
-static struct snd_soc_codec *wm8900_codec;
-
-static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8900_probe(struct snd_soc_codec *codec)
 {
-       struct wm8900_priv *wm8900;
-       struct snd_soc_codec *codec;
-       unsigned int reg;
-       int ret;
-
-       wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
-       if (wm8900 == NULL)
-               return -ENOMEM;
+       struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0, reg;
 
-       codec = &wm8900->codec;
-       snd_soc_codec_set_drvdata(codec, wm8900);
-       codec->reg_cache = &wm8900->reg_cache[0];
-       codec->reg_cache_size = WM8900_MAXREG;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->name = "WM8900";
-       codec->owner = THIS_MODULE;
-       codec->dai = &wm8900_dai;
-       codec->num_dai = 1;
-       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);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type);
        if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
        reg = snd_soc_read(codec, WM8900_REG_ID);
        if (reg != 0x8900) {
-               dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
-               ret = -ENODEV;
-               goto err;
+               dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg);
+               return -ENODEV;
        }
 
        /* Read back from the chip */
        reg = snd_soc_read(codec, WM8900_REG_POWER1);
        reg = (reg >> 12) & 0xf;
-       dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
+       dev_info(codec->dev, "WM8900 revision %d\n", reg);
 
        wm8900_reset(codec);
 
@@ -1271,43 +1235,94 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
        /* Set the DAC and mixer output bias */
        snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
 
-       wm8900_dai.dev = &i2c->dev;
+       snd_soc_add_controls(codec, wm8900_snd_controls,
+                               ARRAY_SIZE(wm8900_snd_controls));
+       wm8900_add_widgets(codec);
 
-       wm8900_codec = codec;
+       return 0;
+}
 
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               goto err;
-       }
+/* power down chip */
+static int wm8900_remove(struct snd_soc_codec *codec)
+{
+       wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-       ret = snd_soc_register_dai(&wm8900_dai);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+static struct snd_soc_codec_driver soc_codec_dev_wm8900 = {
+       .probe =        wm8900_probe,
+       .remove =       wm8900_remove,
+       .suspend =      wm8900_suspend,
+       .resume =       wm8900_resume,
+       .set_bias_level = wm8900_set_bias_level,
+       .volatile_register = wm8900_volatile_register,
+       .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8900_reg_defaults,
+};
 
-       return ret;
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8900_spi_probe(struct spi_device *spi)
+{
+       struct wm8900_priv *wm8900;
+       int ret;
+
+       wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+       if (wm8900 == NULL)
+               return -ENOMEM;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8900);
-       wm8900_codec = NULL;
+       wm8900->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8900);
+
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8900, &wm8900_dai, 1);
+       if (ret < 0)
+               kfree(wm8900);
        return ret;
 }
 
-static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+static int __devexit wm8900_spi_remove(struct spi_device *spi)
 {
-       snd_soc_unregister_dai(&wm8900_dai);
-       snd_soc_unregister_codec(wm8900_codec);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
+}
 
-       wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF);
+static struct spi_driver wm8900_spi_driver = {
+       .driver = {
+               .name   = "wm8900-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8900_spi_probe,
+       .remove         = __devexit_p(wm8900_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8900_priv *wm8900;
+       int ret;
+
+       wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+       if (wm8900 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, wm8900);
+       wm8900->control_type = SND_SOC_I2C;
 
-       wm8900_dai.dev = NULL;
-       kfree(snd_soc_codec_get_drvdata(wm8900_codec));
-       wm8900_codec = NULL;
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8900, &wm8900_dai, 1);
+       if (ret < 0)
+               kfree(wm8900);
+       return ret;
+}
 
+static __devexit int wm8900_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1319,71 +1334,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
 
 static struct i2c_driver wm8900_i2c_driver = {
        .driver = {
-               .name = "WM8900",
+               .name = "wm8900-codec",
                .owner = THIS_MODULE,
        },
-       .probe = wm8900_i2c_probe,
-       .remove = __devexit_p(wm8900_i2c_remove),
+       .probe =    wm8900_i2c_probe,
+       .remove =   __devexit_p(wm8900_i2c_remove),
        .id_table = wm8900_i2c_id,
 };
+#endif
 
-static int wm8900_probe(struct platform_device *pdev)
+static int __init wm8900_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
        int ret = 0;
-
-       if (!wm8900_codec) {
-               dev_err(&pdev->dev, "I2C client not yet instantiated\n");
-               return -ENODEV;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8900_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n",
+                      ret);
        }
-
-       codec = wm8900_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 register new PCMs\n");
-               goto pcm_err;
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       ret = spi_register_driver(&wm8900_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n",
+                      ret);
        }
-
-       snd_soc_add_controls(codec, wm8900_snd_controls,
-                               ARRAY_SIZE(wm8900_snd_controls));
-       wm8900_add_widgets(codec);
-
-pcm_err:
+#endif
        return ret;
 }
-
-/* power down chip */
-static int wm8900_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_wm8900 = {
-       .probe =        wm8900_probe,
-       .remove =       wm8900_remove,
-       .suspend =      wm8900_suspend,
-       .resume =       wm8900_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
-
-static int __init wm8900_modinit(void)
-{
-       return i2c_add_driver(&wm8900_i2c_driver);
-}
 module_init(wm8900_modinit);
 
 static void __exit wm8900_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8900_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8900_spi_driver);
+#endif
 }
 module_exit(wm8900_exit);
 
index fd15007..583f257 100644 (file)
@@ -52,7 +52,4 @@
 #define WM8900_DAC_CLKDIV_5_5 0x14
 #define WM8900_DAC_CLKDIV_6   0x18
 
-extern struct snd_soc_dai wm8900_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8900;
-
 #endif
index bf08282..622b602 100644 (file)
@@ -213,10 +213,11 @@ static u16 wm8903_reg_defaults[] = {
 };
 
 struct wm8903_priv {
-       struct snd_soc_codec codec;
+
        u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
 
        int sysclk;
+       int irq;
 
        /* Reference counts */
        int class_w_users;
@@ -252,7 +253,6 @@ static int wm8903_volatile_register(unsigned int reg)
 static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
 {
        u16 reg[5];
-       struct i2c_client *i2c = codec->control_data;
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
        BUG_ON(start > 48);
@@ -262,7 +262,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
        snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
                      reg[0] | WM8903_WSEQ_ENA);
 
-       dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
+       dev_dbg(codec->dev, "Starting sequence at %d\n", start);
 
        snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
                     start | WM8903_WSEQ_START);
@@ -277,7 +277,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
                reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
        } while (reg[4] & WM8903_WSEQ_BUSY);
 
-       dev_dbg(&i2c->dev, "Sequence complete\n");
+       dev_dbg(codec->dev, "Sequence complete\n");
 
        /* Disable the sequencer again if we enabled it */
        snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
@@ -422,7 +422,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
        struct snd_soc_codec *codec = widget->codec;
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = codec->control_data;
        u16 reg;
        int ret;
 
@@ -431,7 +430,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        /* 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");
+                       dev_dbg(codec->dev, "Disabling Class W\n");
                        snd_soc_write(codec, WM8903_CLASS_W_0, reg &
                                     ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
                }
@@ -444,14 +443,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        /* If we've just disabled the last bypass path turn Class W on */
        if (!ucontrol->value.integer.value[0]) {
                if (wm8903->class_w_users == 1) {
-                       dev_dbg(&i2c->dev, "Enabling Class W\n");
+                       dev_dbg(codec->dev, "Enabling Class W\n");
                        snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
                wm8903->class_w_users--;
        }
 
-       dev_dbg(&i2c->dev, "Bypass use count now %d\n",
+       dev_dbg(codec->dev, "Bypass use count now %d\n",
                wm8903->class_w_users);
 
        return ret;
@@ -935,7 +934,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
 static int wm8903_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       struct i2c_client *i2c = codec->control_data;
        u16 reg, reg2;
 
        switch (level) {
@@ -974,7 +972,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
                        /* By default no bypass paths are enabled so
                         * enable Class W support.
                         */
-                       dev_dbg(&i2c->dev, "Enabling Class W\n");
+                       dev_dbg(codec->dev, "Enabling Class W\n");
                        snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
@@ -1228,10 +1226,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
                          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 snd_soc_codec *codec = rtd->codec;
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = codec->control_data;
        struct snd_pcm_runtime *master_runtime;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1245,7 +1241,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
        if (wm8903->master_substream) {
                master_runtime = wm8903->master_substream->runtime;
 
-               dev_dbg(&i2c->dev, "Constraining to %d bits\n",
+               dev_dbg(codec->dev, "Constraining to %d bits\n",
                        master_runtime->sample_bits);
 
                snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -1264,8 +1260,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1284,10 +1279,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec =rtd->codec;
        struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-       struct i2c_client *i2c = codec->control_data;
        int fs = params_rate(params);
        int bclk;
        int bclk_div;
@@ -1306,7 +1299,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
 
        if (substream == wm8903->slave_substream) {
-               dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
+               dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
                return 0;
        }
 
@@ -1332,7 +1325,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
                switch (sample_rates[dsp_config].rate) {
                case 88200:
                case 96000:
-                       dev_err(&i2c->dev, "%dHz unsupported by ADC\n",
+                       dev_err(codec->dev, "%dHz unsupported by ADC\n",
                                fs);
                        return -EINVAL;
 
@@ -1340,7 +1333,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
                        break;
                }
 
-       dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
+       dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
        clock1 &= ~WM8903_SAMPLE_RATE_MASK;
        clock1 |= sample_rates[dsp_config].value;
 
@@ -1366,7 +1359,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n",
+       dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n",
                wm8903->sysclk, fs);
 
        /* We may not have an MCLK which allows us to generate exactly
@@ -1401,12 +1394,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT;
        clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT;
 
-       dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
+       dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
                clk_sys_ratios[clk_config].rate,
                clk_sys_ratios[clk_config].mode,
                clk_sys_ratios[clk_config].div);
 
-       dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
+       dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
 
        /* We may not get quite the right frequency if using
         * approximate clocks so look for the closest match that is
@@ -1428,7 +1421,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        aif2 &= ~WM8903_BCLK_DIV_MASK;
        aif3 &= ~WM8903_LRCLK_RATE_MASK;
 
-       dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
+       dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
                bclk_divs[bclk_div].ratio / 10, bclk,
                (clk_sys * 10) / bclk_divs[bclk_div].ratio);
 
@@ -1504,8 +1497,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);
 
 static irqreturn_t wm8903_irq(int irq, void *data)
 {
-       struct wm8903_priv *wm8903 = data;
-       struct snd_soc_codec *codec = &wm8903->codec;
+       struct snd_soc_codec *codec = data;
+       struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
        int mic_report;
        int int_pol;
        int int_val = 0;
@@ -1586,8 +1579,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = {
        .set_sysclk     = wm8903_set_dai_sysclk,
 };
 
-struct snd_soc_dai wm8903_dai = {
-       .name = "WM8903",
+static struct snd_soc_dai_driver wm8903_dai = {
+       .name = "wm8903-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -1605,23 +1598,16 @@ struct snd_soc_dai wm8903_dai = {
        .ops = &wm8903_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8903_dai);
 
-static int wm8903_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8903_resume(struct platform_device *pdev)
+static int wm8903_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-       struct i2c_client *i2c = codec->control_data;
        int i;
        u16 *reg_cache = codec->reg_cache;
        u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
@@ -1637,65 +1623,37 @@ static int wm8903_resume(struct platform_device *pdev)
                                snd_soc_write(codec, i, tmp_cache[i]);
                kfree(tmp_cache);
        } else {
-               dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
+               dev_err(codec->dev, "Failed to allocate temporary cache\n");
        }
 
        return 0;
 }
 
-static struct snd_soc_codec *wm8903_codec;
-
-static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
-                                     const struct i2c_device_id *id)
+static int wm8903_probe(struct snd_soc_codec *codec)
 {
-       struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
-       struct wm8903_priv *wm8903;
-       struct snd_soc_codec *codec;
+       struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
+       struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
        int ret, i;
        int trigger, irq_pol;
        u16 val;
 
-       wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
-       if (wm8903 == NULL)
-               return -ENOMEM;
-
-       codec = &wm8903->codec;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->dev = &i2c->dev;
-       codec->name = "WM8903";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8903_set_bias_level;
-       codec->dai = &wm8903_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
-       codec->reg_cache = &wm8903->reg_cache[0];
-       snd_soc_codec_set_drvdata(codec, wm8903);
-       codec->volatile_register = wm8903_volatile_register;
        init_completion(&wm8903->wseq);
 
-       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;
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
        val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
        if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
-               dev_err(&i2c->dev,
+               dev_err(codec->dev,
                        "Device with ID register %x is not a WM8903\n", val);
                return -ENODEV;
        }
 
        val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
-       dev_info(&i2c->dev, "WM8903 revision %d\n",
+       dev_info(codec->dev, "WM8903 revision %d\n",
                 val & WM8903_CHIP_REV_MASK);
 
        wm8903_reset(codec);
@@ -1721,7 +1679,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
                wm8903->mic_delay = pdata->micdet_delay;
        }
        
-       if (i2c->irq) {
+       if (wm8903->irq) {
                if (pdata && pdata->irq_active_low) {
                        trigger = IRQF_TRIGGER_LOW;
                        irq_pol = WM8903_IRQ_POL;
@@ -1733,13 +1691,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
                snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
                                    WM8903_IRQ_POL, irq_pol);
                
-               ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq,
+               ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,
                                           trigger | IRQF_ONESHOT,
-                                          "wm8903", wm8903);
+                                          "wm8903", codec);
                if (ret != 0) {
-                       dev_err(&i2c->dev, "Failed to request IRQ: %d\n",
+                       dev_err(codec->dev, "Failed to request IRQ: %d\n",
                                ret);
-                       goto err;
+                       return ret;
                }
 
                /* Enable write sequencer interrupts */
@@ -1781,133 +1739,96 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        val |= WM8903_DAC_MUTEMODE;
        snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
 
-       wm8903_dai.dev = &i2c->dev;
-       wm8903_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
-               goto err_irq;
-       }
-
-       ret = snd_soc_register_dai(&wm8903_dai);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
-
-       return ret;
+       snd_soc_add_controls(codec, wm8903_snd_controls,
+                               ARRAY_SIZE(wm8903_snd_controls));
+       wm8903_add_widgets(codec);
 
-err_codec:
-       snd_soc_unregister_codec(codec);
-err_irq:
-       if (i2c->irq)
-               free_irq(i2c->irq, wm8903);
-err:
-       wm8903_codec = NULL;
-       kfree(wm8903);
        return ret;
 }
 
-static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+/* power down chip */
+static int wm8903_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec);
+       wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-       snd_soc_unregister_dai(&wm8903_dai);
-       snd_soc_unregister_codec(codec);
+static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
+       .probe =        wm8903_probe,
+       .remove =       wm8903_remove,
+       .suspend =      wm8903_suspend,
+       .resume =       wm8903_resume,
+       .set_bias_level = wm8903_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8903_reg_defaults,
+       .volatile_register = wm8903_volatile_register,
+};
 
-       wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8903_priv *wm8903;
+       int ret;
 
-       if (client->irq)
-               free_irq(client->irq, priv);
+       wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+       if (wm8903 == NULL)
+               return -ENOMEM;
 
-       kfree(priv);
+       i2c_set_clientdata(i2c, wm8903);
+       wm8903->irq = i2c->irq;
 
-       wm8903_codec = NULL;
-       wm8903_dai.dev = NULL;
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8903, &wm8903_dai, 1);
+       if (ret < 0)
+               kfree(wm8903);
+       return ret;
+}
 
+static __devexit int wm8903_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
-/* i2c codec control layer */
 static const struct i2c_device_id wm8903_i2c_id[] = {
-       { "wm8903", 0 },
-       { }
+       { "wm8903", 0 },
+       { }
 };
 MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
 
 static struct i2c_driver wm8903_i2c_driver = {
        .driver = {
-               .name = "WM8903",
+               .name = "wm8903-codec",
                .owner = THIS_MODULE,
        },
-       .probe    = wm8903_i2c_probe,
-       .remove   = __devexit_p(wm8903_i2c_remove),
+       .probe =    wm8903_i2c_probe,
+       .remove =   __devexit_p(wm8903_i2c_remove),
        .id_table = wm8903_i2c_id,
 };
+#endif
 
-static int wm8903_probe(struct platform_device *pdev)
+static int __init wm8903_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        int ret = 0;
-
-       if (!wm8903_codec) {
-               dev_err(&pdev->dev, "I2C device not yet probed\n");
-               goto err;
-       }
-
-       socdev->card->codec = wm8903_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 err;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8903_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
+                      ret);
        }
-
-       snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls,
-                               ARRAY_SIZE(wm8903_snd_controls));
-       wm8903_add_widgets(socdev->card->codec);
-
+#endif
        return ret;
-
-err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8903_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8903 = {
-       .probe =        wm8903_probe,
-       .remove =       wm8903_remove,
-       .suspend =      wm8903_suspend,
-       .resume =       wm8903_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
-
-static int __init wm8903_modinit(void)
-{
-       return i2c_add_driver(&wm8903_i2c_driver);
 }
 module_init(wm8903_modinit);
 
 static void __exit wm8903_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8903_i2c_driver);
+#endif
 }
 module_exit(wm8903_exit);
 
index ce384a2..996435e 100644 (file)
@@ -15,9 +15,6 @@
 
 #include <linux/i2c.h>
 
-extern struct snd_soc_dai wm8903_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8903;
-
 extern int wm8903_mic_detect(struct snd_soc_codec *codec,
                             struct snd_soc_jack *jack,
                             int det, int shrt);
index f7dcabf..33be84e 100644 (file)
@@ -31,9 +31,6 @@
 
 #include "wm8904.h"
 
-static struct snd_soc_codec *wm8904_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8904;
-
 enum wm8904_type {
        WM8904,
        WM8912,
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8904_priv {
-       struct snd_soc_codec codec;
+
        u16 reg_cache[WM8904_MAX_REGISTER + 1];
 
        enum wm8904_type devtype;
+       void *control_data;
 
        struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
 
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
        int value = ucontrol->value.integer.value[0];
 
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);  
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
        int value = ucontrol->value.integer.value[0];
 
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = {
        .digital_mute = wm8904_digital_mute,
 };
 
-struct snd_soc_dai wm8904_dai = {
-       .name = "WM8904",
+static struct snd_soc_dai_driver wm8904_dai = {
+       .name = "wm8904-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = {
        .ops = &wm8904_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8904_dai);
 
 #ifdef CONFIG_PM
-static int wm8904_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8904_resume(struct platform_device *pdev)
+static int wm8904_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev)
 #define wm8904_resume NULL
 #endif
 
-static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
+static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &wm8904->codec;
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
        struct snd_kcontrol_new control =
                SOC_ENUM_EXT("EQ Mode",
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
        wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
        wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
 
-       ret = snd_soc_add_controls(&wm8904->codec, &control, 1);
+       ret = snd_soc_add_controls(codec, &control, 1);
        if (ret != 0)
-               dev_err(wm8904->codec.dev,
+               dev_err(codec->dev,
                        "Failed to add ReTune Mobile control: %d\n", ret);
 }
 
-static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
+static void wm8904_handle_pdata(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = &wm8904->codec;
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
        int ret, i;
 
        if (!pdata) {
-               snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls,
+               snd_soc_add_controls(codec, wm8904_eq_controls,
                                     ARRAY_SIZE(wm8904_eq_controls));
                return;
        }
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
                wm8904->drc_texts = kmalloc(sizeof(char *)
                                            * pdata->num_drc_cfgs, GFP_KERNEL);
                if (!wm8904->drc_texts) {
-                       dev_err(wm8904->codec.dev,
+                       dev_err(codec->dev,
                                "Failed to allocate %d DRC config texts\n",
                                pdata->num_drc_cfgs);
                        return;
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
                wm8904->drc_enum.max = pdata->num_drc_cfgs;
                wm8904->drc_enum.texts = wm8904->drc_texts;
 
-               ret = snd_soc_add_controls(&wm8904->codec, &control, 1);
+               ret = snd_soc_add_controls(codec, &control, 1);
                if (ret != 0)
-                       dev_err(wm8904->codec.dev,
+                       dev_err(codec->dev,
                                "Failed to add DRC mode control: %d\n", ret);
 
                wm8904_set_drc(codec);
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
                pdata->num_retune_mobile_cfgs);
 
        if (pdata->num_retune_mobile_cfgs)
-               wm8904_handle_retune_mobile_pdata(wm8904);
+               wm8904_handle_retune_mobile_pdata(codec);
        else
-               snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls,
+               snd_soc_add_controls(codec, wm8904_eq_controls,
                                     ARRAY_SIZE(wm8904_eq_controls));
 }
 
-static int wm8904_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8904_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
 
-       socdev->card->codec = wm8904_codec;
-       codec = wm8904_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;
-       }
-
-       wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec));
-
-       wm8904_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-static int wm8904_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_wm8904 = {
-       .probe =        wm8904_probe,
-       .remove =       wm8904_remove,
-       .suspend =      wm8904_suspend,
-       .resume =       wm8904_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
-
-static int wm8904_register(struct wm8904_priv *wm8904,
-                          enum snd_soc_control_type control)
+static int wm8904_probe(struct snd_soc_codec *codec)
 {
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
-       int ret;
-       struct snd_soc_codec *codec = &wm8904->codec;
-       int i;
-
-       if (wm8904_codec) {
-               dev_err(codec->dev, "Another WM8904 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
+       int ret, i;
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8904);
-       codec->name = "WM8904";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8904_set_bias_level;
-       codec->dai = &wm8904_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8904_MAX_REGISTER;
-       codec->reg_cache = &wm8904->reg_cache;
-       codec->volatile_register = wm8904_volatile_register;
        codec->cache_sync = 1;
        codec->idle_bias_off = 1;
 
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904,
        default:
                dev_err(codec->dev, "Unknown device type %d\n",
                        wm8904->devtype);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
-       memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg));
-
-       ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+       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;
+               return ret;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904,
                                 wm8904->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904,
                goto err_enable;
        }
 
-       wm8904_dai.dev = codec->dev;
-
        /* Change some default settings - latch VU and enable ZC */
        wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
        wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
@@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904,
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
 
-       wm8904_codec = codec;
+       wm8904_handle_pdata(codec);
 
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err_enable;
-       }
-
-       ret = snd_soc_register_dai(&wm8904_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+       wm8904_add_widgets(codec);
 
        return 0;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
 err_get:
        regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-err:
-       kfree(wm8904);
        return ret;
 }
 
-static void wm8904_unregister(struct wm8904_priv *wm8904)
+static int wm8904_remove(struct snd_soc_codec *codec)
 {
-       wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF);
+       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+
+       wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
-       snd_soc_unregister_dai(&wm8904_dai);
-       snd_soc_unregister_codec(&wm8904->codec);
-       kfree(wm8904);
-       wm8904_codec = NULL;
+
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
+       .probe =        wm8904_probe,
+       .remove =       wm8904_remove,
+       .suspend =      wm8904_suspend,
+       .resume =       wm8904_resume,
+       .set_bias_level = wm8904_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8904_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8904_reg,
+       .volatile_register = wm8904_volatile_register,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8904_priv *wm8904;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
        if (wm8904 == NULL)
                return -ENOMEM;
 
-       codec = &wm8904->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        wm8904->devtype = id->driver_data;
-
        i2c_set_clientdata(i2c, wm8904);
-       codec->control_data = i2c;
+       wm8904->control_data = i2c;
        wm8904->pdata = i2c->dev.platform_data;
 
-       codec->dev = &i2c->dev;
-
-       return wm8904_register(wm8904, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8904, &wm8904_dai, 1);
+       if (ret < 0)
+               kfree(wm8904);
+       return ret;
 }
 
 static __devexit int wm8904_i2c_remove(struct i2c_client *client)
 {
-       struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
-       wm8904_unregister(wm8904);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
 
 static struct i2c_driver wm8904_i2c_driver = {
        .driver = {
-               .name = "WM8904",
+               .name = "wm8904-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8904_i2c_probe,
@@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = {
 
 static int __init wm8904_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8904_i2c_driver);
        if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n",
+               printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
                       ret);
        }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8904_modinit);
 
index abe5059..9e8c841 100644 (file)
@@ -21,9 +21,6 @@
 #define WM8904_FLL_LRCLK         3
 #define WM8904_FLL_FREE_RUNNING  4
 
-extern struct snd_soc_dai wm8904_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8904;
-
 /*
  * Register values.
  */
index f0c1113..2cb16f8 100644 (file)
@@ -44,7 +44,8 @@
 struct wm8940_priv {
        unsigned int sysclk;
        u16 reg_cache[WM8940_CACHEREGNUM];
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
 };
 
 static u16 wm8940_reg_defaults[] = {
@@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->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,
@@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = {
        .set_pll = wm8940_set_dai_pll,
 };
 
-struct snd_soc_dai wm8940_dai = {
-       .name = "WM8940",
+static struct snd_soc_dai_driver wm8940_dai = {
+       .name = "wm8940-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = {
        .ops = &wm8940_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8940_dai);
 
-static int wm8940_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
 }
 
-static int wm8940_resume(struct platform_device *pdev)
+static int wm8940_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        int i;
        int ret;
        u8 data[3];
@@ -697,108 +691,26 @@ error_ret:
        return ret;
 }
 
-static struct snd_soc_codec *wm8940_codec;
-
-static int wm8940_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-
-       int ret = 0;
-
-       if (wm8940_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8940_codec;
-       codec = wm8940_codec;
-
-       mutex_init(&codec->mutex);
-       /* 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;
-       }
-
-       ret = snd_soc_add_controls(codec, wm8940_snd_controls,
-                            ARRAY_SIZE(wm8940_snd_controls));
-       if (ret)
-               goto error_free_pcms;
-       ret = wm8940_add_widgets(codec);
-       if (ret)
-               goto error_free_pcms;
-
-       return ret;
-
-error_free_pcms:
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-pcm_err:
-       return ret;
-}
-
-static int wm8940_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_wm8940 = {
-       .probe = wm8940_probe,
-       .remove = wm8940_remove,
-       .suspend = wm8940_suspend,
-       .resume = wm8940_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
-
-static int wm8940_register(struct wm8940_priv *wm8940,
-                          enum snd_soc_control_type control)
+static int wm8940_probe(struct snd_soc_codec *codec)
 {
-       struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
-       struct snd_soc_codec *codec = &wm8940->codec;
+       struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
+       struct wm8940_setup_data *pdata = codec->dev->platform_data;
        int ret;
        u16 reg;
-       if (wm8940_codec) {
-               dev_err(codec->dev, "Another WM8940 is registered\n");
-               return -EINVAL;
-       }
-
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8940);
-       codec->name = "WM8940";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8940_set_bias_level;
-       codec->dai = &wm8940_dai;
-       codec->num_dai = 1;
-       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);
+       codec->control_data = wm8940->control_data;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
        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));
-
        ret = wm8940_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
                return ret;
        }
 
-       wm8940_dai.dev = codec->dev;
-
        wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
@@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940,
                        return ret;
        }
 
-
-       wm8940_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+       ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+                            ARRAY_SIZE(wm8940_snd_controls));
+       if (ret)
                return ret;
-       }
-
-       ret = snd_soc_register_dai(&wm8940_dai);
-       if (ret) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
+       ret = wm8940_add_widgets(codec);
+       if (ret)
                return ret;
-       }
 
-       return 0;
+       return ret;
+;
 }
 
-static void wm8940_unregister(struct wm8940_priv *wm8940)
+static int wm8940_remove(struct snd_soc_codec *codec)
 {
-       wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8940_dai);
-       snd_soc_unregister_codec(&wm8940->codec);
-       kfree(wm8940);
-       wm8940_codec = NULL;
+       wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-static int wm8940_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
+       .probe =        wm8940_probe,
+       .remove =       wm8940_remove,
+       .suspend =      wm8940_suspend,
+       .resume =       wm8940_resume,
+       .set_bias_level = wm8940_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8940_reg_defaults,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       int ret;
        struct wm8940_priv *wm8940;
-       struct snd_soc_codec *codec;
+       int ret;
 
-       wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL);
+       wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
        if (wm8940 == NULL)
                return -ENOMEM;
 
-       codec = &wm8940->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
        i2c_set_clientdata(i2c, wm8940);
-       codec->control_data = i2c;
-       codec->dev = &i2c->dev;
+       wm8940->control_data = i2c;
 
-       ret = wm8940_register(wm8940, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8940, &wm8940_dai, 1);
        if (ret < 0)
                kfree(wm8940);
-
        return ret;
 }
 
-static int __devexit wm8940_i2c_remove(struct i2c_client *client)
+static __devexit int wm8940_i2c_remove(struct i2c_client *client)
 {
-       struct wm8940_priv *wm8940 = i2c_get_clientdata(client);
-
-       wm8940_unregister(wm8940);
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
 
 static struct i2c_driver wm8940_i2c_driver = {
        .driver = {
-               .name = "WM8940 I2C Codec",
+               .name = "wm8940-codec",
                .owner = THIS_MODULE,
        },
-       .probe = wm8940_i2c_probe,
-       .remove = __devexit_p(wm8940_i2c_remove),
+       .probe =    wm8940_i2c_probe,
+       .remove =   __devexit_p(wm8940_i2c_remove),
        .id_table = wm8940_i2c_id,
 };
+#endif
 
 static int __init wm8940_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8940_i2c_driver);
-       if (ret)
-               printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n",
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
                       ret);
+       }
+#endif
        return ret;
 }
 module_init(wm8940_modinit);
 
 static void __exit wm8940_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8940_i2c_driver);
+#endif
 }
 module_exit(wm8940_exit);
 
index 8410eed..907fe19 100644 (file)
@@ -15,8 +15,6 @@ struct wm8940_setup_data {
 #define WM8940_VROI_30K 1
        unsigned int vroi:1;
 };
-extern struct snd_soc_dai wm8940_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8940;
 
 /* WM8940 register space */
 #define WM8940_SOFTRESET       0x00
index 5f02559..f89ad6c 100644 (file)
@@ -30,9 +30,6 @@
 
 #include "wm8955.h"
 
-static struct snd_soc_codec *wm8955_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8955;
-
 #define WM8955_NUM_SUPPLIES 4
 static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
        "DCVDD",
@@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
 
 /* codec private data */
 struct wm8955_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+
        u16 reg_cache[WM8955_MAX_REGISTER + 1];
 
        unsigned int mclk_rate;
@@ -52,8 +50,6 @@ struct wm8955_priv {
        int fs;
 
        struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
-
-       struct wm8955_pdata *pdata;
 };
 
 static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
@@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = {
        .digital_mute = wm8955_digital_mute,
 };
 
-struct snd_soc_dai wm8955_dai = {
-       .name = "WM8955",
+static struct snd_soc_dai_driver wm8955_dai = {
+       .name = "wm8955-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 2,
@@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = {
        },
        .ops = &wm8955_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8955_dai);
 
 #ifdef CONFIG_PM
-static int wm8955_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm8955_resume(struct platform_device *pdev)
+static int wm8955_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev)
 #define wm8955_resume NULL
 #endif
 
-static int wm8955_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8955_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8955_codec;
-       codec = wm8955_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;
-       }
-
-       wm8955_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-static int wm8955_remove(struct platform_device *pdev)
+static int wm8955_probe(struct snd_soc_codec *codec)
 {
-       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_wm8955 = {
-       .probe =        wm8955_probe,
-       .remove =       wm8955_remove,
-       .suspend =      wm8955_suspend,
-       .resume =       wm8955_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955);
-
-static int wm8955_register(struct wm8955_priv *wm8955,
-                          enum snd_soc_control_type control)
-{
-       int ret;
-       struct snd_soc_codec *codec = &wm8955->codec;
-       int i;
-
-       if (wm8955_codec) {
-               dev_err(codec->dev, "Another WM8955 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8955);
-       codec->name = "WM8955";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8955_set_bias_level;
-       codec->dai = &wm8955_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8955_MAX_REGISTER;
-       codec->reg_cache = &wm8955->reg_cache;
-
-       memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg));
+       struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+       struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
+       int ret, i;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
@@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955,
                                 wm8955->supplies);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
@@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955,
                goto err_enable;
        }
 
-       wm8955_dai.dev = codec->dev;
-
        /* Change some default settings - latch VU and enable ZC */
        wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
        wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
@@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955,
        wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
 
        /* Set platform data values */
-       if (wm8955->pdata) {
-               if (wm8955->pdata->out2_speaker)
+       if (pdata) {
+               if (pdata->out2_speaker)
                        wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
                                |= WM8955_ROUT2INV;
 
-               if (wm8955->pdata->monoin_diff)
+               if (pdata->monoin_diff)
                        wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
                                |= WM8955_DMEN;
        }
@@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955,
        /* Bias level configuration will have done an extra enable */
        regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
 
-       wm8955_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err_enable;
-       }
-
-       ret = snd_soc_register_dai(&wm8955_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
-
+       wm8955_add_widgets(codec);
        return 0;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
 err_get:
        regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
-err:
-       kfree(wm8955);
        return ret;
 }
 
-static void wm8955_unregister(struct wm8955_priv *wm8955)
+static int wm8955_remove(struct snd_soc_codec *codec)
 {
-       wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF);
+       struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
+       wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
        regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
-       snd_soc_unregister_dai(&wm8955_dai);
-       snd_soc_unregister_codec(&wm8955->codec);
-       kfree(wm8955);
-       wm8955_codec = NULL;
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
+       .probe =        wm8955_probe,
+       .remove =       wm8955_remove,
+       .suspend =      wm8955_suspend,
+       .resume =       wm8955_resume,
+       .set_bias_level = wm8955_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8955_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8955_reg,
+};
+
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8955_priv *wm8955;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
        if (wm8955 == NULL)
                return -ENOMEM;
 
-       codec = &wm8955->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        i2c_set_clientdata(i2c, wm8955);
-       codec->control_data = i2c;
-       wm8955->pdata = i2c->dev.platform_data;
-
-       codec->dev = &i2c->dev;
 
-       return wm8955_register(wm8955, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8955, &wm8955_dai, 1);
+       if (ret < 0)
+               kfree(wm8955);
+       return ret;
 }
 
 static __devexit int wm8955_i2c_remove(struct i2c_client *client)
 {
-       struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
-       wm8955_unregister(wm8955);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
 
 static struct i2c_driver wm8955_i2c_driver = {
        .driver = {
-               .name = "wm8955",
+               .name = "wm8955-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8955_i2c_probe,
@@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = {
 
 static int __init wm8955_modinit(void)
 {
-       int ret;
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8955_i2c_driver);
        if (ret != 0) {
@@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void)
                       ret);
        }
 #endif
-       return 0;
+       return ret;
 }
 module_init(wm8955_modinit);
 
index ae349c8..d13fd5c 100644 (file)
@@ -15,9 +15,6 @@
 
 #define WM8955_CLK_MCLK 1
 
-extern struct snd_soc_dai wm8955_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8955;
-
 /*
  * Register values.
  */
index 3c6ee61..8d5efb3 100644 (file)
@@ -29,8 +29,6 @@
 
 #define AUDIO_NAME "wm8960"
 
-struct snd_soc_codec_device soc_codec_dev_wm8960;
-
 /* R25 - Power 1 */
 #define WM8960_VMID_MASK 0x180
 #define WM8960_VREF      0x40
@@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
 
 struct wm8960_priv {
        u16 reg_cache[WM8960_CACHEREGNUM];
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
+       int (*set_bias_level)(struct snd_soc_codec *,
+                             enum snd_soc_bias_level level);
        struct snd_soc_dapm_widget *lout1;
        struct snd_soc_dapm_widget *rout1;
        struct snd_soc_dapm_widget *out3;
@@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
        int i;
@@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int wm8960_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+
+       return wm8960->set_bias_level(codec, level);
+}
+
 #define WM8960_RATES SNDRV_PCM_RATE_8000_48000
 
 #define WM8960_FORMATS \
@@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = {
        .set_pll = wm8960_set_dai_pll,
 };
 
-struct snd_soc_dai wm8960_dai = {
-       .name = "WM8960",
+static struct snd_soc_dai_driver wm8960_dai = {
+       .name = "wm8960-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = {
        .ops = &wm8960_dai_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8960_dai);
 
-static int wm8960_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       codec->set_bias_level(codec, SND_SOC_BIAS_OFF);
+       wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8960_resume(struct platform_device *pdev)
+static int wm8960_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
        int i;
        u8 data[2];
        u16 *cache = codec->reg_cache;
@@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev)
                codec->hw_write(codec->control_data, data, 2);
        }
 
-       codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
+       wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        return 0;
 }
 
-static struct snd_soc_codec *wm8960_codec;
-
-static int wm8960_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8960_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8960_codec;
-       codec = wm8960_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, wm8960_snd_controls,
-                            ARRAY_SIZE(wm8960_snd_controls));
-       wm8960_add_widgets(codec);
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8960_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_wm8960 = {
-       .probe =        wm8960_probe,
-       .remove =       wm8960_remove,
-       .suspend =      wm8960_suspend,
-       .resume =       wm8960_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
-
-static int wm8960_register(struct wm8960_priv *wm8960,
-                          enum snd_soc_control_type control)
+static int wm8960_probe(struct snd_soc_codec *codec)
 {
-       struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
-       struct snd_soc_codec *codec = &wm8960->codec;
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+       struct wm8960_data *pdata = dev_get_platdata(codec->dev);
        int ret;
        u16 reg;
 
-       if (wm8960_codec) {
-               dev_err(codec->dev, "Another WM8960 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       codec->set_bias_level = wm8960_set_bias_level_out3;
+       wm8960->set_bias_level = wm8960_set_bias_level_out3;
+       codec->control_data = wm8960->control_data;
 
        if (!pdata) {
                dev_warn(codec->dev, "No platform data supplied\n");
@@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960,
                }
 
                if (pdata->capless)
-                       codec->set_bias_level = wm8960_set_bias_level_capless;
+                       wm8960->set_bias_level = wm8960_set_bias_level_capless;
        }
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8960);
-       codec->name = "WM8960";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->dai = &wm8960_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8960_CACHEREGNUM;
-       codec->reg_cache = &wm8960->reg_cache;
-
-       memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
-
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        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;
-
-       codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
        reg = snd_soc_read(codec, WM8960_LINVOL);
@@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960,
        reg = snd_soc_read(codec, WM8960_ROUT2);
        snd_soc_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;
-       }
-
-       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_add_controls(codec, wm8960_snd_controls,
+                                    ARRAY_SIZE(wm8960_snd_controls));
+       wm8960_add_widgets(codec);
 
        return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8960);
-       return ret;
 }
 
-static void wm8960_unregister(struct wm8960_priv *wm8960)
+/* power down chip */
+static int wm8960_remove(struct snd_soc_codec *codec)
 {
-       wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8960_dai);
-       snd_soc_unregister_codec(&wm8960->codec);
-       kfree(wm8960);
-       wm8960_codec = NULL;
+       struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
+
+       wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
+       .probe =        wm8960_probe,
+       .remove =       wm8960_remove,
+       .suspend =      wm8960_suspend,
+       .resume =       wm8960_resume,
+       .set_bias_level = wm8960_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8960_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8960_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8960_priv *wm8960;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
        if (wm8960 == NULL)
                return -ENOMEM;
 
-       codec = &wm8960->codec;
-
        i2c_set_clientdata(i2c, wm8960);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
+       wm8960->control_data = i2c;
 
-       return wm8960_register(wm8960, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8960, &wm8960_dai, 1);
+       if (ret < 0)
+               kfree(wm8960);
+       return ret;
 }
 
 static __devexit int wm8960_i2c_remove(struct i2c_client *client)
 {
-       struct wm8960_priv *wm8960 = i2c_get_clientdata(client);
-       wm8960_unregister(wm8960);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
 
 static struct i2c_driver wm8960_i2c_driver = {
        .driver = {
-               .name = "wm8960",
+               .name = "wm8960-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8960_i2c_probe,
        .remove =   __devexit_p(wm8960_i2c_remove),
        .id_table = wm8960_i2c_id,
 };
+#endif
 
 static int __init wm8960_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8960_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
                       ret);
        }
-
+#endif
        return ret;
 }
 module_init(wm8960_modinit);
 
 static void __exit wm8960_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8960_i2c_driver);
+#endif
 }
 module_exit(wm8960_exit);
 
-
 MODULE_DESCRIPTION("ASoC WM8960 driver");
 MODULE_AUTHOR("Liam Girdwood");
 MODULE_LICENSE("GPL");
index a5ef654..2d8163d 100644 (file)
 #define WM8960_OPCLK_DIV_5_5           (4 << 0)
 #define WM8960_OPCLK_DIV_6             (5 << 0)
 
-extern struct snd_soc_dai wm8960_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8960;
-
 #endif
index 2549d3a..4f326f6 100644 (file)
@@ -288,7 +288,7 @@ static u16 wm8961_reg_defaults[] = {
 };
 
 struct wm8961_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        int sysclk;
        u16 reg_cache[WM8961_MAX_REGISTER];
 };
@@ -940,8 +940,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = {
        .set_clkdiv = wm8961_set_clkdiv,
 };
 
-struct snd_soc_dai wm8961_dai = {
-       .name = "WM8961",
+static struct snd_soc_dai_driver wm8961_dai = {
+       .name = "wm8961-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -956,140 +956,22 @@ struct snd_soc_dai wm8961_dai = {
                .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)
+static int wm8961_probe(struct snd_soc_codec *codec)
 {
-       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));
-
-       return ret;
-
-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 (reg_cache[i] == wm8961_reg_defaults[i])
-                       continue;
-
-               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);
-
-       snd_soc_codec_set_drvdata(codec, 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;
+               return ret;
        }
 
        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;
+               return -EINVAL;
        }
 
        /* This isn't volatile - readback doesn't correspond to write */
@@ -1102,7 +984,7 @@ static int wm8961_register(struct wm8961_priv *wm8961)
        ret = wm8961_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               goto err;
+               return ret;
        }
 
        /* Enable class W */
@@ -1140,64 +1022,89 @@ static int wm8961_register(struct wm8961_priv *wm8961)
 
        wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       wm8961_dai.dev = codec->dev;
+       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));
 
-       wm8961_codec = codec;
+       return 0;
+}
 
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err;
-       }
+static int wm8961_remove(struct snd_soc_codec *codec)
+{
+       wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
 
-       ret = snd_soc_register_dai(&wm8961_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+#ifdef CONFIG_PM
+static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8961);
-       return ret;
 }
 
-static void wm8961_unregister(struct wm8961_priv *wm8961)
+static int wm8961_resume(struct snd_soc_codec *codec)
 {
-       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;
+       u16 *reg_cache = codec->reg_cache;
+       int i;
+
+       for (i = 0; i < codec->driver->reg_cache_size; i++) {
+               if (reg_cache[i] == wm8961_reg_defaults[i])
+                       continue;
+
+               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
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8961 = {
+       .probe =        wm8961_probe,
+       .remove =       wm8961_remove,
+       .suspend =      wm8961_suspend,
+       .resume =       wm8961_resume,
+       .set_bias_level = wm8961_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8961_reg_defaults,
+       .volatile_register = wm8961_volatile_register,
+};
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 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;
+       int ret;
 
        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);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8961, &wm8961_dai, 1);
+       if (ret < 0)
+               kfree(wm8961);
+       return ret;
 }
 
 static __devexit int wm8961_i2c_remove(struct i2c_client *client)
 {
-       struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
-       wm8961_unregister(wm8961);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1209,35 +1116,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
 
 static struct i2c_driver wm8961_i2c_driver = {
        .driver = {
-               .name = "wm8961",
+               .name = "wm8961-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8961_i2c_probe,
        .remove =   __devexit_p(wm8961_i2c_remove),
        .id_table = wm8961_i2c_id,
 };
+#endif
 
 static int __init wm8961_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8961_i2c_driver);
        if (ret != 0) {
-               printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
+               printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n",
                       ret);
        }
-
+#endif
        return ret;
 }
 module_init(wm8961_modinit);
 
 static void __exit wm8961_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8961_i2c_driver);
+#endif
 }
 module_exit(wm8961_exit);
 
-
 MODULE_DESCRIPTION("ASoC WM8961 driver");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
index 5513bfd..1d736e5 100644 (file)
@@ -11,9 +11,6 @@
 
 #include <sound/soc.h>
 
-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
 
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
new file mode 100644 (file)
index 0000000..894d0cd
--- /dev/null
@@ -0,0 +1,3977 @@
+/*
+ * wm8962.c  --  WM8962 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm8962.h>
+
+#include "wm8962.h"
+
+#define WM8962_NUM_SUPPLIES 8
+static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
+       "DCVDD",
+       "DBVDD",
+       "AVDD",
+       "CPVDD",
+       "MICVDD",
+       "PLLVDD",
+       "SPKVDD1",
+       "SPKVDD2",
+};
+
+/* codec private data */
+struct wm8962_priv {
+       struct snd_soc_codec *codec;
+
+       u16 reg_cache[WM8962_MAX_REGISTER + 1];
+
+       int sysclk;
+       int sysclk_rate;
+
+       int bclk;  /* Desired BCLK */
+       int lrclk;
+
+       int fll_src;
+       int fll_fref;
+       int fll_fout;
+
+       struct delayed_work mic_work;
+       struct snd_soc_jack *jack;
+
+       struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
+       struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       struct input_dev *beep;
+       struct work_struct beep_work;
+       int beep_rate;
+#endif
+
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip gpio_chip;
+#endif
+};
+
+/* We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8962_REGULATOR_EVENT(n) \
+static int wm8962_regulator_event_##n(struct notifier_block *nb, \
+                                   unsigned long event, void *data)    \
+{ \
+       struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
+                                                 disable_nb[n]); \
+       if (event & REGULATOR_EVENT_DISABLE) { \
+               wm8962->codec->cache_sync = 1; \
+       } \
+       return 0; \
+}
+
+WM8962_REGULATOR_EVENT(0)
+WM8962_REGULATOR_EVENT(1)
+WM8962_REGULATOR_EVENT(2)
+WM8962_REGULATOR_EVENT(3)
+WM8962_REGULATOR_EVENT(4)
+WM8962_REGULATOR_EVENT(5)
+WM8962_REGULATOR_EVENT(6)
+WM8962_REGULATOR_EVENT(7)
+
+static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
+       [0] = 0x009F,     /* R0     - Left Input volume */
+       [1] = 0x049F,     /* R1     - Right Input volume */
+       [2] = 0x0000,     /* R2     - HPOUTL volume */
+       [3] = 0x0000,     /* R3     - HPOUTR volume */
+       [4] = 0x0020,     /* R4     - Clocking1 */
+       [5] = 0x0018,     /* R5     - ADC & DAC Control 1 */
+       [6] = 0x2008,     /* R6     - ADC & DAC Control 2 */
+       [7] = 0x000A,     /* R7     - Audio Interface 0 */
+       [8] = 0x01E4,     /* R8     - Clocking2 */
+       [9] = 0x0300,     /* R9     - Audio Interface 1 */
+       [10] = 0x00C0,    /* R10    - Left DAC volume */
+       [11] = 0x00C0,    /* R11    - Right DAC volume */
+
+       [14] = 0x0040,     /* R14    - Audio Interface 2 */
+       [15] = 0x6243,     /* R15    - Software Reset */
+
+       [17] = 0x007B,     /* R17    - ALC1 */
+       [18] = 0x0000,     /* R18    - ALC2 */
+       [19] = 0x1C32,     /* R19    - ALC3 */
+       [20] = 0x3200,     /* R20    - Noise Gate */
+       [21] = 0x00C0,     /* R21    - Left ADC volume */
+       [22] = 0x00C0,     /* R22    - Right ADC volume */
+       [23] = 0x0160,     /* R23    - Additional control(1) */
+       [24] = 0x0000,     /* R24    - Additional control(2) */
+       [25] = 0x0000,     /* R25    - Pwr Mgmt (1) */
+       [26] = 0x0000,     /* R26    - Pwr Mgmt (2) */
+       [27] = 0x0010,     /* R27    - Additional Control (3) */
+       [28] = 0x0000,     /* R28    - Anti-pop */
+
+       [30] = 0x005E,     /* R30    - Clocking 3 */
+       [31] = 0x0000,     /* R31    - Input mixer control (1) */
+       [32] = 0x0145,     /* R32    - Left input mixer volume */
+       [33] = 0x0145,     /* R33    - Right input mixer volume */
+       [34] = 0x0009,     /* R34    - Input mixer control (2) */
+       [35] = 0x0003,     /* R35    - Input bias control */
+       [37] = 0x0008,     /* R37    - Left input PGA control */
+       [38] = 0x0008,     /* R38    - Right input PGA control */
+
+       [40] = 0x0000,     /* R40    - SPKOUTL volume */
+       [41] = 0x0000,     /* R41    - SPKOUTR volume */
+
+       [47] = 0x0000,     /* R47    - Thermal Shutdown Status */
+       [48] = 0x8027,     /* R48    - Additional Control (4) */
+       [49] = 0x0010,     /* R49    - Class D Control 1 */
+
+       [51] = 0x0003,     /* R51    - Class D Control 2 */
+
+       [56] = 0x0506,     /* R56    - Clocking 4 */
+       [57] = 0x0000,     /* R57    - DAC DSP Mixing (1) */
+       [58] = 0x0000,     /* R58    - DAC DSP Mixing (2) */
+
+       [60] = 0x0300,     /* R60    - DC Servo 0 */
+       [61] = 0x0300,     /* R61    - DC Servo 1 */
+
+       [64] = 0x0810,     /* R64    - DC Servo 4 */
+
+       [66] = 0x0000,     /* R66    - DC Servo 6 */
+
+       [68] = 0x001B,     /* R68    - Analogue PGA Bias */
+       [69] = 0x0000,     /* R69    - Analogue HP 0 */
+
+       [71] = 0x01FB,     /* R71    - Analogue HP 2 */
+       [72] = 0x0000,     /* R72    - Charge Pump 1 */
+
+       [82] = 0x0004,     /* R82    - Charge Pump B */
+
+       [87] = 0x0000,     /* R87    - Write Sequencer Control 1 */
+
+       [90] = 0x0000,     /* R90    - Write Sequencer Control 2 */
+
+       [93] = 0x0000,     /* R93    - Write Sequencer Control 3 */
+       [94] = 0x0000,     /* R94    - Control Interface */
+
+       [99] = 0x0000,     /* R99    - Mixer Enables */
+       [100] = 0x0000,     /* R100   - Headphone Mixer (1) */
+       [101] = 0x0000,     /* R101   - Headphone Mixer (2) */
+       [102] = 0x013F,     /* R102   - Headphone Mixer (3) */
+       [103] = 0x013F,     /* R103   - Headphone Mixer (4) */
+
+       [105] = 0x0000,     /* R105   - Speaker Mixer (1) */
+       [106] = 0x0000,     /* R106   - Speaker Mixer (2) */
+       [107] = 0x013F,     /* R107   - Speaker Mixer (3) */
+       [108] = 0x013F,     /* R108   - Speaker Mixer (4) */
+       [109] = 0x0003,     /* R109   - Speaker Mixer (5) */
+       [110] = 0x0002,     /* R110   - Beep Generator (1) */
+
+       [115] = 0x0006,     /* R115   - Oscillator Trim (3) */
+       [116] = 0x0026,     /* R116   - Oscillator Trim (4) */
+
+       [119] = 0x0000,     /* R119   - Oscillator Trim (7) */
+
+       [124] = 0x0011,     /* R124   - Analogue Clocking1 */
+       [125] = 0x004B,     /* R125   - Analogue Clocking2 */
+       [126] = 0x000D,     /* R126   - Analogue Clocking3 */
+       [127] = 0x0000,     /* R127   - PLL Software Reset */
+
+       [129] = 0x0000,     /* R129   - PLL2 */
+
+       [131] = 0x0000,     /* R131   - PLL 4 */
+
+       [136] = 0x0067,     /* R136   - PLL 9 */
+       [137] = 0x001C,     /* R137   - PLL 10 */
+       [138] = 0x0071,     /* R138   - PLL 11 */
+       [139] = 0x00C7,     /* R139   - PLL 12 */
+       [140] = 0x0067,     /* R140   - PLL 13 */
+       [141] = 0x0048,     /* R141   - PLL 14 */
+       [142] = 0x0022,     /* R142   - PLL 15 */
+       [143] = 0x0097,     /* R143   - PLL 16 */
+
+       [155] = 0x000C,     /* R155   - FLL Control (1) */
+       [156] = 0x0039,     /* R156   - FLL Control (2) */
+       [157] = 0x0180,     /* R157   - FLL Control (3) */
+
+       [159] = 0x0032,     /* R159   - FLL Control (5) */
+       [160] = 0x0018,     /* R160   - FLL Control (6) */
+       [161] = 0x007D,     /* R161   - FLL Control (7) */
+       [162] = 0x0008,     /* R162   - FLL Control (8) */
+
+       [252] = 0x0005,     /* R252   - General test 1 */
+
+       [256] = 0x0000,     /* R256   - DF1 */
+       [257] = 0x0000,     /* R257   - DF2 */
+       [258] = 0x0000,     /* R258   - DF3 */
+       [259] = 0x0000,     /* R259   - DF4 */
+       [260] = 0x0000,     /* R260   - DF5 */
+       [261] = 0x0000,     /* R261   - DF6 */
+       [262] = 0x0000,     /* R262   - DF7 */
+
+       [264] = 0x0000,     /* R264   - LHPF1 */
+       [265] = 0x0000,     /* R265   - LHPF2 */
+
+       [268] = 0x0000,     /* R268   - THREED1 */
+       [269] = 0x0000,     /* R269   - THREED2 */
+       [270] = 0x0000,     /* R270   - THREED3 */
+       [271] = 0x0000,     /* R271   - THREED4 */
+
+       [276] = 0x000C,     /* R276   - DRC 1 */
+       [277] = 0x0925,     /* R277   - DRC 2 */
+       [278] = 0x0000,     /* R278   - DRC 3 */
+       [279] = 0x0000,     /* R279   - DRC 4 */
+       [280] = 0x0000,     /* R280   - DRC 5 */
+
+       [285] = 0x0000,     /* R285   - Tloopback */
+
+       [335] = 0x0004,     /* R335   - EQ1 */
+       [336] = 0x6318,     /* R336   - EQ2 */
+       [337] = 0x6300,     /* R337   - EQ3 */
+       [338] = 0x0FCA,     /* R338   - EQ4 */
+       [339] = 0x0400,     /* R339   - EQ5 */
+       [340] = 0x00D8,     /* R340   - EQ6 */
+       [341] = 0x1EB5,     /* R341   - EQ7 */
+       [342] = 0xF145,     /* R342   - EQ8 */
+       [343] = 0x0B75,     /* R343   - EQ9 */
+       [344] = 0x01C5,     /* R344   - EQ10 */
+       [345] = 0x1C58,     /* R345   - EQ11 */
+       [346] = 0xF373,     /* R346   - EQ12 */
+       [347] = 0x0A54,     /* R347   - EQ13 */
+       [348] = 0x0558,     /* R348   - EQ14 */
+       [349] = 0x168E,     /* R349   - EQ15 */
+       [350] = 0xF829,     /* R350   - EQ16 */
+       [351] = 0x07AD,     /* R351   - EQ17 */
+       [352] = 0x1103,     /* R352   - EQ18 */
+       [353] = 0x0564,     /* R353   - EQ19 */
+       [354] = 0x0559,     /* R354   - EQ20 */
+       [355] = 0x4000,     /* R355   - EQ21 */
+       [356] = 0x6318,     /* R356   - EQ22 */
+       [357] = 0x6300,     /* R357   - EQ23 */
+       [358] = 0x0FCA,     /* R358   - EQ24 */
+       [359] = 0x0400,     /* R359   - EQ25 */
+       [360] = 0x00D8,     /* R360   - EQ26 */
+       [361] = 0x1EB5,     /* R361   - EQ27 */
+       [362] = 0xF145,     /* R362   - EQ28 */
+       [363] = 0x0B75,     /* R363   - EQ29 */
+       [364] = 0x01C5,     /* R364   - EQ30 */
+       [365] = 0x1C58,     /* R365   - EQ31 */
+       [366] = 0xF373,     /* R366   - EQ32 */
+       [367] = 0x0A54,     /* R367   - EQ33 */
+       [368] = 0x0558,     /* R368   - EQ34 */
+       [369] = 0x168E,     /* R369   - EQ35 */
+       [370] = 0xF829,     /* R370   - EQ36 */
+       [371] = 0x07AD,     /* R371   - EQ37 */
+       [372] = 0x1103,     /* R372   - EQ38 */
+       [373] = 0x0564,     /* R373   - EQ39 */
+       [374] = 0x0559,     /* R374   - EQ40 */
+       [375] = 0x4000,     /* R375   - EQ41 */
+
+       [513] = 0x0000,     /* R513   - GPIO 2 */
+       [514] = 0x0000,     /* R514   - GPIO 3 */
+
+       [516] = 0x8100,     /* R516   - GPIO 5 */
+       [517] = 0x8100,     /* R517   - GPIO 6 */
+
+       [560] = 0x0000,     /* R560   - Interrupt Status 1 */
+       [561] = 0x0000,     /* R561   - Interrupt Status 2 */
+
+       [568] = 0x0030,     /* R568   - Interrupt Status 1 Mask */
+       [569] = 0xFFED,     /* R569   - Interrupt Status 2 Mask */
+
+       [576] = 0x0000,     /* R576   - Interrupt Control */
+
+       [584] = 0x002D,     /* R584   - IRQ Debounce */
+
+       [586] = 0x0000,     /* R586   -  MICINT Source Pol */
+
+       [768] = 0x1C00,     /* R768   - DSP2 Power Management */
+
+       [1037] = 0x0000,     /* R1037  - DSP2_ExecControl */
+
+       [8192] = 0x0000,     /* R8192  - DSP2 Instruction RAM 0 */
+
+       [9216] = 0x0030,     /* R9216  - DSP2 Address RAM 2 */
+       [9217] = 0x0000,     /* R9217  - DSP2 Address RAM 1 */
+       [9218] = 0x0000,     /* R9218  - DSP2 Address RAM 0 */
+
+       [12288] = 0x0000,     /* R12288 - DSP2 Data1 RAM 1 */
+       [12289] = 0x0000,     /* R12289 - DSP2 Data1 RAM 0 */
+
+       [13312] = 0x0000,     /* R13312 - DSP2 Data2 RAM 1 */
+       [13313] = 0x0000,     /* R13313 - DSP2 Data2 RAM 0 */
+
+       [14336] = 0x0000,     /* R14336 - DSP2 Data3 RAM 1 */
+       [14337] = 0x0000,     /* R14337 - DSP2 Data3 RAM 0 */
+
+       [15360] = 0x000A,     /* R15360 - DSP2 Coeff RAM 0 */
+
+       [16384] = 0x0000,     /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+       [16385] = 0x0000,     /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+       [16386] = 0x0000,     /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+       [16387] = 0x0000,     /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+       [16388] = 0x0000,     /* R16388 - SOUNDSTAGE_ENABLES_1 */
+       [16389] = 0x0000,     /* R16389 - SOUNDSTAGE_ENABLES_0 */
+
+       [16896] = 0x0002,     /* R16896 - HDBASS_AI_1 */
+       [16897] = 0xBD12,     /* R16897 - HDBASS_AI_0 */
+       [16898] = 0x007C,     /* R16898 - HDBASS_AR_1 */
+       [16899] = 0x586C,     /* R16899 - HDBASS_AR_0 */
+       [16900] = 0x0053,     /* R16900 - HDBASS_B_1 */
+       [16901] = 0x8121,     /* R16901 - HDBASS_B_0 */
+       [16902] = 0x003F,     /* R16902 - HDBASS_K_1 */
+       [16903] = 0x8BD8,     /* R16903 - HDBASS_K_0 */
+       [16904] = 0x0032,     /* R16904 - HDBASS_N1_1 */
+       [16905] = 0xF52D,     /* R16905 - HDBASS_N1_0 */
+       [16906] = 0x0065,     /* R16906 - HDBASS_N2_1 */
+       [16907] = 0xAC8C,     /* R16907 - HDBASS_N2_0 */
+       [16908] = 0x006B,     /* R16908 - HDBASS_N3_1 */
+       [16909] = 0xE087,     /* R16909 - HDBASS_N3_0 */
+       [16910] = 0x0072,     /* R16910 - HDBASS_N4_1 */
+       [16911] = 0x1483,     /* R16911 - HDBASS_N4_0 */
+       [16912] = 0x0072,     /* R16912 - HDBASS_N5_1 */
+       [16913] = 0x1483,     /* R16913 - HDBASS_N5_0 */
+       [16914] = 0x0043,     /* R16914 - HDBASS_X1_1 */
+       [16915] = 0x3525,     /* R16915 - HDBASS_X1_0 */
+       [16916] = 0x0006,     /* R16916 - HDBASS_X2_1 */
+       [16917] = 0x6A4A,     /* R16917 - HDBASS_X2_0 */
+       [16918] = 0x0043,     /* R16918 - HDBASS_X3_1 */
+       [16919] = 0x6079,     /* R16919 - HDBASS_X3_0 */
+       [16920] = 0x0008,     /* R16920 - HDBASS_ATK_1 */
+       [16921] = 0x0000,     /* R16921 - HDBASS_ATK_0 */
+       [16922] = 0x0001,     /* R16922 - HDBASS_DCY_1 */
+       [16923] = 0x0000,     /* R16923 - HDBASS_DCY_0 */
+       [16924] = 0x0059,     /* R16924 - HDBASS_PG_1 */
+       [16925] = 0x999A,     /* R16925 - HDBASS_PG_0 */
+
+       [17048] = 0x0083,     /* R17408 - HPF_C_1 */
+       [17049] = 0x98AD,     /* R17409 - HPF_C_0 */
+
+       [17920] = 0x007F,     /* R17920 - ADCL_RETUNE_C1_1 */
+       [17921] = 0xFFFF,     /* R17921 - ADCL_RETUNE_C1_0 */
+       [17922] = 0x0000,     /* R17922 - ADCL_RETUNE_C2_1 */
+       [17923] = 0x0000,     /* R17923 - ADCL_RETUNE_C2_0 */
+       [17924] = 0x0000,     /* R17924 - ADCL_RETUNE_C3_1 */
+       [17925] = 0x0000,     /* R17925 - ADCL_RETUNE_C3_0 */
+       [17926] = 0x0000,     /* R17926 - ADCL_RETUNE_C4_1 */
+       [17927] = 0x0000,     /* R17927 - ADCL_RETUNE_C4_0 */
+       [17928] = 0x0000,     /* R17928 - ADCL_RETUNE_C5_1 */
+       [17929] = 0x0000,     /* R17929 - ADCL_RETUNE_C5_0 */
+       [17930] = 0x0000,     /* R17930 - ADCL_RETUNE_C6_1 */
+       [17931] = 0x0000,     /* R17931 - ADCL_RETUNE_C6_0 */
+       [17932] = 0x0000,     /* R17932 - ADCL_RETUNE_C7_1 */
+       [17933] = 0x0000,     /* R17933 - ADCL_RETUNE_C7_0 */
+       [17934] = 0x0000,     /* R17934 - ADCL_RETUNE_C8_1 */
+       [17935] = 0x0000,     /* R17935 - ADCL_RETUNE_C8_0 */
+       [17936] = 0x0000,     /* R17936 - ADCL_RETUNE_C9_1 */
+       [17937] = 0x0000,     /* R17937 - ADCL_RETUNE_C9_0 */
+       [17938] = 0x0000,     /* R17938 - ADCL_RETUNE_C10_1 */
+       [17939] = 0x0000,     /* R17939 - ADCL_RETUNE_C10_0 */
+       [17940] = 0x0000,     /* R17940 - ADCL_RETUNE_C11_1 */
+       [17941] = 0x0000,     /* R17941 - ADCL_RETUNE_C11_0 */
+       [17942] = 0x0000,     /* R17942 - ADCL_RETUNE_C12_1 */
+       [17943] = 0x0000,     /* R17943 - ADCL_RETUNE_C12_0 */
+       [17944] = 0x0000,     /* R17944 - ADCL_RETUNE_C13_1 */
+       [17945] = 0x0000,     /* R17945 - ADCL_RETUNE_C13_0 */
+       [17946] = 0x0000,     /* R17946 - ADCL_RETUNE_C14_1 */
+       [17947] = 0x0000,     /* R17947 - ADCL_RETUNE_C14_0 */
+       [17948] = 0x0000,     /* R17948 - ADCL_RETUNE_C15_1 */
+       [17949] = 0x0000,     /* R17949 - ADCL_RETUNE_C15_0 */
+       [17950] = 0x0000,     /* R17950 - ADCL_RETUNE_C16_1 */
+       [17951] = 0x0000,     /* R17951 - ADCL_RETUNE_C16_0 */
+       [17952] = 0x0000,     /* R17952 - ADCL_RETUNE_C17_1 */
+       [17953] = 0x0000,     /* R17953 - ADCL_RETUNE_C17_0 */
+       [17954] = 0x0000,     /* R17954 - ADCL_RETUNE_C18_1 */
+       [17955] = 0x0000,     /* R17955 - ADCL_RETUNE_C18_0 */
+       [17956] = 0x0000,     /* R17956 - ADCL_RETUNE_C19_1 */
+       [17957] = 0x0000,     /* R17957 - ADCL_RETUNE_C19_0 */
+       [17958] = 0x0000,     /* R17958 - ADCL_RETUNE_C20_1 */
+       [17959] = 0x0000,     /* R17959 - ADCL_RETUNE_C20_0 */
+       [17960] = 0x0000,     /* R17960 - ADCL_RETUNE_C21_1 */
+       [17961] = 0x0000,     /* R17961 - ADCL_RETUNE_C21_0 */
+       [17962] = 0x0000,     /* R17962 - ADCL_RETUNE_C22_1 */
+       [17963] = 0x0000,     /* R17963 - ADCL_RETUNE_C22_0 */
+       [17964] = 0x0000,     /* R17964 - ADCL_RETUNE_C23_1 */
+       [17965] = 0x0000,     /* R17965 - ADCL_RETUNE_C23_0 */
+       [17966] = 0x0000,     /* R17966 - ADCL_RETUNE_C24_1 */
+       [17967] = 0x0000,     /* R17967 - ADCL_RETUNE_C24_0 */
+       [17968] = 0x0000,     /* R17968 - ADCL_RETUNE_C25_1 */
+       [17969] = 0x0000,     /* R17969 - ADCL_RETUNE_C25_0 */
+       [17970] = 0x0000,     /* R17970 - ADCL_RETUNE_C26_1 */
+       [17971] = 0x0000,     /* R17971 - ADCL_RETUNE_C26_0 */
+       [17972] = 0x0000,     /* R17972 - ADCL_RETUNE_C27_1 */
+       [17973] = 0x0000,     /* R17973 - ADCL_RETUNE_C27_0 */
+       [17974] = 0x0000,     /* R17974 - ADCL_RETUNE_C28_1 */
+       [17975] = 0x0000,     /* R17975 - ADCL_RETUNE_C28_0 */
+       [17976] = 0x0000,     /* R17976 - ADCL_RETUNE_C29_1 */
+       [17977] = 0x0000,     /* R17977 - ADCL_RETUNE_C29_0 */
+       [17978] = 0x0000,     /* R17978 - ADCL_RETUNE_C30_1 */
+       [17979] = 0x0000,     /* R17979 - ADCL_RETUNE_C30_0 */
+       [17980] = 0x0000,     /* R17980 - ADCL_RETUNE_C31_1 */
+       [17981] = 0x0000,     /* R17981 - ADCL_RETUNE_C31_0 */
+       [17982] = 0x0000,     /* R17982 - ADCL_RETUNE_C32_1 */
+       [17983] = 0x0000,     /* R17983 - ADCL_RETUNE_C32_0 */
+
+       [18432] = 0x0020,     /* R18432 - RETUNEADC_PG2_1 */
+       [18433] = 0x0000,     /* R18433 - RETUNEADC_PG2_0 */
+       [18434] = 0x0040,     /* R18434 - RETUNEADC_PG_1 */
+       [18435] = 0x0000,     /* R18435 - RETUNEADC_PG_0 */
+
+       [18944] = 0x007F,     /* R18944 - ADCR_RETUNE_C1_1 */
+       [18945] = 0xFFFF,     /* R18945 - ADCR_RETUNE_C1_0 */
+       [18946] = 0x0000,     /* R18946 - ADCR_RETUNE_C2_1 */
+       [18947] = 0x0000,     /* R18947 - ADCR_RETUNE_C2_0 */
+       [18948] = 0x0000,     /* R18948 - ADCR_RETUNE_C3_1 */
+       [18949] = 0x0000,     /* R18949 - ADCR_RETUNE_C3_0 */
+       [18950] = 0x0000,     /* R18950 - ADCR_RETUNE_C4_1 */
+       [18951] = 0x0000,     /* R18951 - ADCR_RETUNE_C4_0 */
+       [18952] = 0x0000,     /* R18952 - ADCR_RETUNE_C5_1 */
+       [18953] = 0x0000,     /* R18953 - ADCR_RETUNE_C5_0 */
+       [18954] = 0x0000,     /* R18954 - ADCR_RETUNE_C6_1 */
+       [18955] = 0x0000,     /* R18955 - ADCR_RETUNE_C6_0 */
+       [18956] = 0x0000,     /* R18956 - ADCR_RETUNE_C7_1 */
+       [18957] = 0x0000,     /* R18957 - ADCR_RETUNE_C7_0 */
+       [18958] = 0x0000,     /* R18958 - ADCR_RETUNE_C8_1 */
+       [18959] = 0x0000,     /* R18959 - ADCR_RETUNE_C8_0 */
+       [18960] = 0x0000,     /* R18960 - ADCR_RETUNE_C9_1 */
+       [18961] = 0x0000,     /* R18961 - ADCR_RETUNE_C9_0 */
+       [18962] = 0x0000,     /* R18962 - ADCR_RETUNE_C10_1 */
+       [18963] = 0x0000,     /* R18963 - ADCR_RETUNE_C10_0 */
+       [18964] = 0x0000,     /* R18964 - ADCR_RETUNE_C11_1 */
+       [18965] = 0x0000,     /* R18965 - ADCR_RETUNE_C11_0 */
+       [18966] = 0x0000,     /* R18966 - ADCR_RETUNE_C12_1 */
+       [18967] = 0x0000,     /* R18967 - ADCR_RETUNE_C12_0 */
+       [18968] = 0x0000,     /* R18968 - ADCR_RETUNE_C13_1 */
+       [18969] = 0x0000,     /* R18969 - ADCR_RETUNE_C13_0 */
+       [18970] = 0x0000,     /* R18970 - ADCR_RETUNE_C14_1 */
+       [18971] = 0x0000,     /* R18971 - ADCR_RETUNE_C14_0 */
+       [18972] = 0x0000,     /* R18972 - ADCR_RETUNE_C15_1 */
+       [18973] = 0x0000,     /* R18973 - ADCR_RETUNE_C15_0 */
+       [18974] = 0x0000,     /* R18974 - ADCR_RETUNE_C16_1 */
+       [18975] = 0x0000,     /* R18975 - ADCR_RETUNE_C16_0 */
+       [18976] = 0x0000,     /* R18976 - ADCR_RETUNE_C17_1 */
+       [18977] = 0x0000,     /* R18977 - ADCR_RETUNE_C17_0 */
+       [18978] = 0x0000,     /* R18978 - ADCR_RETUNE_C18_1 */
+       [18979] = 0x0000,     /* R18979 - ADCR_RETUNE_C18_0 */
+       [18980] = 0x0000,     /* R18980 - ADCR_RETUNE_C19_1 */
+       [18981] = 0x0000,     /* R18981 - ADCR_RETUNE_C19_0 */
+       [18982] = 0x0000,     /* R18982 - ADCR_RETUNE_C20_1 */
+       [18983] = 0x0000,     /* R18983 - ADCR_RETUNE_C20_0 */
+       [18984] = 0x0000,     /* R18984 - ADCR_RETUNE_C21_1 */
+       [18985] = 0x0000,     /* R18985 - ADCR_RETUNE_C21_0 */
+       [18986] = 0x0000,     /* R18986 - ADCR_RETUNE_C22_1 */
+       [18987] = 0x0000,     /* R18987 - ADCR_RETUNE_C22_0 */
+       [18988] = 0x0000,     /* R18988 - ADCR_RETUNE_C23_1 */
+       [18989] = 0x0000,     /* R18989 - ADCR_RETUNE_C23_0 */
+       [18990] = 0x0000,     /* R18990 - ADCR_RETUNE_C24_1 */
+       [18991] = 0x0000,     /* R18991 - ADCR_RETUNE_C24_0 */
+       [18992] = 0x0000,     /* R18992 - ADCR_RETUNE_C25_1 */
+       [18993] = 0x0000,     /* R18993 - ADCR_RETUNE_C25_0 */
+       [18994] = 0x0000,     /* R18994 - ADCR_RETUNE_C26_1 */
+       [18995] = 0x0000,     /* R18995 - ADCR_RETUNE_C26_0 */
+       [18996] = 0x0000,     /* R18996 - ADCR_RETUNE_C27_1 */
+       [18997] = 0x0000,     /* R18997 - ADCR_RETUNE_C27_0 */
+       [18998] = 0x0000,     /* R18998 - ADCR_RETUNE_C28_1 */
+       [18999] = 0x0000,     /* R18999 - ADCR_RETUNE_C28_0 */
+       [19000] = 0x0000,     /* R19000 - ADCR_RETUNE_C29_1 */
+       [19001] = 0x0000,     /* R19001 - ADCR_RETUNE_C29_0 */
+       [19002] = 0x0000,     /* R19002 - ADCR_RETUNE_C30_1 */
+       [19003] = 0x0000,     /* R19003 - ADCR_RETUNE_C30_0 */
+       [19004] = 0x0000,     /* R19004 - ADCR_RETUNE_C31_1 */
+       [19005] = 0x0000,     /* R19005 - ADCR_RETUNE_C31_0 */
+       [19006] = 0x0000,     /* R19006 - ADCR_RETUNE_C32_1 */
+       [19007] = 0x0000,     /* R19007 - ADCR_RETUNE_C32_0 */
+
+       [19456] = 0x007F,     /* R19456 - DACL_RETUNE_C1_1 */
+       [19457] = 0xFFFF,     /* R19457 - DACL_RETUNE_C1_0 */
+       [19458] = 0x0000,     /* R19458 - DACL_RETUNE_C2_1 */
+       [19459] = 0x0000,     /* R19459 - DACL_RETUNE_C2_0 */
+       [19460] = 0x0000,     /* R19460 - DACL_RETUNE_C3_1 */
+       [19461] = 0x0000,     /* R19461 - DACL_RETUNE_C3_0 */
+       [19462] = 0x0000,     /* R19462 - DACL_RETUNE_C4_1 */
+       [19463] = 0x0000,     /* R19463 - DACL_RETUNE_C4_0 */
+       [19464] = 0x0000,     /* R19464 - DACL_RETUNE_C5_1 */
+       [19465] = 0x0000,     /* R19465 - DACL_RETUNE_C5_0 */
+       [19466] = 0x0000,     /* R19466 - DACL_RETUNE_C6_1 */
+       [19467] = 0x0000,     /* R19467 - DACL_RETUNE_C6_0 */
+       [19468] = 0x0000,     /* R19468 - DACL_RETUNE_C7_1 */
+       [19469] = 0x0000,     /* R19469 - DACL_RETUNE_C7_0 */
+       [19470] = 0x0000,     /* R19470 - DACL_RETUNE_C8_1 */
+       [19471] = 0x0000,     /* R19471 - DACL_RETUNE_C8_0 */
+       [19472] = 0x0000,     /* R19472 - DACL_RETUNE_C9_1 */
+       [19473] = 0x0000,     /* R19473 - DACL_RETUNE_C9_0 */
+       [19474] = 0x0000,     /* R19474 - DACL_RETUNE_C10_1 */
+       [19475] = 0x0000,     /* R19475 - DACL_RETUNE_C10_0 */
+       [19476] = 0x0000,     /* R19476 - DACL_RETUNE_C11_1 */
+       [19477] = 0x0000,     /* R19477 - DACL_RETUNE_C11_0 */
+       [19478] = 0x0000,     /* R19478 - DACL_RETUNE_C12_1 */
+       [19479] = 0x0000,     /* R19479 - DACL_RETUNE_C12_0 */
+       [19480] = 0x0000,     /* R19480 - DACL_RETUNE_C13_1 */
+       [19481] = 0x0000,     /* R19481 - DACL_RETUNE_C13_0 */
+       [19482] = 0x0000,     /* R19482 - DACL_RETUNE_C14_1 */
+       [19483] = 0x0000,     /* R19483 - DACL_RETUNE_C14_0 */
+       [19484] = 0x0000,     /* R19484 - DACL_RETUNE_C15_1 */
+       [19485] = 0x0000,     /* R19485 - DACL_RETUNE_C15_0 */
+       [19486] = 0x0000,     /* R19486 - DACL_RETUNE_C16_1 */
+       [19487] = 0x0000,     /* R19487 - DACL_RETUNE_C16_0 */
+       [19488] = 0x0000,     /* R19488 - DACL_RETUNE_C17_1 */
+       [19489] = 0x0000,     /* R19489 - DACL_RETUNE_C17_0 */
+       [19490] = 0x0000,     /* R19490 - DACL_RETUNE_C18_1 */
+       [19491] = 0x0000,     /* R19491 - DACL_RETUNE_C18_0 */
+       [19492] = 0x0000,     /* R19492 - DACL_RETUNE_C19_1 */
+       [19493] = 0x0000,     /* R19493 - DACL_RETUNE_C19_0 */
+       [19494] = 0x0000,     /* R19494 - DACL_RETUNE_C20_1 */
+       [19495] = 0x0000,     /* R19495 - DACL_RETUNE_C20_0 */
+       [19496] = 0x0000,     /* R19496 - DACL_RETUNE_C21_1 */
+       [19497] = 0x0000,     /* R19497 - DACL_RETUNE_C21_0 */
+       [19498] = 0x0000,     /* R19498 - DACL_RETUNE_C22_1 */
+       [19499] = 0x0000,     /* R19499 - DACL_RETUNE_C22_0 */
+       [19500] = 0x0000,     /* R19500 - DACL_RETUNE_C23_1 */
+       [19501] = 0x0000,     /* R19501 - DACL_RETUNE_C23_0 */
+       [19502] = 0x0000,     /* R19502 - DACL_RETUNE_C24_1 */
+       [19503] = 0x0000,     /* R19503 - DACL_RETUNE_C24_0 */
+       [19504] = 0x0000,     /* R19504 - DACL_RETUNE_C25_1 */
+       [19505] = 0x0000,     /* R19505 - DACL_RETUNE_C25_0 */
+       [19506] = 0x0000,     /* R19506 - DACL_RETUNE_C26_1 */
+       [19507] = 0x0000,     /* R19507 - DACL_RETUNE_C26_0 */
+       [19508] = 0x0000,     /* R19508 - DACL_RETUNE_C27_1 */
+       [19509] = 0x0000,     /* R19509 - DACL_RETUNE_C27_0 */
+       [19510] = 0x0000,     /* R19510 - DACL_RETUNE_C28_1 */
+       [19511] = 0x0000,     /* R19511 - DACL_RETUNE_C28_0 */
+       [19512] = 0x0000,     /* R19512 - DACL_RETUNE_C29_1 */
+       [19513] = 0x0000,     /* R19513 - DACL_RETUNE_C29_0 */
+       [19514] = 0x0000,     /* R19514 - DACL_RETUNE_C30_1 */
+       [19515] = 0x0000,     /* R19515 - DACL_RETUNE_C30_0 */
+       [19516] = 0x0000,     /* R19516 - DACL_RETUNE_C31_1 */
+       [19517] = 0x0000,     /* R19517 - DACL_RETUNE_C31_0 */
+       [19518] = 0x0000,     /* R19518 - DACL_RETUNE_C32_1 */
+       [19519] = 0x0000,     /* R19519 - DACL_RETUNE_C32_0 */
+
+       [19968] = 0x0020,     /* R19968 - RETUNEDAC_PG2_1 */
+       [19969] = 0x0000,     /* R19969 - RETUNEDAC_PG2_0 */
+       [19970] = 0x0040,     /* R19970 - RETUNEDAC_PG_1 */
+       [19971] = 0x0000,     /* R19971 - RETUNEDAC_PG_0 */
+
+       [20480] = 0x007F,     /* R20480 - DACR_RETUNE_C1_1 */
+       [20481] = 0xFFFF,     /* R20481 - DACR_RETUNE_C1_0 */
+       [20482] = 0x0000,     /* R20482 - DACR_RETUNE_C2_1 */
+       [20483] = 0x0000,     /* R20483 - DACR_RETUNE_C2_0 */
+       [20484] = 0x0000,     /* R20484 - DACR_RETUNE_C3_1 */
+       [20485] = 0x0000,     /* R20485 - DACR_RETUNE_C3_0 */
+       [20486] = 0x0000,     /* R20486 - DACR_RETUNE_C4_1 */
+       [20487] = 0x0000,     /* R20487 - DACR_RETUNE_C4_0 */
+       [20488] = 0x0000,     /* R20488 - DACR_RETUNE_C5_1 */
+       [20489] = 0x0000,     /* R20489 - DACR_RETUNE_C5_0 */
+       [20490] = 0x0000,     /* R20490 - DACR_RETUNE_C6_1 */
+       [20491] = 0x0000,     /* R20491 - DACR_RETUNE_C6_0 */
+       [20492] = 0x0000,     /* R20492 - DACR_RETUNE_C7_1 */
+       [20493] = 0x0000,     /* R20493 - DACR_RETUNE_C7_0 */
+       [20494] = 0x0000,     /* R20494 - DACR_RETUNE_C8_1 */
+       [20495] = 0x0000,     /* R20495 - DACR_RETUNE_C8_0 */
+       [20496] = 0x0000,     /* R20496 - DACR_RETUNE_C9_1 */
+       [20497] = 0x0000,     /* R20497 - DACR_RETUNE_C9_0 */
+       [20498] = 0x0000,     /* R20498 - DACR_RETUNE_C10_1 */
+       [20499] = 0x0000,     /* R20499 - DACR_RETUNE_C10_0 */
+       [20500] = 0x0000,     /* R20500 - DACR_RETUNE_C11_1 */
+       [20501] = 0x0000,     /* R20501 - DACR_RETUNE_C11_0 */
+       [20502] = 0x0000,     /* R20502 - DACR_RETUNE_C12_1 */
+       [20503] = 0x0000,     /* R20503 - DACR_RETUNE_C12_0 */
+       [20504] = 0x0000,     /* R20504 - DACR_RETUNE_C13_1 */
+       [20505] = 0x0000,     /* R20505 - DACR_RETUNE_C13_0 */
+       [20506] = 0x0000,     /* R20506 - DACR_RETUNE_C14_1 */
+       [20507] = 0x0000,     /* R20507 - DACR_RETUNE_C14_0 */
+       [20508] = 0x0000,     /* R20508 - DACR_RETUNE_C15_1 */
+       [20509] = 0x0000,     /* R20509 - DACR_RETUNE_C15_0 */
+       [20510] = 0x0000,     /* R20510 - DACR_RETUNE_C16_1 */
+       [20511] = 0x0000,     /* R20511 - DACR_RETUNE_C16_0 */
+       [20512] = 0x0000,     /* R20512 - DACR_RETUNE_C17_1 */
+       [20513] = 0x0000,     /* R20513 - DACR_RETUNE_C17_0 */
+       [20514] = 0x0000,     /* R20514 - DACR_RETUNE_C18_1 */
+       [20515] = 0x0000,     /* R20515 - DACR_RETUNE_C18_0 */
+       [20516] = 0x0000,     /* R20516 - DACR_RETUNE_C19_1 */
+       [20517] = 0x0000,     /* R20517 - DACR_RETUNE_C19_0 */
+       [20518] = 0x0000,     /* R20518 - DACR_RETUNE_C20_1 */
+       [20519] = 0x0000,     /* R20519 - DACR_RETUNE_C20_0 */
+       [20520] = 0x0000,     /* R20520 - DACR_RETUNE_C21_1 */
+       [20521] = 0x0000,     /* R20521 - DACR_RETUNE_C21_0 */
+       [20522] = 0x0000,     /* R20522 - DACR_RETUNE_C22_1 */
+       [20523] = 0x0000,     /* R20523 - DACR_RETUNE_C22_0 */
+       [20524] = 0x0000,     /* R20524 - DACR_RETUNE_C23_1 */
+       [20525] = 0x0000,     /* R20525 - DACR_RETUNE_C23_0 */
+       [20526] = 0x0000,     /* R20526 - DACR_RETUNE_C24_1 */
+       [20527] = 0x0000,     /* R20527 - DACR_RETUNE_C24_0 */
+       [20528] = 0x0000,     /* R20528 - DACR_RETUNE_C25_1 */
+       [20529] = 0x0000,     /* R20529 - DACR_RETUNE_C25_0 */
+       [20530] = 0x0000,     /* R20530 - DACR_RETUNE_C26_1 */
+       [20531] = 0x0000,     /* R20531 - DACR_RETUNE_C26_0 */
+       [20532] = 0x0000,     /* R20532 - DACR_RETUNE_C27_1 */
+       [20533] = 0x0000,     /* R20533 - DACR_RETUNE_C27_0 */
+       [20534] = 0x0000,     /* R20534 - DACR_RETUNE_C28_1 */
+       [20535] = 0x0000,     /* R20535 - DACR_RETUNE_C28_0 */
+       [20536] = 0x0000,     /* R20536 - DACR_RETUNE_C29_1 */
+       [20537] = 0x0000,     /* R20537 - DACR_RETUNE_C29_0 */
+       [20538] = 0x0000,     /* R20538 - DACR_RETUNE_C30_1 */
+       [20539] = 0x0000,     /* R20539 - DACR_RETUNE_C30_0 */
+       [20540] = 0x0000,     /* R20540 - DACR_RETUNE_C31_1 */
+       [20541] = 0x0000,     /* R20541 - DACR_RETUNE_C31_0 */
+       [20542] = 0x0000,     /* R20542 - DACR_RETUNE_C32_1 */
+       [20543] = 0x0000,     /* R20543 - DACR_RETUNE_C32_0 */
+
+       [20992] = 0x008C,     /* R20992 - VSS_XHD2_1 */
+       [20993] = 0x0200,     /* R20993 - VSS_XHD2_0 */
+       [20994] = 0x0035,     /* R20994 - VSS_XHD3_1 */
+       [20995] = 0x0700,     /* R20995 - VSS_XHD3_0 */
+       [20996] = 0x003A,     /* R20996 - VSS_XHN1_1 */
+       [20997] = 0x4100,     /* R20997 - VSS_XHN1_0 */
+       [20998] = 0x008B,     /* R20998 - VSS_XHN2_1 */
+       [20999] = 0x7D00,     /* R20999 - VSS_XHN2_0 */
+       [21000] = 0x003A,     /* R21000 - VSS_XHN3_1 */
+       [21001] = 0x4100,     /* R21001 - VSS_XHN3_0 */
+       [21002] = 0x008C,     /* R21002 - VSS_XLA_1 */
+       [21003] = 0xFEE8,     /* R21003 - VSS_XLA_0 */
+       [21004] = 0x0078,     /* R21004 - VSS_XLB_1 */
+       [21005] = 0x0000,     /* R21005 - VSS_XLB_0 */
+       [21006] = 0x003F,     /* R21006 - VSS_XLG_1 */
+       [21007] = 0xB260,     /* R21007 - VSS_XLG_0 */
+       [21008] = 0x002D,     /* R21008 - VSS_PG2_1 */
+       [21009] = 0x1818,     /* R21009 - VSS_PG2_0 */
+       [21010] = 0x0020,     /* R21010 - VSS_PG_1 */
+       [21011] = 0x0000,     /* R21011 - VSS_PG_0 */
+       [21012] = 0x00F1,     /* R21012 - VSS_XTD1_1 */
+       [21013] = 0x8340,     /* R21013 - VSS_XTD1_0 */
+       [21014] = 0x00FB,     /* R21014 - VSS_XTD2_1 */
+       [21015] = 0x8300,     /* R21015 - VSS_XTD2_0 */
+       [21016] = 0x00EE,     /* R21016 - VSS_XTD3_1 */
+       [21017] = 0xAEC0,     /* R21017 - VSS_XTD3_0 */
+       [21018] = 0x00FB,     /* R21018 - VSS_XTD4_1 */
+       [21019] = 0xAC40,     /* R21019 - VSS_XTD4_0 */
+       [21020] = 0x00F1,     /* R21020 - VSS_XTD5_1 */
+       [21021] = 0x7F80,     /* R21021 - VSS_XTD5_0 */
+       [21022] = 0x00F4,     /* R21022 - VSS_XTD6_1 */
+       [21023] = 0x3B40,     /* R21023 - VSS_XTD6_0 */
+       [21024] = 0x00F5,     /* R21024 - VSS_XTD7_1 */
+       [21025] = 0xFB00,     /* R21025 - VSS_XTD7_0 */
+       [21026] = 0x00EA,     /* R21026 - VSS_XTD8_1 */
+       [21027] = 0x10C0,     /* R21027 - VSS_XTD8_0 */
+       [21028] = 0x00FC,     /* R21028 - VSS_XTD9_1 */
+       [21029] = 0xC580,     /* R21029 - VSS_XTD9_0 */
+       [21030] = 0x00E2,     /* R21030 - VSS_XTD10_1 */
+       [21031] = 0x75C0,     /* R21031 - VSS_XTD10_0 */
+       [21032] = 0x0004,     /* R21032 - VSS_XTD11_1 */
+       [21033] = 0xB480,     /* R21033 - VSS_XTD11_0 */
+       [21034] = 0x00D4,     /* R21034 - VSS_XTD12_1 */
+       [21035] = 0xF980,     /* R21035 - VSS_XTD12_0 */
+       [21036] = 0x0004,     /* R21036 - VSS_XTD13_1 */
+       [21037] = 0x9140,     /* R21037 - VSS_XTD13_0 */
+       [21038] = 0x00D8,     /* R21038 - VSS_XTD14_1 */
+       [21039] = 0xA480,     /* R21039 - VSS_XTD14_0 */
+       [21040] = 0x0002,     /* R21040 - VSS_XTD15_1 */
+       [21041] = 0x3DC0,     /* R21041 - VSS_XTD15_0 */
+       [21042] = 0x00CF,     /* R21042 - VSS_XTD16_1 */
+       [21043] = 0x7A80,     /* R21043 - VSS_XTD16_0 */
+       [21044] = 0x00DC,     /* R21044 - VSS_XTD17_1 */
+       [21045] = 0x0600,     /* R21045 - VSS_XTD17_0 */
+       [21046] = 0x00F2,     /* R21046 - VSS_XTD18_1 */
+       [21047] = 0xDAC0,     /* R21047 - VSS_XTD18_0 */
+       [21048] = 0x00BA,     /* R21048 - VSS_XTD19_1 */
+       [21049] = 0xF340,     /* R21049 - VSS_XTD19_0 */
+       [21050] = 0x000A,     /* R21050 - VSS_XTD20_1 */
+       [21051] = 0x7940,     /* R21051 - VSS_XTD20_0 */
+       [21052] = 0x001C,     /* R21052 - VSS_XTD21_1 */
+       [21053] = 0x0680,     /* R21053 - VSS_XTD21_0 */
+       [21054] = 0x00FD,     /* R21054 - VSS_XTD22_1 */
+       [21055] = 0x2D00,     /* R21055 - VSS_XTD22_0 */
+       [21056] = 0x001C,     /* R21056 - VSS_XTD23_1 */
+       [21057] = 0xE840,     /* R21057 - VSS_XTD23_0 */
+       [21058] = 0x000D,     /* R21058 - VSS_XTD24_1 */
+       [21059] = 0xDC40,     /* R21059 - VSS_XTD24_0 */
+       [21060] = 0x00FC,     /* R21060 - VSS_XTD25_1 */
+       [21061] = 0x9D00,     /* R21061 - VSS_XTD25_0 */
+       [21062] = 0x0009,     /* R21062 - VSS_XTD26_1 */
+       [21063] = 0x5580,     /* R21063 - VSS_XTD26_0 */
+       [21064] = 0x00FE,     /* R21064 - VSS_XTD27_1 */
+       [21065] = 0x7E80,     /* R21065 - VSS_XTD27_0 */
+       [21066] = 0x000E,     /* R21066 - VSS_XTD28_1 */
+       [21067] = 0xAB40,     /* R21067 - VSS_XTD28_0 */
+       [21068] = 0x00F9,     /* R21068 - VSS_XTD29_1 */
+       [21069] = 0x9880,     /* R21069 - VSS_XTD29_0 */
+       [21070] = 0x0009,     /* R21070 - VSS_XTD30_1 */
+       [21071] = 0x87C0,     /* R21071 - VSS_XTD30_0 */
+       [21072] = 0x00FD,     /* R21072 - VSS_XTD31_1 */
+       [21073] = 0x2C40,     /* R21073 - VSS_XTD31_0 */
+       [21074] = 0x0009,     /* R21074 - VSS_XTD32_1 */
+       [21075] = 0x4800,     /* R21075 - VSS_XTD32_0 */
+       [21076] = 0x0003,     /* R21076 - VSS_XTS1_1 */
+       [21077] = 0x5F40,     /* R21077 - VSS_XTS1_0 */
+       [21078] = 0x0000,     /* R21078 - VSS_XTS2_1 */
+       [21079] = 0x8700,     /* R21079 - VSS_XTS2_0 */
+       [21080] = 0x00FA,     /* R21080 - VSS_XTS3_1 */
+       [21081] = 0xE4C0,     /* R21081 - VSS_XTS3_0 */
+       [21082] = 0x0000,     /* R21082 - VSS_XTS4_1 */
+       [21083] = 0x0B40,     /* R21083 - VSS_XTS4_0 */
+       [21084] = 0x0004,     /* R21084 - VSS_XTS5_1 */
+       [21085] = 0xE180,     /* R21085 - VSS_XTS5_0 */
+       [21086] = 0x0001,     /* R21086 - VSS_XTS6_1 */
+       [21087] = 0x1F40,     /* R21087 - VSS_XTS6_0 */
+       [21088] = 0x00F8,     /* R21088 - VSS_XTS7_1 */
+       [21089] = 0xB000,     /* R21089 - VSS_XTS7_0 */
+       [21090] = 0x00FB,     /* R21090 - VSS_XTS8_1 */
+       [21091] = 0xCBC0,     /* R21091 - VSS_XTS8_0 */
+       [21092] = 0x0004,     /* R21092 - VSS_XTS9_1 */
+       [21093] = 0xF380,     /* R21093 - VSS_XTS9_0 */
+       [21094] = 0x0007,     /* R21094 - VSS_XTS10_1 */
+       [21095] = 0xDF40,     /* R21095 - VSS_XTS10_0 */
+       [21096] = 0x00FF,     /* R21096 - VSS_XTS11_1 */
+       [21097] = 0x0700,     /* R21097 - VSS_XTS11_0 */
+       [21098] = 0x00EF,     /* R21098 - VSS_XTS12_1 */
+       [21099] = 0xD700,     /* R21099 - VSS_XTS12_0 */
+       [21100] = 0x00FB,     /* R21100 - VSS_XTS13_1 */
+       [21101] = 0xAF40,     /* R21101 - VSS_XTS13_0 */
+       [21102] = 0x0010,     /* R21102 - VSS_XTS14_1 */
+       [21103] = 0x8A80,     /* R21103 - VSS_XTS14_0 */
+       [21104] = 0x0011,     /* R21104 - VSS_XTS15_1 */
+       [21105] = 0x07C0,     /* R21105 - VSS_XTS15_0 */
+       [21106] = 0x00E0,     /* R21106 - VSS_XTS16_1 */
+       [21107] = 0x0800,     /* R21107 - VSS_XTS16_0 */
+       [21108] = 0x00D2,     /* R21108 - VSS_XTS17_1 */
+       [21109] = 0x7600,     /* R21109 - VSS_XTS17_0 */
+       [21110] = 0x0020,     /* R21110 - VSS_XTS18_1 */
+       [21111] = 0xCF40,     /* R21111 - VSS_XTS18_0 */
+       [21112] = 0x0030,     /* R21112 - VSS_XTS19_1 */
+       [21113] = 0x2340,     /* R21113 - VSS_XTS19_0 */
+       [21114] = 0x00FD,     /* R21114 - VSS_XTS20_1 */
+       [21115] = 0x69C0,     /* R21115 - VSS_XTS20_0 */
+       [21116] = 0x0028,     /* R21116 - VSS_XTS21_1 */
+       [21117] = 0x3500,     /* R21117 - VSS_XTS21_0 */
+       [21118] = 0x0006,     /* R21118 - VSS_XTS22_1 */
+       [21119] = 0x3300,     /* R21119 - VSS_XTS22_0 */
+       [21120] = 0x00D9,     /* R21120 - VSS_XTS23_1 */
+       [21121] = 0xF6C0,     /* R21121 - VSS_XTS23_0 */
+       [21122] = 0x00F3,     /* R21122 - VSS_XTS24_1 */
+       [21123] = 0x3340,     /* R21123 - VSS_XTS24_0 */
+       [21124] = 0x000F,     /* R21124 - VSS_XTS25_1 */
+       [21125] = 0x4200,     /* R21125 - VSS_XTS25_0 */
+       [21126] = 0x0004,     /* R21126 - VSS_XTS26_1 */
+       [21127] = 0x0C80,     /* R21127 - VSS_XTS26_0 */
+       [21128] = 0x00FB,     /* R21128 - VSS_XTS27_1 */
+       [21129] = 0x3F80,     /* R21129 - VSS_XTS27_0 */
+       [21130] = 0x00F7,     /* R21130 - VSS_XTS28_1 */
+       [21131] = 0x57C0,     /* R21131 - VSS_XTS28_0 */
+       [21132] = 0x0003,     /* R21132 - VSS_XTS29_1 */
+       [21133] = 0x5400,     /* R21133 - VSS_XTS29_0 */
+       [21134] = 0x0000,     /* R21134 - VSS_XTS30_1 */
+       [21135] = 0xC6C0,     /* R21135 - VSS_XTS30_0 */
+       [21136] = 0x0003,     /* R21136 - VSS_XTS31_1 */
+       [21137] = 0x12C0,     /* R21137 - VSS_XTS31_0 */
+       [21138] = 0x00FD,     /* R21138 - VSS_XTS32_1 */
+       [21139] = 0x8580,     /* R21139 - VSS_XTS32_0 */
+};
+
+static const struct wm8962_reg_access {
+       u16 read;
+       u16 write;
+       u16 vol;
+} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
+       [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0     - Left Input volume */
+       [1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1     - Right Input volume */
+       [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2     - HPOUTL volume */
+       [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3     - HPOUTR volume */
+       [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4     - Clocking1 */
+       [5] = { 0x007F, 0x007F, 0x0000 }, /* R5     - ADC & DAC Control 1 */
+       [6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6     - ADC & DAC Control 2 */
+       [7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7     - Audio Interface 0 */
+       [8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8     - Clocking2 */
+       [9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9     - Audio Interface 1 */
+       [10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10    - Left DAC volume */
+       [11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11    - Right DAC volume */
+       [14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14    - Audio Interface 2 */
+       [15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15    - Software Reset */
+       [17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17    - ALC1 */
+       [18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18    - ALC2 */
+       [19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19    - ALC3 */
+       [20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20    - Noise Gate */
+       [21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21    - Left ADC volume */
+       [22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22    - Right ADC volume */
+       [23] = { 0x0161, 0x0161, 0x0000 }, /* R23    - Additional control(1) */
+       [24] = { 0x0008, 0x0008, 0x0000 }, /* R24    - Additional control(2) */
+       [25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25    - Pwr Mgmt (1) */
+       [26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26    - Pwr Mgmt (2) */
+       [27] = { 0x0017, 0x0017, 0x0000 }, /* R27    - Additional Control (3) */
+       [28] = { 0x001C, 0x001C, 0x0000 }, /* R28    - Anti-pop */
+
+       [30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30    - Clocking 3 */
+       [31] = { 0x000F, 0x000F, 0x0000 }, /* R31    - Input mixer control (1) */
+       [32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32    - Left input mixer volume */
+       [33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33    - Right input mixer volume */
+       [34] = { 0x003F, 0x003F, 0x0000 }, /* R34    - Input mixer control (2) */
+       [35] = { 0x003F, 0x003F, 0x0000 }, /* R35    - Input bias control */
+       [37] = { 0x001F, 0x001F, 0x0000 }, /* R37    - Left input PGA control */
+       [38] = { 0x001F, 0x001F, 0x0000 }, /* R38    - Right input PGA control */
+       [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40    - SPKOUTL volume */
+       [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41    - SPKOUTR volume */
+
+       [47] = { 0x000F, 0x0000, 0x0000 }, /* R47    - Thermal Shutdown Status */
+       [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48    - Additional Control (4) */
+       [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49    - Class D Control 1 */
+       [51] = { 0x0047, 0x0047, 0x0000 }, /* R51    - Class D Control 2 */
+       [56] = { 0x001E, 0x001E, 0x0000 }, /* R56    - Clocking 4 */
+       [57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57    - DAC DSP Mixing (1) */
+       [58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58    - DAC DSP Mixing (2) */
+       [60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60    - DC Servo 0 */
+       [61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61    - DC Servo 1 */
+       [64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64    - DC Servo 4 */
+       [66] = { 0x0780, 0x0000, 0xFFFF }, /* R66    - DC Servo 6 */
+       [68] = { 0x0007, 0x0007, 0x0000 }, /* R68    - Analogue PGA Bias */
+       [69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69    - Analogue HP 0 */
+       [71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71    - Analogue HP 2 */
+       [72] = { 0x0001, 0x0001, 0x0000 }, /* R72    - Charge Pump 1 */
+       [82] = { 0x0001, 0x0001, 0x0000 }, /* R82    - Charge Pump B */
+       [87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87    - Write Sequencer Control 1 */
+       [90] = { 0x007F, 0x01FF, 0x0000 }, /* R90    - Write Sequencer Control 2 */
+       [93] = { 0x03F9, 0x0000, 0x0000 }, /* R93    - Write Sequencer Control 3 */
+       [94] = { 0x0070, 0x0070, 0x0000 }, /* R94    - Control Interface */
+       [99] = { 0x000F, 0x000F, 0x0000 }, /* R99    - Mixer Enables */
+       [100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100   - Headphone Mixer (1) */
+       [101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101   - Headphone Mixer (2) */
+       [102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102   - Headphone Mixer (3) */
+       [103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103   - Headphone Mixer (4) */
+       [105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105   - Speaker Mixer (1) */
+       [106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106   - Speaker Mixer (2) */
+       [107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107   - Speaker Mixer (3) */
+       [108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108   - Speaker Mixer (4) */
+       [109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109   - Speaker Mixer (5) */
+       [110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110   - Beep Generator (1) */
+       [115] = { 0x001F, 0x001F, 0x0000 }, /* R115   - Oscillator Trim (3) */
+       [116] = { 0x001F, 0x001F, 0x0000 }, /* R116   - Oscillator Trim (4) */
+       [119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119   - Oscillator Trim (7) */
+       [124] = { 0x0079, 0x0079, 0x0000 }, /* R124   - Analogue Clocking1 */
+       [125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125   - Analogue Clocking2 */
+       [126] = { 0x000D, 0x000D, 0x0000 }, /* R126   - Analogue Clocking3 */
+       [127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127   - PLL Software Reset */
+       [129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129   - PLL2 */
+       [131] = { 0x0003, 0x0003, 0x0000 }, /* R131   - PLL 4 */
+       [136] = { 0x005F, 0x005F, 0x0000 }, /* R136   - PLL 9 */
+       [137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137   - PLL 10 */
+       [138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138   - PLL 11 */
+       [139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139   - PLL 12 */
+       [140] = { 0x005F, 0x005F, 0x0000 }, /* R140   - PLL 13 */
+       [141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141   - PLL 14 */
+       [142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142   - PLL 15 */
+       [143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143   - PLL 16 */
+       [155] = { 0x0067, 0x0067, 0x0000 }, /* R155   - FLL Control (1) */
+       [156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156   - FLL Control (2) */
+       [157] = { 0x0007, 0x0007, 0x0000 }, /* R157   - FLL Control (3) */
+       [159] = { 0x007F, 0x007F, 0x0000 }, /* R159   - FLL Control (5) */
+       [160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160   - FLL Control (6) */
+       [161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161   - FLL Control (7) */
+       [162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162   - FLL Control (8) */
+       [252] = { 0x0005, 0x0005, 0x0000 }, /* R252   - General test 1 */
+       [256] = { 0x000F, 0x000F, 0x0000 }, /* R256   - DF1 */
+       [257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257   - DF2 */
+       [258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258   - DF3 */
+       [259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259   - DF4 */
+       [260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260   - DF5 */
+       [261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261   - DF6 */
+       [262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262   - DF7 */
+       [264] = { 0x0003, 0x0003, 0x0000 }, /* R264   - LHPF1 */
+       [265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265   - LHPF2 */
+       [268] = { 0x0077, 0x0077, 0x0000 }, /* R268   - THREED1 */
+       [269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269   - THREED2 */
+       [270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270   - THREED3 */
+       [271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271   - THREED4 */
+       [276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276   - DRC 1 */
+       [277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277   - DRC 2 */
+       [278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278   - DRC 3 */
+       [279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279   - DRC 4 */
+       [280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280   - DRC 5 */
+       [285] = { 0x0003, 0x0003, 0x0000 }, /* R285   - Tloopback */
+       [335] = { 0x0007, 0x0007, 0x0000 }, /* R335   - EQ1 */
+       [336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336   - EQ2 */
+       [337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337   - EQ3 */
+       [338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338   - EQ4 */
+       [339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339   - EQ5 */
+       [340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340   - EQ6 */
+       [341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341   - EQ7 */
+       [342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342   - EQ8 */
+       [343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343   - EQ9 */
+       [344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344   - EQ10 */
+       [345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345   - EQ11 */
+       [346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346   - EQ12 */
+       [347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347   - EQ13 */
+       [348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348   - EQ14 */
+       [349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349   - EQ15 */
+       [350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350   - EQ16 */
+       [351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351   - EQ17 */
+       [352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352   - EQ18 */
+       [353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353   - EQ19 */
+       [354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354   - EQ20 */
+       [355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355   - EQ21 */
+       [356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356   - EQ22 */
+       [357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357   - EQ23 */
+       [358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358   - EQ24 */
+       [359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359   - EQ25 */
+       [360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360   - EQ26 */
+       [361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361   - EQ27 */
+       [362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362   - EQ28 */
+       [363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363   - EQ29 */
+       [364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364   - EQ30 */
+       [365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365   - EQ31 */
+       [366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366   - EQ32 */
+       [367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367   - EQ33 */
+       [368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368   - EQ34 */
+       [369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369   - EQ35 */
+       [370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370   - EQ36 */
+       [371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371   - EQ37 */
+       [372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372   - EQ38 */
+       [373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373   - EQ39 */
+       [374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374   - EQ40 */
+       [375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375   - EQ41 */
+       [513] = { 0x045F, 0x045F, 0x0000 }, /* R513   - GPIO 2 */
+       [514] = { 0x045F, 0x045F, 0x0000 }, /* R514   - GPIO 3 */
+       [516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516   - GPIO 5 */
+       [517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517   - GPIO 6 */
+       [560] = { 0x0030, 0x0030, 0xFFFF }, /* R560   - Interrupt Status 1 */
+       [561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561   - Interrupt Status 2 */
+       [568] = { 0x0030, 0x0030, 0x0000 }, /* R568   - Interrupt Status 1 Mask */
+       [569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569   - Interrupt Status 2 Mask */
+       [576] = { 0x0001, 0x0001, 0x0000 }, /* R576   - Interrupt Control */
+       [584] = { 0x002D, 0x002D, 0x0000 }, /* R584   - IRQ Debounce */
+       [586] = { 0xC000, 0xC000, 0x0000 }, /* R586   -  MICINT Source Pol */
+       [768] = { 0x0001, 0x0001, 0x0000 }, /* R768   - DSP2 Power Management */
+       [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037  - DSP2_ExecControl */
+       [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096  - Write Sequencer 0 */
+       [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097  - Write Sequencer 1 */
+       [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098  - Write Sequencer 2 */
+       [4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099  - Write Sequencer 3 */
+       [4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100  - Write Sequencer 4 */
+       [4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101  - Write Sequencer 5 */
+       [4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102  - Write Sequencer 6 */
+       [4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103  - Write Sequencer 7 */
+       [4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104  - Write Sequencer 8 */
+       [4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105  - Write Sequencer 9 */
+       [4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106  - Write Sequencer 10 */
+       [4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107  - Write Sequencer 11 */
+       [4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108  - Write Sequencer 12 */
+       [4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109  - Write Sequencer 13 */
+       [4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110  - Write Sequencer 14 */
+       [4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111  - Write Sequencer 15 */
+       [4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112  - Write Sequencer 16 */
+       [4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113  - Write Sequencer 17 */
+       [4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114  - Write Sequencer 18 */
+       [4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115  - Write Sequencer 19 */
+       [4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116  - Write Sequencer 20 */
+       [4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117  - Write Sequencer 21 */
+       [4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118  - Write Sequencer 22 */
+       [4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119  - Write Sequencer 23 */
+       [4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120  - Write Sequencer 24 */
+       [4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121  - Write Sequencer 25 */
+       [4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122  - Write Sequencer 26 */
+       [4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123  - Write Sequencer 27 */
+       [4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124  - Write Sequencer 28 */
+       [4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125  - Write Sequencer 29 */
+       [4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126  - Write Sequencer 30 */
+       [4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127  - Write Sequencer 31 */
+       [4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128  - Write Sequencer 32 */
+       [4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129  - Write Sequencer 33 */
+       [4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130  - Write Sequencer 34 */
+       [4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131  - Write Sequencer 35 */
+       [4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132  - Write Sequencer 36 */
+       [4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133  - Write Sequencer 37 */
+       [4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134  - Write Sequencer 38 */
+       [4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135  - Write Sequencer 39 */
+       [4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136  - Write Sequencer 40 */
+       [4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137  - Write Sequencer 41 */
+       [4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138  - Write Sequencer 42 */
+       [4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139  - Write Sequencer 43 */
+       [4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140  - Write Sequencer 44 */
+       [4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141  - Write Sequencer 45 */
+       [4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142  - Write Sequencer 46 */
+       [4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143  - Write Sequencer 47 */
+       [4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144  - Write Sequencer 48 */
+       [4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145  - Write Sequencer 49 */
+       [4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146  - Write Sequencer 50 */
+       [4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147  - Write Sequencer 51 */
+       [4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148  - Write Sequencer 52 */
+       [4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149  - Write Sequencer 53 */
+       [4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150  - Write Sequencer 54 */
+       [4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151  - Write Sequencer 55 */
+       [4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152  - Write Sequencer 56 */
+       [4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153  - Write Sequencer 57 */
+       [4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154  - Write Sequencer 58 */
+       [4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155  - Write Sequencer 59 */
+       [4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156  - Write Sequencer 60 */
+       [4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157  - Write Sequencer 61 */
+       [4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158  - Write Sequencer 62 */
+       [4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159  - Write Sequencer 63 */
+       [4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160  - Write Sequencer 64 */
+       [4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161  - Write Sequencer 65 */
+       [4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162  - Write Sequencer 66 */
+       [4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163  - Write Sequencer 67 */
+       [4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164  - Write Sequencer 68 */
+       [4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165  - Write Sequencer 69 */
+       [4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166  - Write Sequencer 70 */
+       [4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167  - Write Sequencer 71 */
+       [4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168  - Write Sequencer 72 */
+       [4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169  - Write Sequencer 73 */
+       [4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170  - Write Sequencer 74 */
+       [4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171  - Write Sequencer 75 */
+       [4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172  - Write Sequencer 76 */
+       [4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173  - Write Sequencer 77 */
+       [4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174  - Write Sequencer 78 */
+       [4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175  - Write Sequencer 79 */
+       [4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176  - Write Sequencer 80 */
+       [4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177  - Write Sequencer 81 */
+       [4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178  - Write Sequencer 82 */
+       [4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179  - Write Sequencer 83 */
+       [4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180  - Write Sequencer 84 */
+       [4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181  - Write Sequencer 85 */
+       [4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182  - Write Sequencer 86 */
+       [4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183  - Write Sequencer 87 */
+       [4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184  - Write Sequencer 88 */
+       [4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185  - Write Sequencer 89 */
+       [4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186  - Write Sequencer 90 */
+       [4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187  - Write Sequencer 91 */
+       [4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188  - Write Sequencer 92 */
+       [4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189  - Write Sequencer 93 */
+       [4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190  - Write Sequencer 94 */
+       [4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191  - Write Sequencer 95 */
+       [4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192  - Write Sequencer 96 */
+       [4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193  - Write Sequencer 97 */
+       [4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194  - Write Sequencer 98 */
+       [4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195  - Write Sequencer 99 */
+       [4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196  - Write Sequencer 100 */
+       [4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197  - Write Sequencer 101 */
+       [4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198  - Write Sequencer 102 */
+       [4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199  - Write Sequencer 103 */
+       [4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200  - Write Sequencer 104 */
+       [4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201  - Write Sequencer 105 */
+       [4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202  - Write Sequencer 106 */
+       [4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203  - Write Sequencer 107 */
+       [4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204  - Write Sequencer 108 */
+       [4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205  - Write Sequencer 109 */
+       [4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206  - Write Sequencer 110 */
+       [4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207  - Write Sequencer 111 */
+       [4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208  - Write Sequencer 112 */
+       [4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209  - Write Sequencer 113 */
+       [4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210  - Write Sequencer 114 */
+       [4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211  - Write Sequencer 115 */
+       [4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212  - Write Sequencer 116 */
+       [4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213  - Write Sequencer 117 */
+       [4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214  - Write Sequencer 118 */
+       [4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215  - Write Sequencer 119 */
+       [4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216  - Write Sequencer 120 */
+       [4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217  - Write Sequencer 121 */
+       [4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218  - Write Sequencer 122 */
+       [4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219  - Write Sequencer 123 */
+       [4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220  - Write Sequencer 124 */
+       [4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221  - Write Sequencer 125 */
+       [4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222  - Write Sequencer 126 */
+       [4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223  - Write Sequencer 127 */
+       [4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224  - Write Sequencer 128 */
+       [4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225  - Write Sequencer 129 */
+       [4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226  - Write Sequencer 130 */
+       [4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227  - Write Sequencer 131 */
+       [4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228  - Write Sequencer 132 */
+       [4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229  - Write Sequencer 133 */
+       [4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230  - Write Sequencer 134 */
+       [4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231  - Write Sequencer 135 */
+       [4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232  - Write Sequencer 136 */
+       [4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233  - Write Sequencer 137 */
+       [4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234  - Write Sequencer 138 */
+       [4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235  - Write Sequencer 139 */
+       [4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236  - Write Sequencer 140 */
+       [4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237  - Write Sequencer 141 */
+       [4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238  - Write Sequencer 142 */
+       [4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239  - Write Sequencer 143 */
+       [4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240  - Write Sequencer 144 */
+       [4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241  - Write Sequencer 145 */
+       [4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242  - Write Sequencer 146 */
+       [4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243  - Write Sequencer 147 */
+       [4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244  - Write Sequencer 148 */
+       [4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245  - Write Sequencer 149 */
+       [4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246  - Write Sequencer 150 */
+       [4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247  - Write Sequencer 151 */
+       [4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248  - Write Sequencer 152 */
+       [4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249  - Write Sequencer 153 */
+       [4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250  - Write Sequencer 154 */
+       [4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251  - Write Sequencer 155 */
+       [4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252  - Write Sequencer 156 */
+       [4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253  - Write Sequencer 157 */
+       [4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254  - Write Sequencer 158 */
+       [4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255  - Write Sequencer 159 */
+       [4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256  - Write Sequencer 160 */
+       [4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257  - Write Sequencer 161 */
+       [4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258  - Write Sequencer 162 */
+       [4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259  - Write Sequencer 163 */
+       [4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260  - Write Sequencer 164 */
+       [4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261  - Write Sequencer 165 */
+       [4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262  - Write Sequencer 166 */
+       [4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263  - Write Sequencer 167 */
+       [4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264  - Write Sequencer 168 */
+       [4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265  - Write Sequencer 169 */
+       [4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266  - Write Sequencer 170 */
+       [4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267  - Write Sequencer 171 */
+       [4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268  - Write Sequencer 172 */
+       [4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269  - Write Sequencer 173 */
+       [4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270  - Write Sequencer 174 */
+       [4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271  - Write Sequencer 175 */
+       [4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272  - Write Sequencer 176 */
+       [4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273  - Write Sequencer 177 */
+       [4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274  - Write Sequencer 178 */
+       [4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275  - Write Sequencer 179 */
+       [4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276  - Write Sequencer 180 */
+       [4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277  - Write Sequencer 181 */
+       [4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278  - Write Sequencer 182 */
+       [4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279  - Write Sequencer 183 */
+       [4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280  - Write Sequencer 184 */
+       [4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281  - Write Sequencer 185 */
+       [4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282  - Write Sequencer 186 */
+       [4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283  - Write Sequencer 187 */
+       [4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284  - Write Sequencer 188 */
+       [4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285  - Write Sequencer 189 */
+       [4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286  - Write Sequencer 190 */
+       [4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287  - Write Sequencer 191 */
+       [4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288  - Write Sequencer 192 */
+       [4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289  - Write Sequencer 193 */
+       [4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290  - Write Sequencer 194 */
+       [4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291  - Write Sequencer 195 */
+       [4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292  - Write Sequencer 196 */
+       [4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293  - Write Sequencer 197 */
+       [4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294  - Write Sequencer 198 */
+       [4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295  - Write Sequencer 199 */
+       [4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296  - Write Sequencer 200 */
+       [4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297  - Write Sequencer 201 */
+       [4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298  - Write Sequencer 202 */
+       [4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299  - Write Sequencer 203 */
+       [4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300  - Write Sequencer 204 */
+       [4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301  - Write Sequencer 205 */
+       [4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302  - Write Sequencer 206 */
+       [4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303  - Write Sequencer 207 */
+       [4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304  - Write Sequencer 208 */
+       [4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305  - Write Sequencer 209 */
+       [4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306  - Write Sequencer 210 */
+       [4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307  - Write Sequencer 211 */
+       [4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308  - Write Sequencer 212 */
+       [4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309  - Write Sequencer 213 */
+       [4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310  - Write Sequencer 214 */
+       [4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311  - Write Sequencer 215 */
+       [4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312  - Write Sequencer 216 */
+       [4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313  - Write Sequencer 217 */
+       [4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314  - Write Sequencer 218 */
+       [4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315  - Write Sequencer 219 */
+       [4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316  - Write Sequencer 220 */
+       [4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317  - Write Sequencer 221 */
+       [4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318  - Write Sequencer 222 */
+       [4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319  - Write Sequencer 223 */
+       [4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320  - Write Sequencer 224 */
+       [4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321  - Write Sequencer 225 */
+       [4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322  - Write Sequencer 226 */
+       [4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323  - Write Sequencer 227 */
+       [4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324  - Write Sequencer 228 */
+       [4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325  - Write Sequencer 229 */
+       [4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326  - Write Sequencer 230 */
+       [4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327  - Write Sequencer 231 */
+       [4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328  - Write Sequencer 232 */
+       [4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329  - Write Sequencer 233 */
+       [4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330  - Write Sequencer 234 */
+       [4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331  - Write Sequencer 235 */
+       [4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332  - Write Sequencer 236 */
+       [4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333  - Write Sequencer 237 */
+       [4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334  - Write Sequencer 238 */
+       [4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335  - Write Sequencer 239 */
+       [4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336  - Write Sequencer 240 */
+       [4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337  - Write Sequencer 241 */
+       [4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338  - Write Sequencer 242 */
+       [4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339  - Write Sequencer 243 */
+       [4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340  - Write Sequencer 244 */
+       [4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341  - Write Sequencer 245 */
+       [4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342  - Write Sequencer 246 */
+       [4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343  - Write Sequencer 247 */
+       [4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344  - Write Sequencer 248 */
+       [4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345  - Write Sequencer 249 */
+       [4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346  - Write Sequencer 250 */
+       [4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347  - Write Sequencer 251 */
+       [4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348  - Write Sequencer 252 */
+       [4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349  - Write Sequencer 253 */
+       [4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350  - Write Sequencer 254 */
+       [4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351  - Write Sequencer 255 */
+       [4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352  - Write Sequencer 256 */
+       [4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353  - Write Sequencer 257 */
+       [4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354  - Write Sequencer 258 */
+       [4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355  - Write Sequencer 259 */
+       [4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356  - Write Sequencer 260 */
+       [4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357  - Write Sequencer 261 */
+       [4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358  - Write Sequencer 262 */
+       [4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359  - Write Sequencer 263 */
+       [4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360  - Write Sequencer 264 */
+       [4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361  - Write Sequencer 265 */
+       [4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362  - Write Sequencer 266 */
+       [4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363  - Write Sequencer 267 */
+       [4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364  - Write Sequencer 268 */
+       [4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365  - Write Sequencer 269 */
+       [4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366  - Write Sequencer 270 */
+       [4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367  - Write Sequencer 271 */
+       [4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368  - Write Sequencer 272 */
+       [4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369  - Write Sequencer 273 */
+       [4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370  - Write Sequencer 274 */
+       [4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371  - Write Sequencer 275 */
+       [4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372  - Write Sequencer 276 */
+       [4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373  - Write Sequencer 277 */
+       [4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374  - Write Sequencer 278 */
+       [4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375  - Write Sequencer 279 */
+       [4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376  - Write Sequencer 280 */
+       [4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377  - Write Sequencer 281 */
+       [4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378  - Write Sequencer 282 */
+       [4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379  - Write Sequencer 283 */
+       [4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380  - Write Sequencer 284 */
+       [4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381  - Write Sequencer 285 */
+       [4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382  - Write Sequencer 286 */
+       [4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383  - Write Sequencer 287 */
+       [4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384  - Write Sequencer 288 */
+       [4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385  - Write Sequencer 289 */
+       [4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386  - Write Sequencer 290 */
+       [4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387  - Write Sequencer 291 */
+       [4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388  - Write Sequencer 292 */
+       [4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389  - Write Sequencer 293 */
+       [4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390  - Write Sequencer 294 */
+       [4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391  - Write Sequencer 295 */
+       [4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392  - Write Sequencer 296 */
+       [4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393  - Write Sequencer 297 */
+       [4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394  - Write Sequencer 298 */
+       [4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395  - Write Sequencer 299 */
+       [4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396  - Write Sequencer 300 */
+       [4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397  - Write Sequencer 301 */
+       [4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398  - Write Sequencer 302 */
+       [4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399  - Write Sequencer 303 */
+       [4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400  - Write Sequencer 304 */
+       [4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401  - Write Sequencer 305 */
+       [4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402  - Write Sequencer 306 */
+       [4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403  - Write Sequencer 307 */
+       [4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404  - Write Sequencer 308 */
+       [4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405  - Write Sequencer 309 */
+       [4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406  - Write Sequencer 310 */
+       [4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407  - Write Sequencer 311 */
+       [4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408  - Write Sequencer 312 */
+       [4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409  - Write Sequencer 313 */
+       [4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410  - Write Sequencer 314 */
+       [4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411  - Write Sequencer 315 */
+       [4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412  - Write Sequencer 316 */
+       [4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413  - Write Sequencer 317 */
+       [4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414  - Write Sequencer 318 */
+       [4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415  - Write Sequencer 319 */
+       [4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416  - Write Sequencer 320 */
+       [4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417  - Write Sequencer 321 */
+       [4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418  - Write Sequencer 322 */
+       [4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419  - Write Sequencer 323 */
+       [4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420  - Write Sequencer 324 */
+       [4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421  - Write Sequencer 325 */
+       [4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422  - Write Sequencer 326 */
+       [4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423  - Write Sequencer 327 */
+       [4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424  - Write Sequencer 328 */
+       [4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425  - Write Sequencer 329 */
+       [4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426  - Write Sequencer 330 */
+       [4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427  - Write Sequencer 331 */
+       [4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428  - Write Sequencer 332 */
+       [4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429  - Write Sequencer 333 */
+       [4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430  - Write Sequencer 334 */
+       [4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431  - Write Sequencer 335 */
+       [4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432  - Write Sequencer 336 */
+       [4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433  - Write Sequencer 337 */
+       [4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434  - Write Sequencer 338 */
+       [4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435  - Write Sequencer 339 */
+       [4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436  - Write Sequencer 340 */
+       [4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437  - Write Sequencer 341 */
+       [4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438  - Write Sequencer 342 */
+       [4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439  - Write Sequencer 343 */
+       [4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440  - Write Sequencer 344 */
+       [4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441  - Write Sequencer 345 */
+       [4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442  - Write Sequencer 346 */
+       [4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443  - Write Sequencer 347 */
+       [4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444  - Write Sequencer 348 */
+       [4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445  - Write Sequencer 349 */
+       [4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446  - Write Sequencer 350 */
+       [4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447  - Write Sequencer 351 */
+       [4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448  - Write Sequencer 352 */
+       [4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449  - Write Sequencer 353 */
+       [4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450  - Write Sequencer 354 */
+       [4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451  - Write Sequencer 355 */
+       [4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452  - Write Sequencer 356 */
+       [4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453  - Write Sequencer 357 */
+       [4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454  - Write Sequencer 358 */
+       [4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455  - Write Sequencer 359 */
+       [4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456  - Write Sequencer 360 */
+       [4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457  - Write Sequencer 361 */
+       [4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458  - Write Sequencer 362 */
+       [4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459  - Write Sequencer 363 */
+       [4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460  - Write Sequencer 364 */
+       [4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461  - Write Sequencer 365 */
+       [4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462  - Write Sequencer 366 */
+       [4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463  - Write Sequencer 367 */
+       [4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464  - Write Sequencer 368 */
+       [4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465  - Write Sequencer 369 */
+       [4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466  - Write Sequencer 370 */
+       [4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467  - Write Sequencer 371 */
+       [4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468  - Write Sequencer 372 */
+       [4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469  - Write Sequencer 373 */
+       [4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470  - Write Sequencer 374 */
+       [4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471  - Write Sequencer 375 */
+       [4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472  - Write Sequencer 376 */
+       [4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473  - Write Sequencer 377 */
+       [4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474  - Write Sequencer 378 */
+       [4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475  - Write Sequencer 379 */
+       [4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476  - Write Sequencer 380 */
+       [4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477  - Write Sequencer 381 */
+       [4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478  - Write Sequencer 382 */
+       [4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479  - Write Sequencer 383 */
+       [4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480  - Write Sequencer 384 */
+       [4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481  - Write Sequencer 385 */
+       [4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482  - Write Sequencer 386 */
+       [4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483  - Write Sequencer 387 */
+       [4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484  - Write Sequencer 388 */
+       [4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485  - Write Sequencer 389 */
+       [4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486  - Write Sequencer 390 */
+       [4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487  - Write Sequencer 391 */
+       [4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488  - Write Sequencer 392 */
+       [4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489  - Write Sequencer 393 */
+       [4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490  - Write Sequencer 394 */
+       [4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491  - Write Sequencer 395 */
+       [4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492  - Write Sequencer 396 */
+       [4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493  - Write Sequencer 397 */
+       [4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494  - Write Sequencer 398 */
+       [4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495  - Write Sequencer 399 */
+       [4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496  - Write Sequencer 400 */
+       [4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497  - Write Sequencer 401 */
+       [4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498  - Write Sequencer 402 */
+       [4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499  - Write Sequencer 403 */
+       [4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500  - Write Sequencer 404 */
+       [4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501  - Write Sequencer 405 */
+       [4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502  - Write Sequencer 406 */
+       [4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503  - Write Sequencer 407 */
+       [4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504  - Write Sequencer 408 */
+       [4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505  - Write Sequencer 409 */
+       [4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506  - Write Sequencer 410 */
+       [4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507  - Write Sequencer 411 */
+       [4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508  - Write Sequencer 412 */
+       [4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509  - Write Sequencer 413 */
+       [4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510  - Write Sequencer 414 */
+       [4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511  - Write Sequencer 415 */
+       [4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512  - Write Sequencer 416 */
+       [4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513  - Write Sequencer 417 */
+       [4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514  - Write Sequencer 418 */
+       [4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515  - Write Sequencer 419 */
+       [4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516  - Write Sequencer 420 */
+       [4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517  - Write Sequencer 421 */
+       [4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518  - Write Sequencer 422 */
+       [4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519  - Write Sequencer 423 */
+       [4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520  - Write Sequencer 424 */
+       [4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521  - Write Sequencer 425 */
+       [4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522  - Write Sequencer 426 */
+       [4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523  - Write Sequencer 427 */
+       [4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524  - Write Sequencer 428 */
+       [4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525  - Write Sequencer 429 */
+       [4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526  - Write Sequencer 430 */
+       [4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527  - Write Sequencer 431 */
+       [4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528  - Write Sequencer 432 */
+       [4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529  - Write Sequencer 433 */
+       [4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530  - Write Sequencer 434 */
+       [4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531  - Write Sequencer 435 */
+       [4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532  - Write Sequencer 436 */
+       [4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533  - Write Sequencer 437 */
+       [4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534  - Write Sequencer 438 */
+       [4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535  - Write Sequencer 439 */
+       [4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536  - Write Sequencer 440 */
+       [4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537  - Write Sequencer 441 */
+       [4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538  - Write Sequencer 442 */
+       [4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539  - Write Sequencer 443 */
+       [4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540  - Write Sequencer 444 */
+       [4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541  - Write Sequencer 445 */
+       [4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542  - Write Sequencer 446 */
+       [4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543  - Write Sequencer 447 */
+       [4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544  - Write Sequencer 448 */
+       [4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545  - Write Sequencer 449 */
+       [4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546  - Write Sequencer 450 */
+       [4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547  - Write Sequencer 451 */
+       [4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548  - Write Sequencer 452 */
+       [4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549  - Write Sequencer 453 */
+       [4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550  - Write Sequencer 454 */
+       [4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551  - Write Sequencer 455 */
+       [4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552  - Write Sequencer 456 */
+       [4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553  - Write Sequencer 457 */
+       [4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554  - Write Sequencer 458 */
+       [4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555  - Write Sequencer 459 */
+       [4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556  - Write Sequencer 460 */
+       [4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557  - Write Sequencer 461 */
+       [4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558  - Write Sequencer 462 */
+       [4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559  - Write Sequencer 463 */
+       [4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560  - Write Sequencer 464 */
+       [4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561  - Write Sequencer 465 */
+       [4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562  - Write Sequencer 466 */
+       [4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563  - Write Sequencer 467 */
+       [4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564  - Write Sequencer 468 */
+       [4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565  - Write Sequencer 469 */
+       [4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566  - Write Sequencer 470 */
+       [4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567  - Write Sequencer 471 */
+       [4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568  - Write Sequencer 472 */
+       [4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569  - Write Sequencer 473 */
+       [4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570  - Write Sequencer 474 */
+       [4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571  - Write Sequencer 475 */
+       [4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572  - Write Sequencer 476 */
+       [4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573  - Write Sequencer 477 */
+       [4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574  - Write Sequencer 478 */
+       [4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575  - Write Sequencer 479 */
+       [4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576  - Write Sequencer 480 */
+       [4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577  - Write Sequencer 481 */
+       [4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578  - Write Sequencer 482 */
+       [4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579  - Write Sequencer 483 */
+       [4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580  - Write Sequencer 484 */
+       [4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581  - Write Sequencer 485 */
+       [4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582  - Write Sequencer 486 */
+       [4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583  - Write Sequencer 487 */
+       [4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584  - Write Sequencer 488 */
+       [4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585  - Write Sequencer 489 */
+       [4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586  - Write Sequencer 490 */
+       [4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587  - Write Sequencer 491 */
+       [4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588  - Write Sequencer 492 */
+       [4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589  - Write Sequencer 493 */
+       [4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590  - Write Sequencer 494 */
+       [4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591  - Write Sequencer 495 */
+       [4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592  - Write Sequencer 496 */
+       [4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593  - Write Sequencer 497 */
+       [4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594  - Write Sequencer 498 */
+       [4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595  - Write Sequencer 499 */
+       [4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596  - Write Sequencer 500 */
+       [4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597  - Write Sequencer 501 */
+       [4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598  - Write Sequencer 502 */
+       [4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599  - Write Sequencer 503 */
+       [4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600  - Write Sequencer 504 */
+       [4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601  - Write Sequencer 505 */
+       [4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602  - Write Sequencer 506 */
+       [4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603  - Write Sequencer 507 */
+       [4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604  - Write Sequencer 508 */
+       [4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605  - Write Sequencer 509 */
+       [4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606  - Write Sequencer 510 */
+       [4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607  - Write Sequencer 511 */
+       [8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192  - DSP2 Instruction RAM 0 */
+       [9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216  - DSP2 Address RAM 2 */
+       [9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217  - DSP2 Address RAM 1 */
+       [9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218  - DSP2 Address RAM 0 */
+       [12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
+       [12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
+       [13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
+       [13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
+       [14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
+       [14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
+       [15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
+       [16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+       [16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+       [16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+       [16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+       [16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
+       [16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
+       [16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
+       [16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
+       [16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
+       [16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
+       [16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
+       [16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
+       [16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
+       [16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
+       [16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
+       [16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
+       [16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
+       [16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
+       [16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
+       [16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
+       [16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
+       [16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
+       [16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
+       [16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
+       [16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
+       [16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
+       [16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
+       [16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
+       [16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
+       [16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
+       [16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
+       [16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
+       [16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
+       [16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
+       [16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
+       [16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
+       [17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
+       [17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
+       [17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
+       [17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
+       [17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
+       [17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
+       [17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
+       [17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
+       [17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
+       [17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
+       [17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
+       [17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
+       [17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
+       [17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
+       [17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
+       [17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
+       [17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
+       [17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
+       [17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
+       [17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
+       [17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
+       [17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
+       [17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
+       [17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
+       [17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
+       [17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
+       [17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
+       [17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
+       [17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
+       [17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
+       [17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
+       [17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
+       [17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
+       [17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
+       [17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
+       [17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
+       [17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
+       [17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
+       [17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
+       [17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
+       [17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
+       [17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
+       [17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
+       [17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
+       [17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
+       [17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
+       [17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
+       [17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
+       [17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
+       [17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
+       [17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
+       [17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
+       [17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
+       [17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
+       [17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
+       [17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
+       [17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
+       [17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
+       [17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
+       [17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
+       [17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
+       [17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
+       [17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
+       [17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
+       [17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
+       [17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
+       [18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
+       [18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
+       [18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
+       [18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
+       [18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
+       [18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
+       [18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
+       [18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
+       [18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
+       [18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
+       [18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
+       [18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
+       [18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
+       [18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
+       [18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
+       [18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
+       [18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
+       [18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
+       [18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
+       [18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
+       [18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
+       [18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
+       [18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
+       [18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
+       [18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
+       [18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
+       [18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
+       [18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
+       [18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
+       [18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
+       [18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
+       [18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
+       [18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
+       [18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
+       [18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
+       [18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
+       [18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
+       [18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
+       [18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
+       [18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
+       [18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
+       [18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
+       [18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
+       [18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
+       [18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
+       [18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
+       [18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
+       [18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
+       [18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
+       [18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
+       [18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
+       [18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
+       [18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
+       [18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
+       [18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
+       [18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
+       [18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
+       [18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
+       [18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
+       [18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
+       [19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
+       [19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
+       [19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
+       [19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
+       [19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
+       [19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
+       [19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
+       [19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
+       [19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
+       [19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
+       [19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
+       [19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
+       [19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
+       [19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
+       [19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
+       [19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
+       [19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
+       [19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
+       [19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
+       [19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
+       [19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
+       [19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
+       [19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
+       [19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
+       [19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
+       [19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
+       [19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
+       [19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
+       [19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
+       [19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
+       [19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
+       [19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
+       [19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
+       [19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
+       [19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
+       [19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
+       [19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
+       [19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
+       [19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
+       [19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
+       [19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
+       [19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
+       [19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
+       [19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
+       [19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
+       [19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
+       [19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
+       [19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
+       [19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
+       [19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
+       [19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
+       [19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
+       [19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
+       [19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
+       [19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
+       [19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
+       [19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
+       [19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
+       [19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
+       [19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
+       [19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
+       [19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
+       [19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
+       [19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
+       [19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
+       [19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
+       [19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
+       [19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
+       [19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
+       [19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
+       [19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
+       [19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
+       [19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
+       [19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
+       [19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
+       [19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
+       [20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
+       [20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
+       [20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
+       [20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
+       [20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
+       [20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
+       [20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
+       [20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
+       [20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
+       [20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
+       [20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
+       [20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
+       [20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
+       [20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
+       [20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
+       [20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
+       [20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
+       [20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
+       [20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
+       [20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
+       [20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
+       [20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
+       [20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
+       [20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
+       [20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
+       [20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
+       [20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
+       [20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
+       [20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
+       [20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
+       [20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
+       [20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
+       [20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
+       [20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
+       [20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
+       [20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
+       [20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
+       [20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
+       [20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
+       [20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
+       [20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
+       [20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
+       [20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
+       [20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
+       [20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
+       [20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
+       [20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
+       [20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
+       [20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
+       [20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
+       [20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
+       [20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
+       [20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
+       [20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
+       [20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
+       [20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
+       [20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
+       [20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
+       [20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
+       [20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
+       [20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
+       [20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
+       [20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
+       [20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
+       [20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
+       [20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
+       [20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
+       [20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
+       [20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
+       [20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
+       [20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
+       [20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
+       [21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
+       [21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
+       [21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
+       [21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
+       [21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
+       [21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
+       [21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
+       [21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
+       [21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
+       [21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
+       [21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
+       [21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
+       [21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
+       [21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
+       [21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
+       [21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
+       [21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
+       [21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
+       [21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
+       [21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
+       [21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
+       [21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
+       [21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
+       [21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
+       [21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
+       [21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
+       [21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
+       [21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
+       [21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
+       [21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
+       [21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
+       [21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
+       [21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
+       [21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
+       [21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
+       [21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
+       [21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
+       [21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
+       [21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
+       [21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
+       [21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
+       [21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
+       [21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
+       [21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
+       [21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
+       [21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
+       [21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
+       [21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
+       [21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
+       [21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
+       [21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
+       [21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
+       [21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
+       [21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
+       [21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
+       [21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
+       [21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
+       [21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
+       [21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
+       [21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
+       [21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
+       [21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
+       [21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
+       [21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
+       [21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
+       [21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
+       [21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
+       [21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
+       [21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
+       [21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
+       [21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
+       [21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
+       [21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
+       [21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
+       [21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
+       [21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
+       [21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
+       [21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
+       [21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
+       [21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
+       [21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
+       [21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
+       [21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
+       [21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
+       [21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
+       [21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
+       [21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
+       [21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
+       [21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
+       [21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
+       [21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
+       [21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
+       [21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
+       [21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
+       [21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
+       [21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
+       [21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
+       [21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
+       [21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
+       [21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
+       [21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
+       [21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
+       [21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
+       [21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
+       [21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
+       [21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
+       [21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
+       [21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
+       [21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
+       [21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
+       [21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
+       [21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
+       [21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
+       [21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
+       [21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
+       [21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
+       [21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
+       [21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
+       [21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
+       [21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
+       [21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
+       [21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
+       [21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
+       [21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
+       [21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
+       [21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
+       [21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
+       [21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
+       [21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
+       [21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
+       [21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
+       [21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
+       [21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
+       [21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
+       [21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
+       [21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
+       [21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
+       [21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
+       [21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
+       [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
+};
+
+static int wm8962_volatile_register(unsigned int reg)
+{
+       if (wm8962_reg_access[reg].vol)
+               return 1;
+       else
+               return 0;
+}
+
+static int wm8962_readable_register(unsigned int reg)
+{
+       if (wm8962_reg_access[reg].read)
+               return 1;
+       else
+               return 0;
+}
+
+static int wm8962_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0);
+}
+
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
+static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
+static const unsigned int mixinpga_tlv[] = {
+       TLV_DB_RANGE_HEAD(7),
+       0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
+       2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
+       3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
+       5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0),
+       6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0),
+};
+static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1);
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
+static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
+static const unsigned int classd_tlv[] = {
+       TLV_DB_RANGE_HEAD(7),
+       0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
+       7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
+};
+
+/* The VU bits for the headphones are in a different register to the mute
+ * bits and only take effect on the PGA if it is actually powered.
+ */
+static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = wm8962->reg_cache;
+       int ret;
+
+       /* Apply the update (if any) */
+        ret = snd_soc_put_volsw(kcontrol, ucontrol);
+       if (ret == 0)
+               return 0;
+
+       /* If the left PGA is enabled hit that VU bit... */
+       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA)
+               return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
+                                    reg_cache[WM8962_HPOUTL_VOLUME]);
+
+       /* ...otherwise the right.  The VU is stereo. */
+       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA)
+               return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
+                                    reg_cache[WM8962_HPOUTR_VOLUME]);
+
+       return 0;
+}
+
+/* The VU bits for the speakers are in a different register to the mute
+ * bits and only take effect on the PGA if it is actually powered.
+ */
+static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = wm8962->reg_cache;
+       int ret;
+
+       /* Apply the update (if any) */
+        ret = snd_soc_put_volsw(kcontrol, ucontrol);
+       if (ret == 0)
+               return 0;
+
+       /* If the left PGA is enabled hit that VU bit... */
+       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
+               return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+                                    reg_cache[WM8962_SPKOUTL_VOLUME]);
+
+       /* ...otherwise the right.  The VU is stereo. */
+       if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
+               return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+                                    reg_cache[WM8962_SPKOUTR_VOLUME]);
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new wm8962_snd_controls[] = {
+SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
+
+SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 6, 7, 0,
+              mixin_tlv),
+SOC_SINGLE_TLV("MIXINL PGA Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 3, 7, 0,
+              mixinpga_tlv),
+SOC_SINGLE_TLV("MIXINL IN3L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 0, 7, 0,
+              mixin_tlv),
+
+SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 6, 7, 0,
+              mixin_tlv),
+SOC_SINGLE_TLV("MIXINR PGA Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 3, 7, 0,
+              mixinpga_tlv),
+SOC_SINGLE_TLV("MIXINR IN3R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 0, 7, 0,
+              mixin_tlv),
+
+SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8962_LEFT_ADC_VOLUME,
+                WM8962_RIGHT_ADC_VOLUME, 1, 127, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("Capture Volume", WM8962_LEFT_INPUT_VOLUME,
+                WM8962_RIGHT_INPUT_VOLUME, 0, 63, 0, inpga_tlv),
+SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME,
+            WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1),
+SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME,
+            WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1),
+
+SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
+                WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
+
+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
+                WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
+SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
+
+SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
+          5, 1, 0),
+
+SOC_SINGLE_TLV("Beep Volume", WM8962_BEEP_GENERATOR_1, 4, 15, 0, beep_tlv),
+
+SOC_DOUBLE_R_TLV("Headphone Volume", WM8962_HPOUTL_VOLUME,
+                WM8962_HPOUTR_VOLUME, 0, 127, 0, out_tlv),
+SOC_DOUBLE_EXT("Headphone Switch", WM8962_PWR_MGMT_2, 1, 0, 1, 1,
+              snd_soc_get_volsw, wm8962_put_hp_sw),
+SOC_DOUBLE_R("Headphone ZC Switch", WM8962_HPOUTL_VOLUME, WM8962_HPOUTR_VOLUME,
+            7, 1, 0),
+SOC_DOUBLE_TLV("Headphone Aux Volume", WM8962_ANALOGUE_HP_2, 3, 6, 7, 0,
+              hp_tlv),
+
+SOC_DOUBLE_R("Headphone Mixer Switch", WM8962_HEADPHONE_MIXER_3,
+            WM8962_HEADPHONE_MIXER_4, 8, 1, 1),
+
+SOC_SINGLE_TLV("HPMIXL IN4L Volume", WM8962_HEADPHONE_MIXER_3,
+              3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXL IN4R Volume", WM8962_HEADPHONE_MIXER_3,
+              0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXL MIXINL Volume", WM8962_HEADPHONE_MIXER_3,
+              7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("HPMIXL MIXINR Volume", WM8962_HEADPHONE_MIXER_3,
+              6, 1, 1, inmix_tlv),
+
+SOC_SINGLE_TLV("HPMIXR IN4L Volume", WM8962_HEADPHONE_MIXER_4,
+              3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXR IN4R Volume", WM8962_HEADPHONE_MIXER_4,
+              0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("HPMIXR MIXINL Volume", WM8962_HEADPHONE_MIXER_4,
+              7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4,
+              6, 1, 1, inmix_tlv),
+
+SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0,
+              classd_tlv),
+};
+
+static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
+SOC_SINGLE_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, 0, 127, 0, out_tlv),
+SOC_SINGLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 1, 1,
+              snd_soc_get_volsw, wm8962_put_spk_sw),
+SOC_SINGLE("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, 7, 1, 0),
+
+SOC_SINGLE("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, 8, 1, 1),
+SOC_SINGLE_TLV("Speaker Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
+              3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("Speaker Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
+              0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("Speaker Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
+              7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
+              6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+              7, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("Speaker Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+              6, 1, 0, inmix_tlv),
+};
+
+static const struct snd_kcontrol_new wm8962_spk_stereo_controls[] = {
+SOC_DOUBLE_R_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME,
+                WM8962_SPKOUTR_VOLUME, 0, 127, 0, out_tlv),
+SOC_DOUBLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 0, 1, 1,
+              snd_soc_get_volsw, wm8962_put_spk_sw),
+SOC_DOUBLE_R("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, WM8962_SPKOUTR_VOLUME,
+            7, 1, 0),
+
+SOC_DOUBLE_R("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3,
+            WM8962_SPEAKER_MIXER_4, 8, 1, 1),
+
+SOC_SINGLE_TLV("SPKOUTL Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
+              3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
+              0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
+              7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
+              6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+              7, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTL Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+              6, 1, 0, inmix_tlv),
+
+SOC_SINGLE_TLV("SPKOUTR Mixer IN4L Volume", WM8962_SPEAKER_MIXER_4,
+              3, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer IN4R Volume", WM8962_SPEAKER_MIXER_4,
+              0, 7, 0, bypass_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_4,
+              7, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_4,
+              6, 1, 1, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
+              5, 1, 0, inmix_tlv),
+SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
+              4, 1, 0, inmix_tlv),
+};
+
+static int sysclk_event(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int src;
+       int fll;
+
+       src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
+
+       switch (src) {
+       case 0:      /* MCLK */
+               fll = 0;
+               break;
+       case 0x200:  /* FLL */
+               fll = 1;
+               break;
+       default:
+               dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
+               return -EINVAL;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               if (fll)
+                       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+                                           WM8962_FLL_ENA, WM8962_FLL_ENA);
+               break;
+
+       case SND_SOC_DAPM_POST_PMD:
+               if (fll)
+                       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+                                           WM8962_FLL_ENA, 0);
+               break;
+
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int cp_event(struct snd_soc_dapm_widget *w,
+                   struct snd_kcontrol *kcontrol, int event)
+{
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               msleep(5);
+               break;
+
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+                   struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       int timeout;
+       int reg;
+       int expected = (WM8962_DCS_STARTUP_DONE_HP1L |
+                       WM8962_DCS_STARTUP_DONE_HP1R);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_ENA | WM8962_HP1R_ENA,
+                                   WM8962_HP1L_ENA | WM8962_HP1R_ENA);
+               udelay(20);
+
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY,
+                                   WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY);
+
+               /* Start the DC servo */
+               snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
+                                   WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+                                   WM8962_HP1L_DCS_STARTUP |
+                                   WM8962_HP1R_DCS_STARTUP,
+                                   WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+                                   WM8962_HP1L_DCS_STARTUP |
+                                   WM8962_HP1R_DCS_STARTUP);
+
+               /* Wait for it to complete, should be well under 100ms */
+               timeout = 0;
+               do {
+                       msleep(1);
+                       reg = snd_soc_read(codec, WM8962_DC_SERVO_6);
+                       if (reg < 0) {
+                               dev_err(codec->dev,
+                                       "Failed to read DCS status: %d\n",
+                                       reg);
+                               continue;
+                       }
+                       dev_dbg(codec->dev, "DCS status: %x\n", reg);
+               } while (++timeout < 200 && (reg & expected) != expected);
+
+               if ((reg & expected) != expected)
+                       dev_err(codec->dev, "DC servo timed out\n");
+               else
+                       dev_dbg(codec->dev, "DC servo complete after %dms\n",
+                               timeout);
+
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_ENA_OUTP |
+                                   WM8962_HP1R_ENA_OUTP,
+                                   WM8962_HP1L_ENA_OUTP |
+                                   WM8962_HP1R_ENA_OUTP);
+               udelay(20);
+
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_RMV_SHORT |
+                                   WM8962_HP1R_RMV_SHORT,
+                                   WM8962_HP1L_RMV_SHORT |
+                                   WM8962_HP1R_RMV_SHORT);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_RMV_SHORT |
+                                   WM8962_HP1R_RMV_SHORT, 0);
+
+               udelay(20);
+
+               snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
+                                   WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
+                                   WM8962_HP1L_DCS_STARTUP |
+                                   WM8962_HP1R_DCS_STARTUP,
+                                   0);
+
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
+                                   WM8962_HP1L_ENA | WM8962_HP1R_ENA |
+                                   WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY |
+                                   WM8962_HP1L_ENA_OUTP |
+                                   WM8962_HP1R_ENA_OUTP, 0);
+                                   
+               break;
+
+       default:
+               BUG();
+               return -EINVAL;
+       
+       }
+
+       return 0;
+}
+
+/* VU bits for the output PGAs only take effect while the PGA is powered */
+static int out_pga_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = wm8962->reg_cache;
+       int reg;
+
+       switch (w->shift) {
+       case WM8962_HPOUTR_PGA_ENA_SHIFT:
+               reg = WM8962_HPOUTR_VOLUME;
+               break;
+       case WM8962_HPOUTL_PGA_ENA_SHIFT:
+               reg = WM8962_HPOUTL_VOLUME;
+               break;
+       case WM8962_SPKOUTR_PGA_ENA_SHIFT:
+               reg = WM8962_SPKOUTR_VOLUME;
+               break;
+       case WM8962_SPKOUTL_PGA_ENA_SHIFT:
+               reg = WM8962_SPKOUTL_VOLUME;
+               break;
+       default:
+               BUG();
+               return -EINVAL;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               return snd_soc_write(codec, reg, reg_cache[reg]);
+       default:
+               BUG();
+               return -EINVAL;
+       }
+}
+
+static const char *st_text[] = { "None", "Right", "Left" };
+
+static const struct soc_enum str_enum =
+       SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
+
+static const struct snd_kcontrol_new str_mux =
+       SOC_DAPM_ENUM("Right Sidetone", str_enum);
+
+static const struct soc_enum stl_enum =
+       SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text);
+
+static const struct snd_kcontrol_new stl_mux =
+       SOC_DAPM_ENUM("Left Sidetone", stl_enum);
+
+static const char *outmux_text[] = { "DAC", "Mixer" };
+
+static const struct soc_enum spkoutr_enum =
+       SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new spkoutr_mux =
+       SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum);
+
+static const struct soc_enum spkoutl_enum =
+       SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new spkoutl_mux =
+       SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum);
+
+static const struct soc_enum hpoutr_enum =
+       SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new hpoutr_mux =
+       SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum);
+
+static const struct soc_enum hpoutl_enum =
+       SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text);
+
+static const struct snd_kcontrol_new hpoutl_mux =
+       SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum);
+
+static const struct snd_kcontrol_new inpgal[] = {
+SOC_DAPM_SINGLE("IN1L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 3, 1, 0),
+SOC_DAPM_SINGLE("IN2L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new inpgar[] = {
+SOC_DAPM_SINGLE("IN1R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 3, 1, 0),
+SOC_DAPM_SINGLE("IN2R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinl[] = {
+SOC_DAPM_SINGLE("IN2L Switch", WM8962_INPUT_MIXER_CONTROL_2, 5, 1, 0),
+SOC_DAPM_SINGLE("IN3L Switch", WM8962_INPUT_MIXER_CONTROL_2, 4, 1, 0),
+SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinr[] = {
+SOC_DAPM_SINGLE("IN2R Switch", WM8962_INPUT_MIXER_CONTROL_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN3R Switch", WM8962_INPUT_MIXER_CONTROL_2, 1, 1, 0),
+SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new hpmixl[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_1, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_1, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_1, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_1, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_1, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new hpmixr[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_2, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_2, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_2, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new spkmixl[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_1, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_1, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_1, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_1, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_1, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new spkmixr[] = {
+SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_2, 5, 1, 0),
+SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_2, 4, 1, 0),
+SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_2, 3, 1, 0),
+SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_2, 0, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+SND_SOC_DAPM_INPUT("Beep"),
+
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+
+SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
+                   SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
+                  inpgal, ARRAY_SIZE(inpgal)),
+SND_SOC_DAPM_MIXER("INPGAR", WM8962_RIGHT_INPUT_PGA_CONTROL, 4, 0,
+                  inpgar, ARRAY_SIZE(inpgar)),
+SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
+                  mixinl, ARRAY_SIZE(mixinl)),
+SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
+                  mixinr, ARRAY_SIZE(mixinr)),
+
+SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
+SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
+
+SND_SOC_DAPM_MUX("STL", SND_SOC_NOPM, 0, 0, &stl_mux),
+SND_SOC_DAPM_MUX("STR", SND_SOC_NOPM, 0, 0, &str_mux),
+
+SND_SOC_DAPM_DAC("DACL", "Playback", WM8962_PWR_MGMT_2, 8, 0),
+SND_SOC_DAPM_DAC("DACR", "Playback", WM8962_PWR_MGMT_2, 7, 0),
+
+SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("HPMIXL", WM8962_MIXER_ENABLES, 3, 0,
+                  hpmixl, ARRAY_SIZE(hpmixl)),
+SND_SOC_DAPM_MIXER("HPMIXR", WM8962_MIXER_ENABLES, 2, 0,
+                  hpmixr, ARRAY_SIZE(hpmixr)),
+
+SND_SOC_DAPM_MUX_E("HPOUTL PGA", WM8962_PWR_MGMT_2, 6, 0, &hpoutl_mux,
+                  out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_MUX_E("HPOUTR PGA", WM8962_PWR_MGMT_2, 5, 0, &hpoutr_mux,
+                  out_pga_event, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_OUTPUT("HPOUTL"),
+SND_SOC_DAPM_OUTPUT("HPOUTR"),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = {
+SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0,
+                  spkmixl, ARRAY_SIZE(spkmixl)),
+SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
+                  out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
+SND_SOC_DAPM_OUTPUT("SPKOUT"),
+};
+
+static const struct snd_soc_dapm_widget wm8962_dapm_spk_stereo_widgets[] = {
+SND_SOC_DAPM_MIXER("SPKOUTL Mixer", WM8962_MIXER_ENABLES, 1, 0,
+                  spkmixl, ARRAY_SIZE(spkmixl)),
+SND_SOC_DAPM_MIXER("SPKOUTR Mixer", WM8962_MIXER_ENABLES, 0, 0,
+                  spkmixr, ARRAY_SIZE(spkmixr)),
+
+SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
+                  out_pga_event, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux,
+                  out_pga_event, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+};
+
+static const struct snd_soc_dapm_route wm8962_intercon[] = {
+       { "INPGAL", "IN1L Switch", "IN1L" },
+       { "INPGAL", "IN2L Switch", "IN2L" },
+       { "INPGAL", "IN3L Switch", "IN3L" },
+       { "INPGAL", "IN4L Switch", "IN4L" },
+
+       { "INPGAR", "IN1R Switch", "IN1R" },
+       { "INPGAR", "IN2R Switch", "IN2R" },
+       { "INPGAR", "IN3R Switch", "IN3R" },
+       { "INPGAR", "IN4R Switch", "IN4R" },
+
+       { "MIXINL", "IN2L Switch", "IN2L" },
+       { "MIXINL", "IN3L Switch", "IN3L" },
+       { "MIXINL", "PGA Switch", "INPGAL" },
+
+       { "MIXINR", "IN2R Switch", "IN2R" },
+       { "MIXINR", "IN3R Switch", "IN3R" },
+       { "MIXINR", "PGA Switch", "INPGAR" },
+
+       { "MICBIAS", NULL, "SYSCLK" },
+
+       { "ADCL", NULL, "SYSCLK" },
+       { "ADCL", NULL, "TOCLK" },
+       { "ADCL", NULL, "MIXINL" },
+
+       { "ADCR", NULL, "SYSCLK" },
+       { "ADCR", NULL, "TOCLK" },
+       { "ADCR", NULL, "MIXINR" },
+
+       { "STL", "Left", "ADCL" },
+       { "STL", "Right", "ADCR" },
+
+       { "STR", "Left", "ADCL" },
+       { "STR", "Right", "ADCR" },
+
+       { "DACL", NULL, "SYSCLK" },
+       { "DACL", NULL, "TOCLK" },
+       { "DACL", NULL, "Beep" },
+       { "DACL", NULL, "STL" },
+
+       { "DACR", NULL, "SYSCLK" },
+       { "DACR", NULL, "TOCLK" },
+       { "DACR", NULL, "Beep" },
+       { "DACR", NULL, "STR" },
+
+       { "HPMIXL", "IN4L Switch", "IN4L" },
+       { "HPMIXL", "IN4R Switch", "IN4R" },
+       { "HPMIXL", "DACL Switch", "DACL" },
+       { "HPMIXL", "DACR Switch", "DACR" },
+       { "HPMIXL", "MIXINL Switch", "MIXINL" },
+       { "HPMIXL", "MIXINR Switch", "MIXINR" },
+
+       { "HPMIXR", "IN4L Switch", "IN4L" },
+       { "HPMIXR", "IN4R Switch", "IN4R" },
+       { "HPMIXR", "DACL Switch", "DACL" },
+       { "HPMIXR", "DACR Switch", "DACR" },
+       { "HPMIXR", "MIXINL Switch", "MIXINL" },
+       { "HPMIXR", "MIXINR Switch", "MIXINR" },
+
+       { "Left Bypass", NULL, "HPMIXL" },
+       { "Left Bypass", NULL, "Class G" },
+
+       { "Right Bypass", NULL, "HPMIXR" },
+       { "Right Bypass", NULL, "Class G" },
+
+       { "HPOUTL PGA", "Mixer", "Left Bypass" },
+       { "HPOUTL PGA", "DAC", "DACL" },
+
+       { "HPOUTR PGA", "Mixer", "Right Bypass" },
+       { "HPOUTR PGA", "DAC", "DACR" },
+
+       { "HPOUT", NULL, "HPOUTL PGA" },
+       { "HPOUT", NULL, "HPOUTR PGA" },
+       { "HPOUT", NULL, "Charge Pump" },
+       { "HPOUT", NULL, "SYSCLK" },
+       { "HPOUT", NULL, "TOCLK" },
+
+       { "HPOUTL", NULL, "HPOUT" },
+       { "HPOUTR", NULL, "HPOUT" },
+};
+
+static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
+       { "Speaker Mixer", "IN4L Switch", "IN4L" },
+       { "Speaker Mixer", "IN4R Switch", "IN4R" },
+       { "Speaker Mixer", "DACL Switch", "DACL" },
+       { "Speaker Mixer", "DACR Switch", "DACR" },
+       { "Speaker Mixer", "MIXINL Switch", "MIXINL" },
+       { "Speaker Mixer", "MIXINR Switch", "MIXINR" },
+
+       { "Speaker PGA", "Mixer", "Speaker Mixer" },
+       { "Speaker PGA", "DAC", "DACL" },
+
+       { "Speaker Output", NULL, "Speaker PGA" },
+       { "Speaker Output", NULL, "SYSCLK" },
+       { "Speaker Output", NULL, "TOCLK" },
+
+       { "SPKOUT", NULL, "Speaker Output" },
+};
+
+static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
+       { "SPKOUTL Mixer", "IN4L Switch", "IN4L" },
+       { "SPKOUTL Mixer", "IN4R Switch", "IN4R" },
+       { "SPKOUTL Mixer", "DACL Switch", "DACL" },
+       { "SPKOUTL Mixer", "DACR Switch", "DACR" },
+       { "SPKOUTL Mixer", "MIXINL Switch", "MIXINL" },
+       { "SPKOUTL Mixer", "MIXINR Switch", "MIXINR" },
+
+       { "SPKOUTR Mixer", "IN4L Switch", "IN4L" },
+       { "SPKOUTR Mixer", "IN4R Switch", "IN4R" },
+       { "SPKOUTR Mixer", "DACL Switch", "DACL" },
+       { "SPKOUTR Mixer", "DACR Switch", "DACR" },
+       { "SPKOUTR Mixer", "MIXINL Switch", "MIXINL" },
+       { "SPKOUTR Mixer", "MIXINR Switch", "MIXINR" },
+
+       { "SPKOUTL PGA", "Mixer", "SPKOUTL Mixer" },
+       { "SPKOUTL PGA", "DAC", "DACL" },
+
+       { "SPKOUTR PGA", "Mixer", "SPKOUTR Mixer" },
+       { "SPKOUTR PGA", "DAC", "DACR" },
+
+       { "SPKOUTL Output", NULL, "SPKOUTL PGA" },
+       { "SPKOUTL Output", NULL, "SYSCLK" },
+       { "SPKOUTL Output", NULL, "TOCLK" },
+
+       { "SPKOUTR Output", NULL, "SPKOUTR PGA" },
+       { "SPKOUTR Output", NULL, "SYSCLK" },
+       { "SPKOUTR Output", NULL, "TOCLK" },
+
+       { "SPKOUTL", NULL, "SPKOUTL Output" },
+       { "SPKOUTR", NULL, "SPKOUTR Output" },
+};
+
+static int wm8962_add_widgets(struct snd_soc_codec *codec)
+{
+       struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+
+       snd_soc_add_controls(codec, wm8962_snd_controls,
+                            ARRAY_SIZE(wm8962_snd_controls));
+       if (pdata && pdata->spk_mono)
+               snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+                                    ARRAY_SIZE(wm8962_spk_mono_controls));
+       else
+               snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+                                    ARRAY_SIZE(wm8962_spk_stereo_controls));
+
+
+       snd_soc_dapm_new_controls(codec, wm8962_dapm_widgets,
+                                 ARRAY_SIZE(wm8962_dapm_widgets));
+       if (pdata && pdata->spk_mono)
+               snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_mono_widgets,
+                                         ARRAY_SIZE(wm8962_dapm_spk_mono_widgets));
+       else
+               snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_stereo_widgets,
+                                         ARRAY_SIZE(wm8962_dapm_spk_stereo_widgets));
+
+       snd_soc_dapm_add_routes(codec, wm8962_intercon,
+                               ARRAY_SIZE(wm8962_intercon));
+       if (pdata && pdata->spk_mono)
+               snd_soc_dapm_add_routes(codec, wm8962_spk_mono_intercon,
+                                       ARRAY_SIZE(wm8962_spk_mono_intercon));
+       else
+               snd_soc_dapm_add_routes(codec, wm8962_spk_stereo_intercon,
+                                       ARRAY_SIZE(wm8962_spk_stereo_intercon));
+
+
+       snd_soc_dapm_disable_pin(codec, "Beep");
+
+       return 0;
+}
+
+static void wm8962_sync_cache(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int i;
+
+       if (!codec->cache_sync)
+               return;
+
+       dev_dbg(codec->dev, "Syncing cache\n");
+
+       codec->cache_only = 0;
+
+       /* Sync back cached values if they're different from the
+        * hardware default.
+        */
+       for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+               if (i == WM8962_SOFTWARE_RESET)
+                       continue;
+               if (wm8962->reg_cache[i] == wm8962_reg[i])
+                       continue;
+
+               snd_soc_write(codec, i, wm8962->reg_cache[i]);
+       }
+
+       codec->cache_sync = 0;
+}
+
+/* -1 for reserved values */
+static const int bclk_divs[] = {
+       1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
+};
+
+static void wm8962_configure_bclk(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int dspclk, i;
+       int clocking2 = 0;
+       int aif2 = 0;
+
+       if (!wm8962->bclk) {
+               dev_dbg(codec->dev, "No BCLK rate configured\n");
+               return;
+       }
+
+       dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
+       if (dspclk < 0) {
+               dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
+               return;
+       }
+
+       dspclk = (dspclk & WM8962_DSPCLK_DIV_MASK) >> WM8962_DSPCLK_DIV_SHIFT;
+       switch (dspclk) {
+       case 0:
+               dspclk = wm8962->sysclk_rate;
+               break;
+       case 1:
+               dspclk = wm8962->sysclk_rate / 2;
+               break;
+       case 2:
+               dspclk = wm8962->sysclk_rate / 4;
+               break;
+       default:
+               dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n");
+               dspclk = wm8962->sysclk;
+       }
+
+       dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
+
+       /* We're expecting an exact match */
+       for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+               if (bclk_divs[i] < 0)
+                       continue;
+
+               if (dspclk / bclk_divs[i] == wm8962->bclk) {
+                       dev_dbg(codec->dev, "Selected BCLK_DIV %d for %dHz\n",
+                               bclk_divs[i], wm8962->bclk);
+                       clocking2 |= i;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(bclk_divs)) {
+               dev_err(codec->dev, "Unsupported BCLK ratio %d\n",
+                       dspclk / wm8962->bclk);
+               return;
+       }
+
+       aif2 |= wm8962->bclk / wm8962->lrclk;
+       dev_dbg(codec->dev, "Selected LRCLK divisor %d for %dHz\n",
+               wm8962->bclk / wm8962->lrclk, wm8962->lrclk);
+
+       snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                           WM8962_BCLK_DIV_MASK, clocking2);
+       snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_2,
+                           WM8962_AIF_RATE_MASK, aif2);
+}
+
+static int wm8962_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       if (level == codec->bias_level)
+               return 0;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               /* VMID 2*50k */
+               snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+                                   WM8962_VMID_SEL_MASK, 0x80);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+                                                   wm8962->supplies);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       wm8962_sync_cache(codec);
+
+                       snd_soc_update_bits(codec, WM8962_ANTI_POP,
+                                           WM8962_STARTUP_BIAS_ENA |
+                                           WM8962_VMID_BUF_ENA,
+                                           WM8962_STARTUP_BIAS_ENA |
+                                           WM8962_VMID_BUF_ENA);
+
+                       /* Bias enable at 2*50k for ramp */
+                       snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+                                           WM8962_VMID_SEL_MASK |
+                                           WM8962_BIAS_ENA,
+                                           WM8962_BIAS_ENA | 0x180);
+
+                       msleep(5);
+
+                       snd_soc_update_bits(codec, WM8962_CLOCKING2,
+                                           WM8962_CLKREG_OVD,
+                                           WM8962_CLKREG_OVD);
+
+                       wm8962_configure_bclk(codec);
+               }
+
+               /* VMID 2*250k */
+               snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+                                   WM8962_VMID_SEL_MASK, 0x100);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
+                                   WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+               snd_soc_update_bits(codec, WM8962_ANTI_POP,
+                                   WM8962_STARTUP_BIAS_ENA |
+                                   WM8962_VMID_BUF_ENA, 0);
+
+               regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+                                      wm8962->supplies);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+static const struct {
+       int rate;
+       int reg;
+} sr_vals[] = {
+       { 48000, 0 },
+       { 44100, 0 },
+       { 32000, 1 },
+       { 22050, 2 },
+       { 24000, 2 },
+       { 16000, 3 },
+       { 11025, 4 },
+       { 12000, 4 },
+       { 8000,  5 },
+       { 88200, 6 },
+       { 96000, 6 },
+};
+
+static const int sysclk_rates[] = {
+       64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+};
+
+static int wm8962_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_codec *codec = rtd->codec;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int rate = params_rate(params);
+       int i;
+       int aif0 = 0;
+       int adctl3 = 0;
+       int clocking4 = 0;
+
+       wm8962->bclk = snd_soc_params_to_bclk(params);
+       wm8962->lrclk = params_rate(params);
+
+       for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
+               if (sr_vals[i].rate == rate) {
+                       adctl3 |= sr_vals[i].reg;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(sr_vals)) {
+               dev_err(codec->dev, "Unsupported rate %dHz\n", rate);
+               return -EINVAL;
+       }
+
+       if (rate % 8000 == 0)
+               adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
+
+       for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
+               if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
+                       clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(sysclk_rates)) {
+               dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
+                       wm8962->sysclk_rate / rate);
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               aif0 |= 0x40;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               aif0 |= 0x80;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               aif0 |= 0xc0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
+                           WM8962_WL_MASK, aif0);
+       snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
+                           WM8962_SAMPLE_RATE_INT_MODE |
+                           WM8962_SAMPLE_RATE_MASK, adctl3);
+       snd_soc_update_bits(codec, WM8962_CLOCKING_4,
+                           WM8962_SYSCLK_RATE_MASK, clocking4);
+
+       wm8962_configure_bclk(codec);
+
+       return 0;
+}
+
+static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int src;
+
+       switch (clk_id) {
+       case WM8962_SYSCLK_MCLK:
+               wm8962->sysclk = WM8962_SYSCLK_MCLK;
+               src = 0;
+               break;
+       case WM8962_SYSCLK_FLL:
+               wm8962->sysclk = WM8962_SYSCLK_FLL;
+               src = 1 << WM8962_SYSCLK_SRC_SHIFT;
+               WARN_ON(freq != wm8962->fll_fout);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_SRC_MASK,
+                           src);
+
+       wm8962->sysclk_rate = freq;
+
+       return 0;
+}
+
+static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int aif0 = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               aif0 |= WM8962_LRCLK_INV;
+       case SND_SOC_DAIFMT_DSP_B:
+               aif0 |= 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;
+
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               aif0 |= 1;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               aif0 |= 2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               aif0 |= WM8962_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               aif0 |= WM8962_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               aif0 |= WM8962_BCLK_INV | WM8962_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               aif0 |= WM8962_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
+                           WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR |
+                           WM8962_LRCLK_INV, aif0);
+
+       return 0;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_refclk_div;
+       u16 n;
+       u16 theta;
+       u16 lambda;
+};
+
+/* 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)
+{
+       unsigned int target;
+       unsigned int div;
+       unsigned int fratio, gcd_fll;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_refclk_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_refclk_div++;
+
+               if (div > 4) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("FLL 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 = 2;
+       while (Fout * div < 90000000) {
+               div++;
+               if (div > 64) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       target = Fout * div;
+       fll_div->fll_outdiv = div - 1;
+
+       pr_debug("FLL 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;
+                       fratio = 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;
+       }
+
+       fll_div->n = target / (fratio * Fref);
+
+       if (target % Fref == 0) {
+               fll_div->theta = 0;
+               fll_div->lambda = 0;
+       } else {
+               gcd_fll = gcd(target, fratio * Fref);
+
+               fll_div->theta = (target - (fll_div->n * fratio * Fref))
+                       / gcd_fll;
+               fll_div->lambda = (fratio * Fref) / gcd_fll;
+       }
+
+       pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+                fll_div->n, fll_div->theta, fll_div->lambda);
+       pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+                fll_div->fll_fratio, fll_div->fll_outdiv,
+                fll_div->fll_refclk_div);
+
+       return 0;
+}
+
+static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       struct _fll_div fll_div;
+       int ret;
+       int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
+
+       /* Any change? */
+       if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
+           Fout == wm8962->fll_fout)
+               return 0;
+
+       if (Fout == 0) {
+               dev_dbg(codec->dev, "FLL disabled\n");
+
+               wm8962->fll_fref = 0;
+               wm8962->fll_fout = 0;
+
+               snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+                                   WM8962_FLL_ENA, 0);
+
+               return 0;
+       }
+
+       ret = fll_factors(&fll_div, Fref, Fout);
+       if (ret != 0)
+               return ret;
+
+       switch (fll_id) {
+       case WM8962_FLL_MCLK:
+       case WM8962_FLL_BCLK:
+       case WM8962_FLL_OSC:
+               fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
+               break;
+       case WM8962_FLL_INT:
+               snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+                                   WM8962_FLL_OSC_ENA, WM8962_FLL_OSC_ENA);
+               snd_soc_update_bits(codec, WM8962_FLL_CONTROL_5,
+                                   WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO);
+               break;
+       default:
+               dev_err(codec->dev, "Unknown FLL source %d\n", ret);
+               return -EINVAL;
+       }
+
+       if (fll_div.theta || fll_div.lambda)
+               fll1 |= WM8962_FLL_FRAC;
+
+       /* Stop the FLL while we reconfigure */
+       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
+       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2,
+                           WM8962_FLL_OUTDIV_MASK |
+                           WM8962_FLL_REFCLK_DIV_MASK,
+                           (fll_div.fll_outdiv << WM8962_FLL_OUTDIV_SHIFT) |
+                           (fll_div.fll_refclk_div));
+
+       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_3,
+                           WM8962_FLL_FRATIO_MASK, fll_div.fll_fratio);
+
+       snd_soc_write(codec, WM8962_FLL_CONTROL_6, fll_div.theta);
+       snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda);
+       snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n);
+
+       snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
+                           WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
+                           WM8962_FLL_ENA, fll1);
+
+       dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
+
+       wm8962->fll_fref = Fref;
+       wm8962->fll_fout = Fout;
+       wm8962->fll_src = source;
+
+       return 0;
+}
+
+static int wm8962_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int val;
+
+       if (mute)
+               val = WM8962_DAC_MUTE;
+       else
+               val = 0;
+
+       return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+                                  WM8962_DAC_MUTE, val);
+}
+
+#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
+
+#define WM8962_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 wm8962_dai_ops = {
+       .hw_params = wm8962_hw_params,
+       .set_sysclk = wm8962_set_dai_sysclk,
+       .set_fmt = wm8962_set_dai_fmt,
+       .set_pll = wm8962_set_fll,
+       .digital_mute = wm8962_mute,
+};
+
+static struct snd_soc_dai_driver wm8962_dai = {
+       .name = "wm8962",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = WM8962_RATES,
+               .formats = WM8962_FORMATS,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = WM8962_RATES,
+               .formats = WM8962_FORMATS,
+       },
+       .ops = &wm8962_dai_ops,
+       .symmetric_rates = 1,
+};
+
+static void wm8962_mic_work(struct work_struct *work)
+{
+       struct wm8962_priv *wm8962 = container_of(work,
+                                                 struct wm8962_priv,
+                                                 mic_work.work);
+       struct snd_soc_codec *codec = wm8962->codec;
+       int status = 0;
+       int irq_pol = 0;
+       int reg;
+
+       reg = snd_soc_read(codec, WM8962_ADDITIONAL_CONTROL_4);
+
+       if (reg & WM8962_MICDET_STS) {
+               status |= SND_JACK_MICROPHONE;
+               irq_pol |= WM8962_MICD_IRQ_POL;
+       }
+
+       if (reg & WM8962_MICSHORT_STS) {
+               status |= SND_JACK_BTN_0;
+               irq_pol |= WM8962_MICSCD_IRQ_POL;
+       }
+
+       snd_soc_jack_report(wm8962->jack, status,
+                           SND_JACK_MICROPHONE | SND_JACK_BTN_0);
+
+       snd_soc_update_bits(codec, WM8962_MICINT_SOURCE_POL,
+                           WM8962_MICSCD_IRQ_POL |
+                           WM8962_MICD_IRQ_POL, irq_pol);
+}
+
+static irqreturn_t wm8962_irq(int irq, void *data)
+{
+       struct snd_soc_codec *codec = data;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int mask;
+       int active;
+
+       mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+
+       active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
+       active &= ~mask;
+
+       if (active & WM8962_FIFOS_ERR_EINT)
+               dev_err(codec->dev, "FIFO error\n");
+
+       if (active & WM8962_TEMP_SHUT_EINT)
+               dev_crit(codec->dev, "Thermal shutdown\n");
+
+       if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
+               dev_dbg(codec->dev, "Microphone event detected\n");
+
+               schedule_delayed_work(&wm8962->mic_work,
+                                     msecs_to_jiffies(250));
+       }
+
+       /* Acknowledge the interrupts */
+       snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * wm8962_mic_detect - Enable microphone detection via the WM8962 IRQ
+ *
+ * @codec:  WM8962 codec
+ * @jack:   jack to report detection events on
+ *
+ * Enable microphone detection via IRQ on the WM8962.  If GPIOs are
+ * being used to bring out signals to the processor then only platform
+ * data configuration is needed for WM8962 and processor GPIOs should
+ * be configured using snd_soc_jack_add_gpios() instead.
+ *
+ * If no jack is supplied detection will be disabled.
+ */
+int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int irq_mask, enable;
+
+       wm8962->jack = jack;
+       if (jack) {
+               irq_mask = 0;
+               enable = WM8962_MICDET_ENA;
+       } else {
+               irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
+               enable = 0;
+       }
+
+       snd_soc_update_bits(codec, WM8962_INTERRUPT_STATUS_2_MASK,
+                           WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
+       snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
+                           WM8962_MICDET_ENA, enable);
+
+       /* Send an initial empty report */
+       snd_soc_jack_report(wm8962->jack, 0,
+                           SND_JACK_MICROPHONE | SND_JACK_BTN_0);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm8962_mic_detect);
+
+#ifdef CONFIG_PM
+static int wm8962_resume(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
+       int i;
+
+       /* Restore the registers */
+       for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+               switch (i) {
+               case WM8962_SOFTWARE_RESET:
+                       continue;
+               default:
+                       break;
+               }
+
+               if (reg_cache[i] != wm8962_reg[i])
+                       snd_soc_write(codec, i, reg_cache[i]);
+       }
+
+       return 0;
+}
+#else
+#define wm8962_resume NULL
+#endif
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int beep_rates[] = {
+       500, 1000, 2000, 4000,
+};
+
+static void wm8962_beep_work(struct work_struct *work)
+{
+       struct wm8962_priv *wm8962 =
+               container_of(work, struct wm8962_priv, beep_work);
+       struct snd_soc_codec *codec = wm8962->codec;
+       int i;
+       int reg = 0;
+       int best = 0;
+
+       if (wm8962->beep_rate) {
+               for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
+                       if (abs(wm8962->beep_rate - beep_rates[i]) <
+                           abs(wm8962->beep_rate - beep_rates[best]))
+                               best = i;
+               }
+
+               dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
+                       beep_rates[best], wm8962->beep_rate);
+
+               reg = WM8962_BEEP_ENA | (best << WM8962_BEEP_RATE_SHIFT);
+
+               snd_soc_dapm_enable_pin(codec, "Beep");
+       } else {
+               dev_dbg(codec->dev, "Disabling beep\n");
+               snd_soc_dapm_disable_pin(codec, "Beep");
+       }
+
+       snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1,
+                           WM8962_BEEP_ENA | WM8962_BEEP_RATE_MASK, reg);
+
+       snd_soc_dapm_sync(codec);
+}
+
+/* For usability define a way of injecting beep events for the device -
+ * many systems will not have a keyboard.
+ */
+static int wm8962_beep_event(struct input_dev *dev, unsigned int type,
+                            unsigned int code, int hz)
+{
+       struct snd_soc_codec *codec = input_get_drvdata(dev);
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+       dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
+
+       switch (code) {
+       case SND_BELL:
+               if (hz)
+                       hz = 1000;
+       case SND_TONE:
+               break;
+       default:
+               return -1;
+       }
+
+       /* Kick the beep from a workqueue */
+       wm8962->beep_rate = hz;
+       schedule_work(&wm8962->beep_work);
+       return 0;
+}
+
+static ssize_t wm8962_beep_set(struct device *dev,
+                              struct device_attribute *attr,
+                              const char *buf, size_t count)
+{
+       struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+       long int time;
+
+       strict_strtol(buf, 10, &time);
+
+       input_event(wm8962->beep, EV_SND, SND_TONE, time);
+
+       return count;
+}
+
+static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set);
+
+static void wm8962_init_beep(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       wm8962->beep = input_allocate_device();
+       if (!wm8962->beep) {
+               dev_err(codec->dev, "Failed to allocate beep device\n");
+               return;
+       }
+
+       INIT_WORK(&wm8962->beep_work, wm8962_beep_work);
+       wm8962->beep_rate = 0;
+
+       wm8962->beep->name = "WM8962 Beep Generator";
+       wm8962->beep->phys = dev_name(codec->dev);
+       wm8962->beep->id.bustype = BUS_I2C;
+
+       wm8962->beep->evbit[0] = BIT_MASK(EV_SND);
+       wm8962->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
+       wm8962->beep->event = wm8962_beep_event;
+       wm8962->beep->dev.parent = codec->dev;
+       input_set_drvdata(wm8962->beep, codec);
+
+       ret = input_register_device(wm8962->beep);
+       if (ret != 0) {
+               input_free_device(wm8962->beep);
+               wm8962->beep = NULL;
+               dev_err(codec->dev, "Failed to register beep device\n");
+       }
+
+       ret = device_create_file(codec->dev, &dev_attr_beep);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to create keyclick file: %d\n",
+                       ret);
+       }
+}
+
+static void wm8962_free_beep(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+       device_remove_file(codec->dev, &dev_attr_beep);
+       input_unregister_device(wm8962->beep);
+       cancel_work_sync(&wm8962->beep_work);
+       wm8962->beep = NULL;
+
+       snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0);
+}
+#else
+static void wm8962_init_beep(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8962_free_beep(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
+{
+       int mask = 0;
+       int val = 0;
+
+       /* Some of the GPIOs are behind MFP configuration and need to
+        * be put into GPIO mode. */
+       switch (gpio) {
+       case 2:
+               mask = WM8962_CLKOUT2_SEL_MASK;
+               val = 1 << WM8962_CLKOUT2_SEL_SHIFT;
+               break;
+       case 3:
+               mask = WM8962_CLKOUT3_SEL_MASK;
+               val = 1 << WM8962_CLKOUT3_SEL_SHIFT;
+               break;
+       default:
+               break;
+       }
+
+       if (mask)
+               snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,
+                                   mask, val);
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip)
+{
+       return container_of(chip, struct wm8962_priv, gpio_chip);
+}
+
+static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+       struct snd_soc_codec *codec = wm8962->codec;
+
+       /* The WM8962 GPIOs aren't linearly numbered.  For simplicity
+        * we export linear numbers and error out if the unsupported
+        * ones are requsted.
+        */
+       switch (offset + 1) {
+       case 2:
+       case 3:
+       case 5:
+       case 6:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       wm8962_set_gpio_mode(codec, offset + 1);
+
+       return 0;
+}
+
+static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+       struct snd_soc_codec *codec = wm8962->codec;
+
+       snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
+                           WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);
+}
+
+static int wm8962_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned offset, int value)
+{
+       struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
+       struct snd_soc_codec *codec = wm8962->codec;
+       int val;
+
+       /* Force function 1 (logic output) */
+       val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT);
+
+       return snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
+                                  WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);
+}
+
+static struct gpio_chip wm8962_template_chip = {
+       .label                  = "wm8962",
+       .owner                  = THIS_MODULE,
+       .request                = wm8962_gpio_request,
+       .direction_output       = wm8962_gpio_direction_out,
+       .set                    = wm8962_gpio_set,
+       .can_sleep              = 1,
+};
+
+static void wm8962_init_gpio(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+       int ret;
+
+       wm8962->gpio_chip = wm8962_template_chip;
+       wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO;
+       wm8962->gpio_chip.dev = codec->dev;
+
+       if (pdata && pdata->gpio_base)
+               wm8962->gpio_chip.base = pdata->gpio_base;
+       else
+               wm8962->gpio_chip.base = -1;
+
+       ret = gpiochip_add(&wm8962->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm8962_free_gpio(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+
+       ret = gpiochip_remove(&wm8962->gpio_chip);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm8962_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8962_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
+static int wm8962_probe(struct snd_soc_codec *codec)
+{
+       int ret;
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
+       struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
+                                             dev);
+       int i, trigger, irq_pol;
+
+       wm8962->codec = codec;
+       INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
+
+       codec->cache_sync = 1;
+       codec->idle_bias_off = 1;
+
+       ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+               wm8962->supplies[i].supply = wm8962_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
+                                wm8962->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
+       wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
+       wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2;
+       wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3;
+       wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4;
+       wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5;
+       wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6;
+       wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
+               ret = regulator_register_notifier(wm8962->supplies[i].consumer,
+                                                 &wm8962->disable_nb[i]);
+               if (ret != 0) {
+                       dev_err(codec->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+                                   wm8962->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
+
+       ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read ID register\n");
+               goto err_enable;
+       }
+       if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
+               dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
+                       ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
+               ret = -EINVAL;
+               goto err_enable;
+       }
+
+       ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read device revision: %d\n",
+                       ret);
+               goto err_enable;
+       }
+       
+       dev_info(codec->dev, "customer id %x revision %c\n",
+                (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
+                ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
+                + 'A');
+
+       ret = wm8962_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err_enable;
+       }
+
+       /* SYSCLK defaults to on; make sure it is off so we can safely
+        * write to registers if the device is declocked.
+        */
+       snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
+
+       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+       if (pdata) {
+               /* Apply static configuration for GPIOs */
+               for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
+                       if (pdata->gpio_init[i]) {
+                               wm8962_set_gpio_mode(codec, i + 1);
+                               snd_soc_write(codec, 0x200 + i,
+                                             pdata->gpio_init[i] & 0xffff);
+                       }
+
+               /* Put the speakers into mono mode? */
+               if (pdata->spk_mono)
+                       wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
+                               |= WM8962_SPK_MONO;
+
+               /* Micbias setup, detection enable and detection
+                * threasholds. */
+               if (pdata->mic_cfg)
+                       snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
+                                           WM8962_MICDET_ENA |
+                                           WM8962_MICDET_THR_MASK |
+                                           WM8962_MICSHORT_THR_MASK |
+                                           WM8962_MICBIAS_LVL,
+                                           pdata->mic_cfg);
+       }
+
+       /* Latch volume update bits */
+       wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
+       wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
+       wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
+       wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;    
+       wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
+       wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
+       wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
+       wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
+       wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
+       wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+
+       wm8962_add_widgets(codec);
+
+       wm8962_init_beep(codec);
+       wm8962_init_gpio(codec);
+
+       if (i2c->irq) {
+               if (pdata && pdata->irq_active_low) {
+                       trigger = IRQF_TRIGGER_LOW;
+                       irq_pol = WM8962_IRQ_POL;
+               } else {
+                       trigger = IRQF_TRIGGER_HIGH;
+                       irq_pol = 0;
+               }
+
+               snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
+                                   WM8962_IRQ_POL, irq_pol);
+
+               ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
+                                          trigger | IRQF_ONESHOT,
+                                          "wm8962", codec);
+               if (ret != 0) {
+                       dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
+                               i2c->irq, ret);
+                       /* Non-fatal */
+               } else {
+                       /* Enable error reporting IRQs by default */
+                       snd_soc_update_bits(codec,
+                                           WM8962_INTERRUPT_STATUS_2_MASK,
+                                           WM8962_TEMP_SHUT_EINT |
+                                           WM8962_FIFOS_ERR_EINT, 0);
+               }
+       }
+
+       return 0;
+
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err:
+       kfree(wm8962);
+       return ret;
+}
+
+static int wm8962_remove(struct snd_soc_codec *codec)
+{
+       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
+                                             dev);
+       int i;
+
+       if (i2c->irq)
+               free_irq(i2c->irq, codec);
+
+       cancel_delayed_work_sync(&wm8962->mic_work);
+
+       wm8962_free_gpio(codec);
+       wm8962_free_beep(codec);
+       for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+               regulator_unregister_notifier(wm8962->supplies[i].consumer,
+                                             &wm8962->disable_nb[i]);
+       regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+       return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
+       .probe =        wm8962_probe,
+       .remove =       wm8962_remove,
+       .resume =       wm8962_resume,
+       .set_bias_level = wm8962_set_bias_level,
+       .reg_cache_size = WM8962_MAX_REGISTER + 1,
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8962_reg,
+       .volatile_register = wm8962_volatile_register,
+       .readable_register = wm8962_readable_register,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8962_priv *wm8962;
+       int ret;
+
+       wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
+       if (wm8962 == NULL)
+               return -ENOMEM;
+
+       i2c_set_clientdata(i2c, wm8962);
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm8962, &wm8962_dai, 1);
+       if (ret < 0)
+               kfree(wm8962);
+
+       return ret;
+}
+
+static __devexit int wm8962_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm8962_i2c_id[] = {
+       { "wm8962", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id);
+
+static struct i2c_driver wm8962_i2c_driver = {
+       .driver = {
+               .name = "wm8962",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8962_i2c_probe,
+       .remove =   __devexit_p(wm8962_i2c_remove),
+       .id_table = wm8962_i2c_id,
+};
+#endif
+
+static int __init wm8962_modinit(void)
+{
+       int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8962_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+       return 0;
+}
+module_init(wm8962_modinit);
+
+static void __exit wm8962_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8962_i2c_driver);
+#endif
+}
+module_exit(wm8962_exit);
+
+MODULE_DESCRIPTION("ASoC WM8962 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
new file mode 100644 (file)
index 0000000..a1a5d52
--- /dev/null
@@ -0,0 +1,3780 @@
+/*
+ * wm8962.h  --  WM8962 ASoC driver
+ *
+ * Copyright 2010 Wolfson Microelectronics, plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8962_H
+#define _WM8962_H
+
+#include <asm/types.h>
+#include <sound/soc.h>
+
+#define WM8962_SYSCLK_MCLK 1
+#define WM8962_SYSCLK_FLL  2
+#define WM8962_SYSCLK_PLL3 3
+
+#define WM8962_FLL  1
+
+#define WM8962_FLL_MCLK 1
+#define WM8962_FLL_BCLK 2
+#define WM8962_FLL_OSC  3
+#define WM8962_FLL_INT  4
+
+/*
+ * Register values.
+ */
+#define WM8962_LEFT_INPUT_VOLUME                0x00
+#define WM8962_RIGHT_INPUT_VOLUME               0x01
+#define WM8962_HPOUTL_VOLUME                    0x02
+#define WM8962_HPOUTR_VOLUME                    0x03
+#define WM8962_CLOCKING1                        0x04
+#define WM8962_ADC_DAC_CONTROL_1                0x05
+#define WM8962_ADC_DAC_CONTROL_2                0x06
+#define WM8962_AUDIO_INTERFACE_0                0x07
+#define WM8962_CLOCKING2                        0x08
+#define WM8962_AUDIO_INTERFACE_1                0x09
+#define WM8962_LEFT_DAC_VOLUME                  0x0A
+#define WM8962_RIGHT_DAC_VOLUME                 0x0B
+#define WM8962_AUDIO_INTERFACE_2                0x0E
+#define WM8962_SOFTWARE_RESET                   0x0F
+#define WM8962_ALC1                             0x11
+#define WM8962_ALC2                             0x12
+#define WM8962_ALC3                             0x13
+#define WM8962_NOISE_GATE                       0x14
+#define WM8962_LEFT_ADC_VOLUME                  0x15
+#define WM8962_RIGHT_ADC_VOLUME                 0x16
+#define WM8962_ADDITIONAL_CONTROL_1             0x17
+#define WM8962_ADDITIONAL_CONTROL_2             0x18
+#define WM8962_PWR_MGMT_1                       0x19
+#define WM8962_PWR_MGMT_2                       0x1A
+#define WM8962_ADDITIONAL_CONTROL_3             0x1B
+#define WM8962_ANTI_POP                         0x1C
+#define WM8962_CLOCKING_3                       0x1E
+#define WM8962_INPUT_MIXER_CONTROL_1            0x1F
+#define WM8962_LEFT_INPUT_MIXER_VOLUME          0x20
+#define WM8962_RIGHT_INPUT_MIXER_VOLUME         0x21
+#define WM8962_INPUT_MIXER_CONTROL_2            0x22
+#define WM8962_INPUT_BIAS_CONTROL               0x23
+#define WM8962_LEFT_INPUT_PGA_CONTROL           0x25
+#define WM8962_RIGHT_INPUT_PGA_CONTROL          0x26
+#define WM8962_SPKOUTL_VOLUME                   0x28
+#define WM8962_SPKOUTR_VOLUME                   0x29
+#define WM8962_THERMAL_SHUTDOWN_STATUS          0x2F
+#define WM8962_ADDITIONAL_CONTROL_4             0x30
+#define WM8962_CLASS_D_CONTROL_1                0x31
+#define WM8962_CLASS_D_CONTROL_2                0x33
+#define WM8962_CLOCKING_4                       0x38
+#define WM8962_DAC_DSP_MIXING_1                 0x39
+#define WM8962_DAC_DSP_MIXING_2                 0x3A
+#define WM8962_DC_SERVO_0                       0x3C
+#define WM8962_DC_SERVO_1                       0x3D
+#define WM8962_DC_SERVO_4                       0x40
+#define WM8962_DC_SERVO_6                       0x42
+#define WM8962_ANALOGUE_PGA_BIAS                0x44
+#define WM8962_ANALOGUE_HP_0                    0x45
+#define WM8962_ANALOGUE_HP_2                    0x47
+#define WM8962_CHARGE_PUMP_1                    0x48
+#define WM8962_CHARGE_PUMP_B                    0x52
+#define WM8962_WRITE_SEQUENCER_CONTROL_1        0x57
+#define WM8962_WRITE_SEQUENCER_CONTROL_2        0x5A
+#define WM8962_WRITE_SEQUENCER_CONTROL_3        0x5D
+#define WM8962_CONTROL_INTERFACE                0x5E
+#define WM8962_MIXER_ENABLES                    0x63
+#define WM8962_HEADPHONE_MIXER_1                0x64
+#define WM8962_HEADPHONE_MIXER_2                0x65
+#define WM8962_HEADPHONE_MIXER_3                0x66
+#define WM8962_HEADPHONE_MIXER_4                0x67
+#define WM8962_SPEAKER_MIXER_1                  0x69
+#define WM8962_SPEAKER_MIXER_2                  0x6A
+#define WM8962_SPEAKER_MIXER_3                  0x6B
+#define WM8962_SPEAKER_MIXER_4                  0x6C
+#define WM8962_SPEAKER_MIXER_5                  0x6D
+#define WM8962_BEEP_GENERATOR_1                 0x6E
+#define WM8962_OSCILLATOR_TRIM_3                0x73
+#define WM8962_OSCILLATOR_TRIM_4                0x74
+#define WM8962_OSCILLATOR_TRIM_7                0x77
+#define WM8962_ANALOGUE_CLOCKING1               0x7C
+#define WM8962_ANALOGUE_CLOCKING2               0x7D
+#define WM8962_ANALOGUE_CLOCKING3               0x7E
+#define WM8962_PLL_SOFTWARE_RESET               0x7F
+#define WM8962_PLL2                             0x81
+#define WM8962_PLL_4                            0x83
+#define WM8962_PLL_9                            0x88
+#define WM8962_PLL_10                           0x89
+#define WM8962_PLL_11                           0x8A
+#define WM8962_PLL_12                           0x8B
+#define WM8962_PLL_13                           0x8C
+#define WM8962_PLL_14                           0x8D
+#define WM8962_PLL_15                           0x8E
+#define WM8962_PLL_16                           0x8F
+#define WM8962_FLL_CONTROL_1                    0x9B
+#define WM8962_FLL_CONTROL_2                    0x9C
+#define WM8962_FLL_CONTROL_3                    0x9D
+#define WM8962_FLL_CONTROL_5                    0x9F
+#define WM8962_FLL_CONTROL_6                    0xA0
+#define WM8962_FLL_CONTROL_7                    0xA1
+#define WM8962_FLL_CONTROL_8                    0xA2
+#define WM8962_GENERAL_TEST_1                   0xFC
+#define WM8962_DF1                              0x100
+#define WM8962_DF2                              0x101
+#define WM8962_DF3                              0x102
+#define WM8962_DF4                              0x103
+#define WM8962_DF5                              0x104
+#define WM8962_DF6                              0x105
+#define WM8962_DF7                              0x106
+#define WM8962_LHPF1                            0x108
+#define WM8962_LHPF2                            0x109
+#define WM8962_THREED1                          0x10C
+#define WM8962_THREED2                          0x10D
+#define WM8962_THREED3                          0x10E
+#define WM8962_THREED4                          0x10F
+#define WM8962_DRC_1                            0x114
+#define WM8962_DRC_2                            0x115
+#define WM8962_DRC_3                            0x116
+#define WM8962_DRC_4                            0x117
+#define WM8962_DRC_5                            0x118
+#define WM8962_TLOOPBACK                        0x11D
+#define WM8962_EQ1                              0x14F
+#define WM8962_EQ2                              0x150
+#define WM8962_EQ3                              0x151
+#define WM8962_EQ4                              0x152
+#define WM8962_EQ5                              0x153
+#define WM8962_EQ6                              0x154
+#define WM8962_EQ7                              0x155
+#define WM8962_EQ8                              0x156
+#define WM8962_EQ9                              0x157
+#define WM8962_EQ10                             0x158
+#define WM8962_EQ11                             0x159
+#define WM8962_EQ12                             0x15A
+#define WM8962_EQ13                             0x15B
+#define WM8962_EQ14                             0x15C
+#define WM8962_EQ15                             0x15D
+#define WM8962_EQ16                             0x15E
+#define WM8962_EQ17                             0x15F
+#define WM8962_EQ18                             0x160
+#define WM8962_EQ19                             0x161
+#define WM8962_EQ20                             0x162
+#define WM8962_EQ21                             0x163
+#define WM8962_EQ22                             0x164
+#define WM8962_EQ23                             0x165
+#define WM8962_EQ24                             0x166
+#define WM8962_EQ25                             0x167
+#define WM8962_EQ26                             0x168
+#define WM8962_EQ27                             0x169
+#define WM8962_EQ28                             0x16A
+#define WM8962_EQ29                             0x16B
+#define WM8962_EQ30                             0x16C
+#define WM8962_EQ31                             0x16D
+#define WM8962_EQ32                             0x16E
+#define WM8962_EQ33                             0x16F
+#define WM8962_EQ34                             0x170
+#define WM8962_EQ35                             0x171
+#define WM8962_EQ36                             0x172
+#define WM8962_EQ37                             0x173
+#define WM8962_EQ38                             0x174
+#define WM8962_EQ39                             0x175
+#define WM8962_EQ40                             0x176
+#define WM8962_EQ41                             0x177
+#define WM8962_GPIO_BASE                       0x200
+#define WM8962_GPIO_2                           0x201
+#define WM8962_GPIO_3                           0x202
+#define WM8962_GPIO_5                           0x204
+#define WM8962_GPIO_6                           0x205
+#define WM8962_INTERRUPT_STATUS_1               0x230
+#define WM8962_INTERRUPT_STATUS_2               0x231
+#define WM8962_INTERRUPT_STATUS_1_MASK          0x238
+#define WM8962_INTERRUPT_STATUS_2_MASK          0x239
+#define WM8962_INTERRUPT_CONTROL                0x240
+#define WM8962_IRQ_DEBOUNCE                     0x248
+#define WM8962_MICINT_SOURCE_POL                0x24A
+#define WM8962_DSP2_POWER_MANAGEMENT            0x300
+#define WM8962_DSP2_EXECCONTROL                 0x40D
+#define WM8962_WRITE_SEQUENCER_0                0x1000
+#define WM8962_WRITE_SEQUENCER_1                0x1001
+#define WM8962_WRITE_SEQUENCER_2                0x1002
+#define WM8962_WRITE_SEQUENCER_3                0x1003
+#define WM8962_WRITE_SEQUENCER_4                0x1004
+#define WM8962_WRITE_SEQUENCER_5                0x1005
+#define WM8962_WRITE_SEQUENCER_6                0x1006
+#define WM8962_WRITE_SEQUENCER_7                0x1007
+#define WM8962_WRITE_SEQUENCER_8                0x1008
+#define WM8962_WRITE_SEQUENCER_9                0x1009
+#define WM8962_WRITE_SEQUENCER_10               0x100A
+#define WM8962_WRITE_SEQUENCER_11               0x100B
+#define WM8962_WRITE_SEQUENCER_12               0x100C
+#define WM8962_WRITE_SEQUENCER_13               0x100D
+#define WM8962_WRITE_SEQUENCER_14               0x100E
+#define WM8962_WRITE_SEQUENCER_15               0x100F
+#define WM8962_WRITE_SEQUENCER_16               0x1010
+#define WM8962_WRITE_SEQUENCER_17               0x1011
+#define WM8962_WRITE_SEQUENCER_18               0x1012
+#define WM8962_WRITE_SEQUENCER_19               0x1013
+#define WM8962_WRITE_SEQUENCER_20               0x1014
+#define WM8962_WRITE_SEQUENCER_21               0x1015
+#define WM8962_WRITE_SEQUENCER_22               0x1016
+#define WM8962_WRITE_SEQUENCER_23               0x1017
+#define WM8962_WRITE_SEQUENCER_24               0x1018
+#define WM8962_WRITE_SEQUENCER_25               0x1019
+#define WM8962_WRITE_SEQUENCER_26               0x101A
+#define WM8962_WRITE_SEQUENCER_27               0x101B
+#define WM8962_WRITE_SEQUENCER_28               0x101C
+#define WM8962_WRITE_SEQUENCER_29               0x101D
+#define WM8962_WRITE_SEQUENCER_30               0x101E
+#define WM8962_WRITE_SEQUENCER_31               0x101F
+#define WM8962_WRITE_SEQUENCER_32               0x1020
+#define WM8962_WRITE_SEQUENCER_33               0x1021
+#define WM8962_WRITE_SEQUENCER_34               0x1022
+#define WM8962_WRITE_SEQUENCER_35               0x1023
+#define WM8962_WRITE_SEQUENCER_36               0x1024
+#define WM8962_WRITE_SEQUENCER_37               0x1025
+#define WM8962_WRITE_SEQUENCER_38               0x1026
+#define WM8962_WRITE_SEQUENCER_39               0x1027
+#define WM8962_WRITE_SEQUENCER_40               0x1028
+#define WM8962_WRITE_SEQUENCER_41               0x1029
+#define WM8962_WRITE_SEQUENCER_42               0x102A
+#define WM8962_WRITE_SEQUENCER_43               0x102B
+#define WM8962_WRITE_SEQUENCER_44               0x102C
+#define WM8962_WRITE_SEQUENCER_45               0x102D
+#define WM8962_WRITE_SEQUENCER_46               0x102E
+#define WM8962_WRITE_SEQUENCER_47               0x102F
+#define WM8962_WRITE_SEQUENCER_48               0x1030
+#define WM8962_WRITE_SEQUENCER_49               0x1031
+#define WM8962_WRITE_SEQUENCER_50               0x1032
+#define WM8962_WRITE_SEQUENCER_51               0x1033
+#define WM8962_WRITE_SEQUENCER_52               0x1034
+#define WM8962_WRITE_SEQUENCER_53               0x1035
+#define WM8962_WRITE_SEQUENCER_54               0x1036
+#define WM8962_WRITE_SEQUENCER_55               0x1037
+#define WM8962_WRITE_SEQUENCER_56               0x1038
+#define WM8962_WRITE_SEQUENCER_57               0x1039
+#define WM8962_WRITE_SEQUENCER_58               0x103A
+#define WM8962_WRITE_SEQUENCER_59               0x103B
+#define WM8962_WRITE_SEQUENCER_60               0x103C
+#define WM8962_WRITE_SEQUENCER_61               0x103D
+#define WM8962_WRITE_SEQUENCER_62               0x103E
+#define WM8962_WRITE_SEQUENCER_63               0x103F
+#define WM8962_WRITE_SEQUENCER_64               0x1040
+#define WM8962_WRITE_SEQUENCER_65               0x1041
+#define WM8962_WRITE_SEQUENCER_66               0x1042
+#define WM8962_WRITE_SEQUENCER_67               0x1043
+#define WM8962_WRITE_SEQUENCER_68               0x1044
+#define WM8962_WRITE_SEQUENCER_69               0x1045
+#define WM8962_WRITE_SEQUENCER_70               0x1046
+#define WM8962_WRITE_SEQUENCER_71               0x1047
+#define WM8962_WRITE_SEQUENCER_72               0x1048
+#define WM8962_WRITE_SEQUENCER_73               0x1049
+#define WM8962_WRITE_SEQUENCER_74               0x104A
+#define WM8962_WRITE_SEQUENCER_75               0x104B
+#define WM8962_WRITE_SEQUENCER_76               0x104C
+#define WM8962_WRITE_SEQUENCER_77               0x104D
+#define WM8962_WRITE_SEQUENCER_78               0x104E
+#define WM8962_WRITE_SEQUENCER_79               0x104F
+#define WM8962_WRITE_SEQUENCER_80               0x1050
+#define WM8962_WRITE_SEQUENCER_81               0x1051
+#define WM8962_WRITE_SEQUENCER_82               0x1052
+#define WM8962_WRITE_SEQUENCER_83               0x1053
+#define WM8962_WRITE_SEQUENCER_84               0x1054
+#define WM8962_WRITE_SEQUENCER_85               0x1055
+#define WM8962_WRITE_SEQUENCER_86               0x1056
+#define WM8962_WRITE_SEQUENCER_87               0x1057
+#define WM8962_WRITE_SEQUENCER_88               0x1058
+#define WM8962_WRITE_SEQUENCER_89               0x1059
+#define WM8962_WRITE_SEQUENCER_90               0x105A
+#define WM8962_WRITE_SEQUENCER_91               0x105B
+#define WM8962_WRITE_SEQUENCER_92               0x105C
+#define WM8962_WRITE_SEQUENCER_93               0x105D
+#define WM8962_WRITE_SEQUENCER_94               0x105E
+#define WM8962_WRITE_SEQUENCER_95               0x105F
+#define WM8962_WRITE_SEQUENCER_96               0x1060
+#define WM8962_WRITE_SEQUENCER_97               0x1061
+#define WM8962_WRITE_SEQUENCER_98               0x1062
+#define WM8962_WRITE_SEQUENCER_99               0x1063
+#define WM8962_WRITE_SEQUENCER_100              0x1064
+#define WM8962_WRITE_SEQUENCER_101              0x1065
+#define WM8962_WRITE_SEQUENCER_102              0x1066
+#define WM8962_WRITE_SEQUENCER_103              0x1067
+#define WM8962_WRITE_SEQUENCER_104              0x1068
+#define WM8962_WRITE_SEQUENCER_105              0x1069
+#define WM8962_WRITE_SEQUENCER_106              0x106A
+#define WM8962_WRITE_SEQUENCER_107              0x106B
+#define WM8962_WRITE_SEQUENCER_108              0x106C
+#define WM8962_WRITE_SEQUENCER_109              0x106D
+#define WM8962_WRITE_SEQUENCER_110              0x106E
+#define WM8962_WRITE_SEQUENCER_111              0x106F
+#define WM8962_WRITE_SEQUENCER_112              0x1070
+#define WM8962_WRITE_SEQUENCER_113              0x1071
+#define WM8962_WRITE_SEQUENCER_114              0x1072
+#define WM8962_WRITE_SEQUENCER_115              0x1073
+#define WM8962_WRITE_SEQUENCER_116              0x1074
+#define WM8962_WRITE_SEQUENCER_117              0x1075
+#define WM8962_WRITE_SEQUENCER_118              0x1076
+#define WM8962_WRITE_SEQUENCER_119              0x1077
+#define WM8962_WRITE_SEQUENCER_120              0x1078
+#define WM8962_WRITE_SEQUENCER_121              0x1079
+#define WM8962_WRITE_SEQUENCER_122              0x107A
+#define WM8962_WRITE_SEQUENCER_123              0x107B
+#define WM8962_WRITE_SEQUENCER_124              0x107C
+#define WM8962_WRITE_SEQUENCER_125              0x107D
+#define WM8962_WRITE_SEQUENCER_126              0x107E
+#define WM8962_WRITE_SEQUENCER_127              0x107F
+#define WM8962_WRITE_SEQUENCER_128              0x1080
+#define WM8962_WRITE_SEQUENCER_129              0x1081
+#define WM8962_WRITE_SEQUENCER_130              0x1082
+#define WM8962_WRITE_SEQUENCER_131              0x1083
+#define WM8962_WRITE_SEQUENCER_132              0x1084
+#define WM8962_WRITE_SEQUENCER_133              0x1085
+#define WM8962_WRITE_SEQUENCER_134              0x1086
+#define WM8962_WRITE_SEQUENCER_135              0x1087
+#define WM8962_WRITE_SEQUENCER_136              0x1088
+#define WM8962_WRITE_SEQUENCER_137              0x1089
+#define WM8962_WRITE_SEQUENCER_138              0x108A
+#define WM8962_WRITE_SEQUENCER_139              0x108B
+#define WM8962_WRITE_SEQUENCER_140              0x108C
+#define WM8962_WRITE_SEQUENCER_141              0x108D
+#define WM8962_WRITE_SEQUENCER_142              0x108E
+#define WM8962_WRITE_SEQUENCER_143              0x108F
+#define WM8962_WRITE_SEQUENCER_144              0x1090
+#define WM8962_WRITE_SEQUENCER_145              0x1091
+#define WM8962_WRITE_SEQUENCER_146              0x1092
+#define WM8962_WRITE_SEQUENCER_147              0x1093
+#define WM8962_WRITE_SEQUENCER_148              0x1094
+#define WM8962_WRITE_SEQUENCER_149              0x1095
+#define WM8962_WRITE_SEQUENCER_150              0x1096
+#define WM8962_WRITE_SEQUENCER_151              0x1097
+#define WM8962_WRITE_SEQUENCER_152              0x1098
+#define WM8962_WRITE_SEQUENCER_153              0x1099
+#define WM8962_WRITE_SEQUENCER_154              0x109A
+#define WM8962_WRITE_SEQUENCER_155              0x109B
+#define WM8962_WRITE_SEQUENCER_156              0x109C
+#define WM8962_WRITE_SEQUENCER_157              0x109D
+#define WM8962_WRITE_SEQUENCER_158              0x109E
+#define WM8962_WRITE_SEQUENCER_159              0x109F
+#define WM8962_WRITE_SEQUENCER_160              0x10A0
+#define WM8962_WRITE_SEQUENCER_161              0x10A1
+#define WM8962_WRITE_SEQUENCER_162              0x10A2
+#define WM8962_WRITE_SEQUENCER_163              0x10A3
+#define WM8962_WRITE_SEQUENCER_164              0x10A4
+#define WM8962_WRITE_SEQUENCER_165              0x10A5
+#define WM8962_WRITE_SEQUENCER_166              0x10A6
+#define WM8962_WRITE_SEQUENCER_167              0x10A7
+#define WM8962_WRITE_SEQUENCER_168              0x10A8
+#define WM8962_WRITE_SEQUENCER_169              0x10A9
+#define WM8962_WRITE_SEQUENCER_170              0x10AA
+#define WM8962_WRITE_SEQUENCER_171              0x10AB
+#define WM8962_WRITE_SEQUENCER_172              0x10AC
+#define WM8962_WRITE_SEQUENCER_173              0x10AD
+#define WM8962_WRITE_SEQUENCER_174              0x10AE
+#define WM8962_WRITE_SEQUENCER_175              0x10AF
+#define WM8962_WRITE_SEQUENCER_176              0x10B0
+#define WM8962_WRITE_SEQUENCER_177              0x10B1
+#define WM8962_WRITE_SEQUENCER_178              0x10B2
+#define WM8962_WRITE_SEQUENCER_179              0x10B3
+#define WM8962_WRITE_SEQUENCER_180              0x10B4
+#define WM8962_WRITE_SEQUENCER_181              0x10B5
+#define WM8962_WRITE_SEQUENCER_182              0x10B6
+#define WM8962_WRITE_SEQUENCER_183              0x10B7
+#define WM8962_WRITE_SEQUENCER_184              0x10B8
+#define WM8962_WRITE_SEQUENCER_185              0x10B9
+#define WM8962_WRITE_SEQUENCER_186              0x10BA
+#define WM8962_WRITE_SEQUENCER_187              0x10BB
+#define WM8962_WRITE_SEQUENCER_188              0x10BC
+#define WM8962_WRITE_SEQUENCER_189              0x10BD
+#define WM8962_WRITE_SEQUENCER_190              0x10BE
+#define WM8962_WRITE_SEQUENCER_191              0x10BF
+#define WM8962_WRITE_SEQUENCER_192              0x10C0
+#define WM8962_WRITE_SEQUENCER_193              0x10C1
+#define WM8962_WRITE_SEQUENCER_194              0x10C2
+#define WM8962_WRITE_SEQUENCER_195              0x10C3
+#define WM8962_WRITE_SEQUENCER_196              0x10C4
+#define WM8962_WRITE_SEQUENCER_197              0x10C5
+#define WM8962_WRITE_SEQUENCER_198              0x10C6
+#define WM8962_WRITE_SEQUENCER_199              0x10C7
+#define WM8962_WRITE_SEQUENCER_200              0x10C8
+#define WM8962_WRITE_SEQUENCER_201              0x10C9
+#define WM8962_WRITE_SEQUENCER_202              0x10CA
+#define WM8962_WRITE_SEQUENCER_203              0x10CB
+#define WM8962_WRITE_SEQUENCER_204              0x10CC
+#define WM8962_WRITE_SEQUENCER_205              0x10CD
+#define WM8962_WRITE_SEQUENCER_206              0x10CE
+#define WM8962_WRITE_SEQUENCER_207              0x10CF
+#define WM8962_WRITE_SEQUENCER_208              0x10D0
+#define WM8962_WRITE_SEQUENCER_209              0x10D1
+#define WM8962_WRITE_SEQUENCER_210              0x10D2
+#define WM8962_WRITE_SEQUENCER_211              0x10D3
+#define WM8962_WRITE_SEQUENCER_212              0x10D4
+#define WM8962_WRITE_SEQUENCER_213              0x10D5
+#define WM8962_WRITE_SEQUENCER_214              0x10D6
+#define WM8962_WRITE_SEQUENCER_215              0x10D7
+#define WM8962_WRITE_SEQUENCER_216              0x10D8
+#define WM8962_WRITE_SEQUENCER_217              0x10D9
+#define WM8962_WRITE_SEQUENCER_218              0x10DA
+#define WM8962_WRITE_SEQUENCER_219              0x10DB
+#define WM8962_WRITE_SEQUENCER_220              0x10DC
+#define WM8962_WRITE_SEQUENCER_221              0x10DD
+#define WM8962_WRITE_SEQUENCER_222              0x10DE
+#define WM8962_WRITE_SEQUENCER_223              0x10DF
+#define WM8962_WRITE_SEQUENCER_224              0x10E0
+#define WM8962_WRITE_SEQUENCER_225              0x10E1
+#define WM8962_WRITE_SEQUENCER_226              0x10E2
+#define WM8962_WRITE_SEQUENCER_227              0x10E3
+#define WM8962_WRITE_SEQUENCER_228              0x10E4
+#define WM8962_WRITE_SEQUENCER_229              0x10E5
+#define WM8962_WRITE_SEQUENCER_230              0x10E6
+#define WM8962_WRITE_SEQUENCER_231              0x10E7
+#define WM8962_WRITE_SEQUENCER_232              0x10E8
+#define WM8962_WRITE_SEQUENCER_233              0x10E9
+#define WM8962_WRITE_SEQUENCER_234              0x10EA
+#define WM8962_WRITE_SEQUENCER_235              0x10EB
+#define WM8962_WRITE_SEQUENCER_236              0x10EC
+#define WM8962_WRITE_SEQUENCER_237              0x10ED
+#define WM8962_WRITE_SEQUENCER_238              0x10EE
+#define WM8962_WRITE_SEQUENCER_239              0x10EF
+#define WM8962_WRITE_SEQUENCER_240              0x10F0
+#define WM8962_WRITE_SEQUENCER_241              0x10F1
+#define WM8962_WRITE_SEQUENCER_242              0x10F2
+#define WM8962_WRITE_SEQUENCER_243              0x10F3
+#define WM8962_WRITE_SEQUENCER_244              0x10F4
+#define WM8962_WRITE_SEQUENCER_245              0x10F5
+#define WM8962_WRITE_SEQUENCER_246              0x10F6
+#define WM8962_WRITE_SEQUENCER_247              0x10F7
+#define WM8962_WRITE_SEQUENCER_248              0x10F8
+#define WM8962_WRITE_SEQUENCER_249              0x10F9
+#define WM8962_WRITE_SEQUENCER_250              0x10FA
+#define WM8962_WRITE_SEQUENCER_251              0x10FB
+#define WM8962_WRITE_SEQUENCER_252              0x10FC
+#define WM8962_WRITE_SEQUENCER_253              0x10FD
+#define WM8962_WRITE_SEQUENCER_254              0x10FE
+#define WM8962_WRITE_SEQUENCER_255              0x10FF
+#define WM8962_WRITE_SEQUENCER_256              0x1100
+#define WM8962_WRITE_SEQUENCER_257              0x1101
+#define WM8962_WRITE_SEQUENCER_258              0x1102
+#define WM8962_WRITE_SEQUENCER_259              0x1103
+#define WM8962_WRITE_SEQUENCER_260              0x1104
+#define WM8962_WRITE_SEQUENCER_261              0x1105
+#define WM8962_WRITE_SEQUENCER_262              0x1106
+#define WM8962_WRITE_SEQUENCER_263              0x1107
+#define WM8962_WRITE_SEQUENCER_264              0x1108
+#define WM8962_WRITE_SEQUENCER_265              0x1109
+#define WM8962_WRITE_SEQUENCER_266              0x110A
+#define WM8962_WRITE_SEQUENCER_267              0x110B
+#define WM8962_WRITE_SEQUENCER_268              0x110C
+#define WM8962_WRITE_SEQUENCER_269              0x110D
+#define WM8962_WRITE_SEQUENCER_270              0x110E
+#define WM8962_WRITE_SEQUENCER_271              0x110F
+#define WM8962_WRITE_SEQUENCER_272              0x1110
+#define WM8962_WRITE_SEQUENCER_273              0x1111
+#define WM8962_WRITE_SEQUENCER_274              0x1112
+#define WM8962_WRITE_SEQUENCER_275              0x1113
+#define WM8962_WRITE_SEQUENCER_276              0x1114
+#define WM8962_WRITE_SEQUENCER_277              0x1115
+#define WM8962_WRITE_SEQUENCER_278              0x1116
+#define WM8962_WRITE_SEQUENCER_279              0x1117
+#define WM8962_WRITE_SEQUENCER_280              0x1118
+#define WM8962_WRITE_SEQUENCER_281              0x1119
+#define WM8962_WRITE_SEQUENCER_282              0x111A
+#define WM8962_WRITE_SEQUENCER_283              0x111B
+#define WM8962_WRITE_SEQUENCER_284              0x111C
+#define WM8962_WRITE_SEQUENCER_285              0x111D
+#define WM8962_WRITE_SEQUENCER_286              0x111E
+#define WM8962_WRITE_SEQUENCER_287              0x111F
+#define WM8962_WRITE_SEQUENCER_288              0x1120
+#define WM8962_WRITE_SEQUENCER_289              0x1121
+#define WM8962_WRITE_SEQUENCER_290              0x1122
+#define WM8962_WRITE_SEQUENCER_291              0x1123
+#define WM8962_WRITE_SEQUENCER_292              0x1124
+#define WM8962_WRITE_SEQUENCER_293              0x1125
+#define WM8962_WRITE_SEQUENCER_294              0x1126
+#define WM8962_WRITE_SEQUENCER_295              0x1127
+#define WM8962_WRITE_SEQUENCER_296              0x1128
+#define WM8962_WRITE_SEQUENCER_297              0x1129
+#define WM8962_WRITE_SEQUENCER_298              0x112A
+#define WM8962_WRITE_SEQUENCER_299              0x112B
+#define WM8962_WRITE_SEQUENCER_300              0x112C
+#define WM8962_WRITE_SEQUENCER_301              0x112D
+#define WM8962_WRITE_SEQUENCER_302              0x112E
+#define WM8962_WRITE_SEQUENCER_303              0x112F
+#define WM8962_WRITE_SEQUENCER_304              0x1130
+#define WM8962_WRITE_SEQUENCER_305              0x1131
+#define WM8962_WRITE_SEQUENCER_306              0x1132
+#define WM8962_WRITE_SEQUENCER_307              0x1133
+#define WM8962_WRITE_SEQUENCER_308              0x1134
+#define WM8962_WRITE_SEQUENCER_309              0x1135
+#define WM8962_WRITE_SEQUENCER_310              0x1136
+#define WM8962_WRITE_SEQUENCER_311              0x1137
+#define WM8962_WRITE_SEQUENCER_312              0x1138
+#define WM8962_WRITE_SEQUENCER_313              0x1139
+#define WM8962_WRITE_SEQUENCER_314              0x113A
+#define WM8962_WRITE_SEQUENCER_315              0x113B
+#define WM8962_WRITE_SEQUENCER_316              0x113C
+#define WM8962_WRITE_SEQUENCER_317              0x113D
+#define WM8962_WRITE_SEQUENCER_318              0x113E
+#define WM8962_WRITE_SEQUENCER_319              0x113F
+#define WM8962_WRITE_SEQUENCER_320              0x1140
+#define WM8962_WRITE_SEQUENCER_321              0x1141
+#define WM8962_WRITE_SEQUENCER_322              0x1142
+#define WM8962_WRITE_SEQUENCER_323              0x1143
+#define WM8962_WRITE_SEQUENCER_324              0x1144
+#define WM8962_WRITE_SEQUENCER_325              0x1145
+#define WM8962_WRITE_SEQUENCER_326              0x1146
+#define WM8962_WRITE_SEQUENCER_327              0x1147
+#define WM8962_WRITE_SEQUENCER_328              0x1148
+#define WM8962_WRITE_SEQUENCER_329              0x1149
+#define WM8962_WRITE_SEQUENCER_330              0x114A
+#define WM8962_WRITE_SEQUENCER_331              0x114B
+#define WM8962_WRITE_SEQUENCER_332              0x114C
+#define WM8962_WRITE_SEQUENCER_333              0x114D
+#define WM8962_WRITE_SEQUENCER_334              0x114E
+#define WM8962_WRITE_SEQUENCER_335              0x114F
+#define WM8962_WRITE_SEQUENCER_336              0x1150
+#define WM8962_WRITE_SEQUENCER_337              0x1151
+#define WM8962_WRITE_SEQUENCER_338              0x1152
+#define WM8962_WRITE_SEQUENCER_339              0x1153
+#define WM8962_WRITE_SEQUENCER_340              0x1154
+#define WM8962_WRITE_SEQUENCER_341              0x1155
+#define WM8962_WRITE_SEQUENCER_342              0x1156
+#define WM8962_WRITE_SEQUENCER_343              0x1157
+#define WM8962_WRITE_SEQUENCER_344              0x1158
+#define WM8962_WRITE_SEQUENCER_345              0x1159
+#define WM8962_WRITE_SEQUENCER_346              0x115A
+#define WM8962_WRITE_SEQUENCER_347              0x115B
+#define WM8962_WRITE_SEQUENCER_348              0x115C
+#define WM8962_WRITE_SEQUENCER_349              0x115D
+#define WM8962_WRITE_SEQUENCER_350              0x115E
+#define WM8962_WRITE_SEQUENCER_351              0x115F
+#define WM8962_WRITE_SEQUENCER_352              0x1160
+#define WM8962_WRITE_SEQUENCER_353              0x1161
+#define WM8962_WRITE_SEQUENCER_354              0x1162
+#define WM8962_WRITE_SEQUENCER_355              0x1163
+#define WM8962_WRITE_SEQUENCER_356              0x1164
+#define WM8962_WRITE_SEQUENCER_357              0x1165
+#define WM8962_WRITE_SEQUENCER_358              0x1166
+#define WM8962_WRITE_SEQUENCER_359              0x1167
+#define WM8962_WRITE_SEQUENCER_360              0x1168
+#define WM8962_WRITE_SEQUENCER_361              0x1169
+#define WM8962_WRITE_SEQUENCER_362              0x116A
+#define WM8962_WRITE_SEQUENCER_363              0x116B
+#define WM8962_WRITE_SEQUENCER_364              0x116C
+#define WM8962_WRITE_SEQUENCER_365              0x116D
+#define WM8962_WRITE_SEQUENCER_366              0x116E
+#define WM8962_WRITE_SEQUENCER_367              0x116F
+#define WM8962_WRITE_SEQUENCER_368              0x1170
+#define WM8962_WRITE_SEQUENCER_369              0x1171
+#define WM8962_WRITE_SEQUENCER_370              0x1172
+#define WM8962_WRITE_SEQUENCER_371              0x1173
+#define WM8962_WRITE_SEQUENCER_372              0x1174
+#define WM8962_WRITE_SEQUENCER_373              0x1175
+#define WM8962_WRITE_SEQUENCER_374              0x1176
+#define WM8962_WRITE_SEQUENCER_375              0x1177
+#define WM8962_WRITE_SEQUENCER_376              0x1178
+#define WM8962_WRITE_SEQUENCER_377              0x1179
+#define WM8962_WRITE_SEQUENCER_378              0x117A
+#define WM8962_WRITE_SEQUENCER_379              0x117B
+#define WM8962_WRITE_SEQUENCER_380              0x117C
+#define WM8962_WRITE_SEQUENCER_381              0x117D
+#define WM8962_WRITE_SEQUENCER_382              0x117E
+#define WM8962_WRITE_SEQUENCER_383              0x117F
+#define WM8962_WRITE_SEQUENCER_384              0x1180
+#define WM8962_WRITE_SEQUENCER_385              0x1181
+#define WM8962_WRITE_SEQUENCER_386              0x1182
+#define WM8962_WRITE_SEQUENCER_387              0x1183
+#define WM8962_WRITE_SEQUENCER_388              0x1184
+#define WM8962_WRITE_SEQUENCER_389              0x1185
+#define WM8962_WRITE_SEQUENCER_390              0x1186
+#define WM8962_WRITE_SEQUENCER_391              0x1187
+#define WM8962_WRITE_SEQUENCER_392              0x1188
+#define WM8962_WRITE_SEQUENCER_393              0x1189
+#define WM8962_WRITE_SEQUENCER_394              0x118A
+#define WM8962_WRITE_SEQUENCER_395              0x118B
+#define WM8962_WRITE_SEQUENCER_396              0x118C
+#define WM8962_WRITE_SEQUENCER_397              0x118D
+#define WM8962_WRITE_SEQUENCER_398              0x118E
+#define WM8962_WRITE_SEQUENCER_399              0x118F
+#define WM8962_WRITE_SEQUENCER_400              0x1190
+#define WM8962_WRITE_SEQUENCER_401              0x1191
+#define WM8962_WRITE_SEQUENCER_402              0x1192
+#define WM8962_WRITE_SEQUENCER_403              0x1193
+#define WM8962_WRITE_SEQUENCER_404              0x1194
+#define WM8962_WRITE_SEQUENCER_405              0x1195
+#define WM8962_WRITE_SEQUENCER_406              0x1196
+#define WM8962_WRITE_SEQUENCER_407              0x1197
+#define WM8962_WRITE_SEQUENCER_408              0x1198
+#define WM8962_WRITE_SEQUENCER_409              0x1199
+#define WM8962_WRITE_SEQUENCER_410              0x119A
+#define WM8962_WRITE_SEQUENCER_411              0x119B
+#define WM8962_WRITE_SEQUENCER_412              0x119C
+#define WM8962_WRITE_SEQUENCER_413              0x119D
+#define WM8962_WRITE_SEQUENCER_414              0x119E
+#define WM8962_WRITE_SEQUENCER_415              0x119F
+#define WM8962_WRITE_SEQUENCER_416              0x11A0
+#define WM8962_WRITE_SEQUENCER_417              0x11A1
+#define WM8962_WRITE_SEQUENCER_418              0x11A2
+#define WM8962_WRITE_SEQUENCER_419              0x11A3
+#define WM8962_WRITE_SEQUENCER_420              0x11A4
+#define WM8962_WRITE_SEQUENCER_421              0x11A5
+#define WM8962_WRITE_SEQUENCER_422              0x11A6
+#define WM8962_WRITE_SEQUENCER_423              0x11A7
+#define WM8962_WRITE_SEQUENCER_424              0x11A8
+#define WM8962_WRITE_SEQUENCER_425              0x11A9
+#define WM8962_WRITE_SEQUENCER_426              0x11AA
+#define WM8962_WRITE_SEQUENCER_427              0x11AB
+#define WM8962_WRITE_SEQUENCER_428              0x11AC
+#define WM8962_WRITE_SEQUENCER_429              0x11AD
+#define WM8962_WRITE_SEQUENCER_430              0x11AE
+#define WM8962_WRITE_SEQUENCER_431              0x11AF
+#define WM8962_WRITE_SEQUENCER_432              0x11B0
+#define WM8962_WRITE_SEQUENCER_433              0x11B1
+#define WM8962_WRITE_SEQUENCER_434              0x11B2
+#define WM8962_WRITE_SEQUENCER_435              0x11B3
+#define WM8962_WRITE_SEQUENCER_436              0x11B4
+#define WM8962_WRITE_SEQUENCER_437              0x11B5
+#define WM8962_WRITE_SEQUENCER_438              0x11B6
+#define WM8962_WRITE_SEQUENCER_439              0x11B7
+#define WM8962_WRITE_SEQUENCER_440              0x11B8
+#define WM8962_WRITE_SEQUENCER_441              0x11B9
+#define WM8962_WRITE_SEQUENCER_442              0x11BA
+#define WM8962_WRITE_SEQUENCER_443              0x11BB
+#define WM8962_WRITE_SEQUENCER_444              0x11BC
+#define WM8962_WRITE_SEQUENCER_445              0x11BD
+#define WM8962_WRITE_SEQUENCER_446              0x11BE
+#define WM8962_WRITE_SEQUENCER_447              0x11BF
+#define WM8962_WRITE_SEQUENCER_448              0x11C0
+#define WM8962_WRITE_SEQUENCER_449              0x11C1
+#define WM8962_WRITE_SEQUENCER_450              0x11C2
+#define WM8962_WRITE_SEQUENCER_451              0x11C3
+#define WM8962_WRITE_SEQUENCER_452              0x11C4
+#define WM8962_WRITE_SEQUENCER_453              0x11C5
+#define WM8962_WRITE_SEQUENCER_454              0x11C6
+#define WM8962_WRITE_SEQUENCER_455              0x11C7
+#define WM8962_WRITE_SEQUENCER_456              0x11C8
+#define WM8962_WRITE_SEQUENCER_457              0x11C9
+#define WM8962_WRITE_SEQUENCER_458              0x11CA
+#define WM8962_WRITE_SEQUENCER_459              0x11CB
+#define WM8962_WRITE_SEQUENCER_460              0x11CC
+#define WM8962_WRITE_SEQUENCER_461              0x11CD
+#define WM8962_WRITE_SEQUENCER_462              0x11CE
+#define WM8962_WRITE_SEQUENCER_463              0x11CF
+#define WM8962_WRITE_SEQUENCER_464              0x11D0
+#define WM8962_WRITE_SEQUENCER_465              0x11D1
+#define WM8962_WRITE_SEQUENCER_466              0x11D2
+#define WM8962_WRITE_SEQUENCER_467              0x11D3
+#define WM8962_WRITE_SEQUENCER_468              0x11D4
+#define WM8962_WRITE_SEQUENCER_469              0x11D5
+#define WM8962_WRITE_SEQUENCER_470              0x11D6
+#define WM8962_WRITE_SEQUENCER_471              0x11D7
+#define WM8962_WRITE_SEQUENCER_472              0x11D8
+#define WM8962_WRITE_SEQUENCER_473              0x11D9
+#define WM8962_WRITE_SEQUENCER_474              0x11DA
+#define WM8962_WRITE_SEQUENCER_475              0x11DB
+#define WM8962_WRITE_SEQUENCER_476              0x11DC
+#define WM8962_WRITE_SEQUENCER_477              0x11DD
+#define WM8962_WRITE_SEQUENCER_478              0x11DE
+#define WM8962_WRITE_SEQUENCER_479              0x11DF
+#define WM8962_WRITE_SEQUENCER_480              0x11E0
+#define WM8962_WRITE_SEQUENCER_481              0x11E1
+#define WM8962_WRITE_SEQUENCER_482              0x11E2
+#define WM8962_WRITE_SEQUENCER_483              0x11E3
+#define WM8962_WRITE_SEQUENCER_484              0x11E4
+#define WM8962_WRITE_SEQUENCER_485              0x11E5
+#define WM8962_WRITE_SEQUENCER_486              0x11E6
+#define WM8962_WRITE_SEQUENCER_487              0x11E7
+#define WM8962_WRITE_SEQUENCER_488              0x11E8
+#define WM8962_WRITE_SEQUENCER_489              0x11E9
+#define WM8962_WRITE_SEQUENCER_490              0x11EA
+#define WM8962_WRITE_SEQUENCER_491              0x11EB
+#define WM8962_WRITE_SEQUENCER_492              0x11EC
+#define WM8962_WRITE_SEQUENCER_493              0x11ED
+#define WM8962_WRITE_SEQUENCER_494              0x11EE
+#define WM8962_WRITE_SEQUENCER_495              0x11EF
+#define WM8962_WRITE_SEQUENCER_496              0x11F0
+#define WM8962_WRITE_SEQUENCER_497              0x11F1
+#define WM8962_WRITE_SEQUENCER_498              0x11F2
+#define WM8962_WRITE_SEQUENCER_499              0x11F3
+#define WM8962_WRITE_SEQUENCER_500              0x11F4
+#define WM8962_WRITE_SEQUENCER_501              0x11F5
+#define WM8962_WRITE_SEQUENCER_502              0x11F6
+#define WM8962_WRITE_SEQUENCER_503              0x11F7
+#define WM8962_WRITE_SEQUENCER_504              0x11F8
+#define WM8962_WRITE_SEQUENCER_505              0x11F9
+#define WM8962_WRITE_SEQUENCER_506              0x11FA
+#define WM8962_WRITE_SEQUENCER_507              0x11FB
+#define WM8962_WRITE_SEQUENCER_508              0x11FC
+#define WM8962_WRITE_SEQUENCER_509              0x11FD
+#define WM8962_WRITE_SEQUENCER_510              0x11FE
+#define WM8962_WRITE_SEQUENCER_511              0x11FF
+#define WM8962_DSP2_INSTRUCTION_RAM_0           0x2000
+#define WM8962_DSP2_ADDRESS_RAM_2               0x2400
+#define WM8962_DSP2_ADDRESS_RAM_1               0x2401
+#define WM8962_DSP2_ADDRESS_RAM_0               0x2402
+#define WM8962_DSP2_DATA1_RAM_1                 0x3000
+#define WM8962_DSP2_DATA1_RAM_0                 0x3001
+#define WM8962_DSP2_DATA2_RAM_1                 0x3400
+#define WM8962_DSP2_DATA2_RAM_0                 0x3401
+#define WM8962_DSP2_DATA3_RAM_1                 0x3800
+#define WM8962_DSP2_DATA3_RAM_0                 0x3801
+#define WM8962_DSP2_COEFF_RAM_0                 0x3C00
+#define WM8962_RETUNEADC_SHARED_COEFF_1         0x4000
+#define WM8962_RETUNEADC_SHARED_COEFF_0         0x4001
+#define WM8962_RETUNEDAC_SHARED_COEFF_1         0x4002
+#define WM8962_RETUNEDAC_SHARED_COEFF_0         0x4003
+#define WM8962_SOUNDSTAGE_ENABLES_1             0x4004
+#define WM8962_SOUNDSTAGE_ENABLES_0             0x4005
+#define WM8962_HDBASS_AI_1                      0x4200
+#define WM8962_HDBASS_AI_0                      0x4201
+#define WM8962_HDBASS_AR_1                      0x4202
+#define WM8962_HDBASS_AR_0                      0x4203
+#define WM8962_HDBASS_B_1                       0x4204
+#define WM8962_HDBASS_B_0                       0x4205
+#define WM8962_HDBASS_K_1                       0x4206
+#define WM8962_HDBASS_K_0                       0x4207
+#define WM8962_HDBASS_N1_1                      0x4208
+#define WM8962_HDBASS_N1_0                      0x4209
+#define WM8962_HDBASS_N2_1                      0x420A
+#define WM8962_HDBASS_N2_0                      0x420B
+#define WM8962_HDBASS_N3_1                      0x420C
+#define WM8962_HDBASS_N3_0                      0x420D
+#define WM8962_HDBASS_N4_1                      0x420E
+#define WM8962_HDBASS_N4_0                      0x420F
+#define WM8962_HDBASS_N5_1                      0x4210
+#define WM8962_HDBASS_N5_0                      0x4211
+#define WM8962_HDBASS_X1_1                      0x4212
+#define WM8962_HDBASS_X1_0                      0x4213
+#define WM8962_HDBASS_X2_1                      0x4214
+#define WM8962_HDBASS_X2_0                      0x4215
+#define WM8962_HDBASS_X3_1                      0x4216
+#define WM8962_HDBASS_X3_0                      0x4217
+#define WM8962_HDBASS_ATK_1                     0x4218
+#define WM8962_HDBASS_ATK_0                     0x4219
+#define WM8962_HDBASS_DCY_1                     0x421A
+#define WM8962_HDBASS_DCY_0                     0x421B
+#define WM8962_HDBASS_PG_1                      0x421C
+#define WM8962_HDBASS_PG_0                      0x421D
+#define WM8962_HPF_C_1                          0x4400
+#define WM8962_HPF_C_0                          0x4401
+#define WM8962_ADCL_RETUNE_C1_1                 0x4600
+#define WM8962_ADCL_RETUNE_C1_0                 0x4601
+#define WM8962_ADCL_RETUNE_C2_1                 0x4602
+#define WM8962_ADCL_RETUNE_C2_0                 0x4603
+#define WM8962_ADCL_RETUNE_C3_1                 0x4604
+#define WM8962_ADCL_RETUNE_C3_0                 0x4605
+#define WM8962_ADCL_RETUNE_C4_1                 0x4606
+#define WM8962_ADCL_RETUNE_C4_0                 0x4607
+#define WM8962_ADCL_RETUNE_C5_1                 0x4608
+#define WM8962_ADCL_RETUNE_C5_0                 0x4609
+#define WM8962_ADCL_RETUNE_C6_1                 0x460A
+#define WM8962_ADCL_RETUNE_C6_0                 0x460B
+#define WM8962_ADCL_RETUNE_C7_1                 0x460C
+#define WM8962_ADCL_RETUNE_C7_0                 0x460D
+#define WM8962_ADCL_RETUNE_C8_1                 0x460E
+#define WM8962_ADCL_RETUNE_C8_0                 0x460F
+#define WM8962_ADCL_RETUNE_C9_1                 0x4610
+#define WM8962_ADCL_RETUNE_C9_0                 0x4611
+#define WM8962_ADCL_RETUNE_C10_1                0x4612
+#define WM8962_ADCL_RETUNE_C10_0                0x4613
+#define WM8962_ADCL_RETUNE_C11_1                0x4614
+#define WM8962_ADCL_RETUNE_C11_0                0x4615
+#define WM8962_ADCL_RETUNE_C12_1                0x4616
+#define WM8962_ADCL_RETUNE_C12_0                0x4617
+#define WM8962_ADCL_RETUNE_C13_1                0x4618
+#define WM8962_ADCL_RETUNE_C13_0                0x4619
+#define WM8962_ADCL_RETUNE_C14_1                0x461A
+#define WM8962_ADCL_RETUNE_C14_0                0x461B
+#define WM8962_ADCL_RETUNE_C15_1                0x461C
+#define WM8962_ADCL_RETUNE_C15_0                0x461D
+#define WM8962_ADCL_RETUNE_C16_1                0x461E
+#define WM8962_ADCL_RETUNE_C16_0                0x461F
+#define WM8962_ADCL_RETUNE_C17_1                0x4620
+#define WM8962_ADCL_RETUNE_C17_0                0x4621
+#define WM8962_ADCL_RETUNE_C18_1                0x4622
+#define WM8962_ADCL_RETUNE_C18_0                0x4623
+#define WM8962_ADCL_RETUNE_C19_1                0x4624
+#define WM8962_ADCL_RETUNE_C19_0                0x4625
+#define WM8962_ADCL_RETUNE_C20_1                0x4626
+#define WM8962_ADCL_RETUNE_C20_0                0x4627
+#define WM8962_ADCL_RETUNE_C21_1                0x4628
+#define WM8962_ADCL_RETUNE_C21_0                0x4629
+#define WM8962_ADCL_RETUNE_C22_1                0x462A
+#define WM8962_ADCL_RETUNE_C22_0                0x462B
+#define WM8962_ADCL_RETUNE_C23_1                0x462C
+#define WM8962_ADCL_RETUNE_C23_0                0x462D
+#define WM8962_ADCL_RETUNE_C24_1                0x462E
+#define WM8962_ADCL_RETUNE_C24_0                0x462F
+#define WM8962_ADCL_RETUNE_C25_1                0x4630
+#define WM8962_ADCL_RETUNE_C25_0                0x4631
+#define WM8962_ADCL_RETUNE_C26_1                0x4632
+#define WM8962_ADCL_RETUNE_C26_0                0x4633
+#define WM8962_ADCL_RETUNE_C27_1                0x4634
+#define WM8962_ADCL_RETUNE_C27_0                0x4635
+#define WM8962_ADCL_RETUNE_C28_1                0x4636
+#define WM8962_ADCL_RETUNE_C28_0                0x4637
+#define WM8962_ADCL_RETUNE_C29_1                0x4638
+#define WM8962_ADCL_RETUNE_C29_0                0x4639
+#define WM8962_ADCL_RETUNE_C30_1                0x463A
+#define WM8962_ADCL_RETUNE_C30_0                0x463B
+#define WM8962_ADCL_RETUNE_C31_1                0x463C
+#define WM8962_ADCL_RETUNE_C31_0                0x463D
+#define WM8962_ADCL_RETUNE_C32_1                0x463E
+#define WM8962_ADCL_RETUNE_C32_0                0x463F
+#define WM8962_RETUNEADC_PG2_1                  0x4800
+#define WM8962_RETUNEADC_PG2_0                  0x4801
+#define WM8962_RETUNEADC_PG_1                   0x4802
+#define WM8962_RETUNEADC_PG_0                   0x4803
+#define WM8962_ADCR_RETUNE_C1_1                 0x4A00
+#define WM8962_ADCR_RETUNE_C1_0                 0x4A01
+#define WM8962_ADCR_RETUNE_C2_1                 0x4A02
+#define WM8962_ADCR_RETUNE_C2_0                 0x4A03
+#define WM8962_ADCR_RETUNE_C3_1                 0x4A04
+#define WM8962_ADCR_RETUNE_C3_0                 0x4A05
+#define WM8962_ADCR_RETUNE_C4_1                 0x4A06
+#define WM8962_ADCR_RETUNE_C4_0                 0x4A07
+#define WM8962_ADCR_RETUNE_C5_1                 0x4A08
+#define WM8962_ADCR_RETUNE_C5_0                 0x4A09
+#define WM8962_ADCR_RETUNE_C6_1                 0x4A0A
+#define WM8962_ADCR_RETUNE_C6_0                 0x4A0B
+#define WM8962_ADCR_RETUNE_C7_1                 0x4A0C
+#define WM8962_ADCR_RETUNE_C7_0                 0x4A0D
+#define WM8962_ADCR_RETUNE_C8_1                 0x4A0E
+#define WM8962_ADCR_RETUNE_C8_0                 0x4A0F
+#define WM8962_ADCR_RETUNE_C9_1                 0x4A10
+#define WM8962_ADCR_RETUNE_C9_0                 0x4A11
+#define WM8962_ADCR_RETUNE_C10_1                0x4A12
+#define WM8962_ADCR_RETUNE_C10_0                0x4A13
+#define WM8962_ADCR_RETUNE_C11_1                0x4A14
+#define WM8962_ADCR_RETUNE_C11_0                0x4A15
+#define WM8962_ADCR_RETUNE_C12_1                0x4A16
+#define WM8962_ADCR_RETUNE_C12_0                0x4A17
+#define WM8962_ADCR_RETUNE_C13_1                0x4A18
+#define WM8962_ADCR_RETUNE_C13_0                0x4A19
+#define WM8962_ADCR_RETUNE_C14_1                0x4A1A
+#define WM8962_ADCR_RETUNE_C14_0                0x4A1B
+#define WM8962_ADCR_RETUNE_C15_1                0x4A1C
+#define WM8962_ADCR_RETUNE_C15_0                0x4A1D
+#define WM8962_ADCR_RETUNE_C16_1                0x4A1E
+#define WM8962_ADCR_RETUNE_C16_0                0x4A1F
+#define WM8962_ADCR_RETUNE_C17_1                0x4A20
+#define WM8962_ADCR_RETUNE_C17_0                0x4A21
+#define WM8962_ADCR_RETUNE_C18_1                0x4A22
+#define WM8962_ADCR_RETUNE_C18_0                0x4A23
+#define WM8962_ADCR_RETUNE_C19_1                0x4A24
+#define WM8962_ADCR_RETUNE_C19_0                0x4A25
+#define WM8962_ADCR_RETUNE_C20_1                0x4A26
+#define WM8962_ADCR_RETUNE_C20_0                0x4A27
+#define WM8962_ADCR_RETUNE_C21_1                0x4A28
+#define WM8962_ADCR_RETUNE_C21_0                0x4A29
+#define WM8962_ADCR_RETUNE_C22_1                0x4A2A
+#define WM8962_ADCR_RETUNE_C22_0                0x4A2B
+#define WM8962_ADCR_RETUNE_C23_1                0x4A2C
+#define WM8962_ADCR_RETUNE_C23_0                0x4A2D
+#define WM8962_ADCR_RETUNE_C24_1                0x4A2E
+#define WM8962_ADCR_RETUNE_C24_0                0x4A2F
+#define WM8962_ADCR_RETUNE_C25_1                0x4A30
+#define WM8962_ADCR_RETUNE_C25_0                0x4A31
+#define WM8962_ADCR_RETUNE_C26_1                0x4A32
+#define WM8962_ADCR_RETUNE_C26_0                0x4A33
+#define WM8962_ADCR_RETUNE_C27_1                0x4A34
+#define WM8962_ADCR_RETUNE_C27_0                0x4A35
+#define WM8962_ADCR_RETUNE_C28_1                0x4A36
+#define WM8962_ADCR_RETUNE_C28_0                0x4A37
+#define WM8962_ADCR_RETUNE_C29_1                0x4A38
+#define WM8962_ADCR_RETUNE_C29_0                0x4A39
+#define WM8962_ADCR_RETUNE_C30_1                0x4A3A
+#define WM8962_ADCR_RETUNE_C30_0                0x4A3B
+#define WM8962_ADCR_RETUNE_C31_1                0x4A3C
+#define WM8962_ADCR_RETUNE_C31_0                0x4A3D
+#define WM8962_ADCR_RETUNE_C32_1                0x4A3E
+#define WM8962_ADCR_RETUNE_C32_0                0x4A3F
+#define WM8962_DACL_RETUNE_C1_1                 0x4C00
+#define WM8962_DACL_RETUNE_C1_0                 0x4C01
+#define WM8962_DACL_RETUNE_C2_1                 0x4C02
+#define WM8962_DACL_RETUNE_C2_0                 0x4C03
+#define WM8962_DACL_RETUNE_C3_1                 0x4C04
+#define WM8962_DACL_RETUNE_C3_0                 0x4C05
+#define WM8962_DACL_RETUNE_C4_1                 0x4C06
+#define WM8962_DACL_RETUNE_C4_0                 0x4C07
+#define WM8962_DACL_RETUNE_C5_1                 0x4C08
+#define WM8962_DACL_RETUNE_C5_0                 0x4C09
+#define WM8962_DACL_RETUNE_C6_1                 0x4C0A
+#define WM8962_DACL_RETUNE_C6_0                 0x4C0B
+#define WM8962_DACL_RETUNE_C7_1                 0x4C0C
+#define WM8962_DACL_RETUNE_C7_0                 0x4C0D
+#define WM8962_DACL_RETUNE_C8_1                 0x4C0E
+#define WM8962_DACL_RETUNE_C8_0                 0x4C0F
+#define WM8962_DACL_RETUNE_C9_1                 0x4C10
+#define WM8962_DACL_RETUNE_C9_0                 0x4C11
+#define WM8962_DACL_RETUNE_C10_1                0x4C12
+#define WM8962_DACL_RETUNE_C10_0                0x4C13
+#define WM8962_DACL_RETUNE_C11_1                0x4C14
+#define WM8962_DACL_RETUNE_C11_0                0x4C15
+#define WM8962_DACL_RETUNE_C12_1                0x4C16
+#define WM8962_DACL_RETUNE_C12_0                0x4C17
+#define WM8962_DACL_RETUNE_C13_1                0x4C18
+#define WM8962_DACL_RETUNE_C13_0                0x4C19
+#define WM8962_DACL_RETUNE_C14_1                0x4C1A
+#define WM8962_DACL_RETUNE_C14_0                0x4C1B
+#define WM8962_DACL_RETUNE_C15_1                0x4C1C
+#define WM8962_DACL_RETUNE_C15_0                0x4C1D
+#define WM8962_DACL_RETUNE_C16_1                0x4C1E
+#define WM8962_DACL_RETUNE_C16_0                0x4C1F
+#define WM8962_DACL_RETUNE_C17_1                0x4C20
+#define WM8962_DACL_RETUNE_C17_0                0x4C21
+#define WM8962_DACL_RETUNE_C18_1                0x4C22
+#define WM8962_DACL_RETUNE_C18_0                0x4C23
+#define WM8962_DACL_RETUNE_C19_1                0x4C24
+#define WM8962_DACL_RETUNE_C19_0                0x4C25
+#define WM8962_DACL_RETUNE_C20_1                0x4C26
+#define WM8962_DACL_RETUNE_C20_0                0x4C27
+#define WM8962_DACL_RETUNE_C21_1                0x4C28
+#define WM8962_DACL_RETUNE_C21_0                0x4C29
+#define WM8962_DACL_RETUNE_C22_1                0x4C2A
+#define WM8962_DACL_RETUNE_C22_0                0x4C2B
+#define WM8962_DACL_RETUNE_C23_1                0x4C2C
+#define WM8962_DACL_RETUNE_C23_0                0x4C2D
+#define WM8962_DACL_RETUNE_C24_1                0x4C2E
+#define WM8962_DACL_RETUNE_C24_0                0x4C2F
+#define WM8962_DACL_RETUNE_C25_1                0x4C30
+#define WM8962_DACL_RETUNE_C25_0                0x4C31
+#define WM8962_DACL_RETUNE_C26_1                0x4C32
+#define WM8962_DACL_RETUNE_C26_0                0x4C33
+#define WM8962_DACL_RETUNE_C27_1                0x4C34
+#define WM8962_DACL_RETUNE_C27_0                0x4C35
+#define WM8962_DACL_RETUNE_C28_1                0x4C36
+#define WM8962_DACL_RETUNE_C28_0                0x4C37
+#define WM8962_DACL_RETUNE_C29_1                0x4C38
+#define WM8962_DACL_RETUNE_C29_0                0x4C39
+#define WM8962_DACL_RETUNE_C30_1                0x4C3A
+#define WM8962_DACL_RETUNE_C30_0                0x4C3B
+#define WM8962_DACL_RETUNE_C31_1                0x4C3C
+#define WM8962_DACL_RETUNE_C31_0                0x4C3D
+#define WM8962_DACL_RETUNE_C32_1                0x4C3E
+#define WM8962_DACL_RETUNE_C32_0                0x4C3F
+#define WM8962_RETUNEDAC_PG2_1                  0x4E00
+#define WM8962_RETUNEDAC_PG2_0                  0x4E01
+#define WM8962_RETUNEDAC_PG_1                   0x4E02
+#define WM8962_RETUNEDAC_PG_0                   0x4E03
+#define WM8962_DACR_RETUNE_C1_1                 0x5000
+#define WM8962_DACR_RETUNE_C1_0                 0x5001
+#define WM8962_DACR_RETUNE_C2_1                 0x5002
+#define WM8962_DACR_RETUNE_C2_0                 0x5003
+#define WM8962_DACR_RETUNE_C3_1                 0x5004
+#define WM8962_DACR_RETUNE_C3_0                 0x5005
+#define WM8962_DACR_RETUNE_C4_1                 0x5006
+#define WM8962_DACR_RETUNE_C4_0                 0x5007
+#define WM8962_DACR_RETUNE_C5_1                 0x5008
+#define WM8962_DACR_RETUNE_C5_0                 0x5009
+#define WM8962_DACR_RETUNE_C6_1                 0x500A
+#define WM8962_DACR_RETUNE_C6_0                 0x500B
+#define WM8962_DACR_RETUNE_C7_1                 0x500C
+#define WM8962_DACR_RETUNE_C7_0                 0x500D
+#define WM8962_DACR_RETUNE_C8_1                 0x500E
+#define WM8962_DACR_RETUNE_C8_0                 0x500F
+#define WM8962_DACR_RETUNE_C9_1                 0x5010
+#define WM8962_DACR_RETUNE_C9_0                 0x5011
+#define WM8962_DACR_RETUNE_C10_1                0x5012
+#define WM8962_DACR_RETUNE_C10_0                0x5013
+#define WM8962_DACR_RETUNE_C11_1                0x5014
+#define WM8962_DACR_RETUNE_C11_0                0x5015
+#define WM8962_DACR_RETUNE_C12_1                0x5016
+#define WM8962_DACR_RETUNE_C12_0                0x5017
+#define WM8962_DACR_RETUNE_C13_1                0x5018
+#define WM8962_DACR_RETUNE_C13_0                0x5019
+#define WM8962_DACR_RETUNE_C14_1                0x501A
+#define WM8962_DACR_RETUNE_C14_0                0x501B
+#define WM8962_DACR_RETUNE_C15_1                0x501C
+#define WM8962_DACR_RETUNE_C15_0                0x501D
+#define WM8962_DACR_RETUNE_C16_1                0x501E
+#define WM8962_DACR_RETUNE_C16_0                0x501F
+#define WM8962_DACR_RETUNE_C17_1                0x5020
+#define WM8962_DACR_RETUNE_C17_0                0x5021
+#define WM8962_DACR_RETUNE_C18_1                0x5022
+#define WM8962_DACR_RETUNE_C18_0                0x5023
+#define WM8962_DACR_RETUNE_C19_1                0x5024
+#define WM8962_DACR_RETUNE_C19_0                0x5025
+#define WM8962_DACR_RETUNE_C20_1                0x5026
+#define WM8962_DACR_RETUNE_C20_0                0x5027
+#define WM8962_DACR_RETUNE_C21_1                0x5028
+#define WM8962_DACR_RETUNE_C21_0                0x5029
+#define WM8962_DACR_RETUNE_C22_1                0x502A
+#define WM8962_DACR_RETUNE_C22_0                0x502B
+#define WM8962_DACR_RETUNE_C23_1                0x502C
+#define WM8962_DACR_RETUNE_C23_0                0x502D
+#define WM8962_DACR_RETUNE_C24_1                0x502E
+#define WM8962_DACR_RETUNE_C24_0                0x502F
+#define WM8962_DACR_RETUNE_C25_1                0x5030
+#define WM8962_DACR_RETUNE_C25_0                0x5031
+#define WM8962_DACR_RETUNE_C26_1                0x5032
+#define WM8962_DACR_RETUNE_C26_0                0x5033
+#define WM8962_DACR_RETUNE_C27_1                0x5034
+#define WM8962_DACR_RETUNE_C27_0                0x5035
+#define WM8962_DACR_RETUNE_C28_1                0x5036
+#define WM8962_DACR_RETUNE_C28_0                0x5037
+#define WM8962_DACR_RETUNE_C29_1                0x5038
+#define WM8962_DACR_RETUNE_C29_0                0x5039
+#define WM8962_DACR_RETUNE_C30_1                0x503A
+#define WM8962_DACR_RETUNE_C30_0                0x503B
+#define WM8962_DACR_RETUNE_C31_1                0x503C
+#define WM8962_DACR_RETUNE_C31_0                0x503D
+#define WM8962_DACR_RETUNE_C32_1                0x503E
+#define WM8962_DACR_RETUNE_C32_0                0x503F
+#define WM8962_VSS_XHD2_1                       0x5200
+#define WM8962_VSS_XHD2_0                       0x5201
+#define WM8962_VSS_XHD3_1                       0x5202
+#define WM8962_VSS_XHD3_0                       0x5203
+#define WM8962_VSS_XHN1_1                       0x5204
+#define WM8962_VSS_XHN1_0                       0x5205
+#define WM8962_VSS_XHN2_1                       0x5206
+#define WM8962_VSS_XHN2_0                       0x5207
+#define WM8962_VSS_XHN3_1                       0x5208
+#define WM8962_VSS_XHN3_0                       0x5209
+#define WM8962_VSS_XLA_1                        0x520A
+#define WM8962_VSS_XLA_0                        0x520B
+#define WM8962_VSS_XLB_1                        0x520C
+#define WM8962_VSS_XLB_0                        0x520D
+#define WM8962_VSS_XLG_1                        0x520E
+#define WM8962_VSS_XLG_0                        0x520F
+#define WM8962_VSS_PG2_1                        0x5210
+#define WM8962_VSS_PG2_0                        0x5211
+#define WM8962_VSS_PG_1                         0x5212
+#define WM8962_VSS_PG_0                         0x5213
+#define WM8962_VSS_XTD1_1                       0x5214
+#define WM8962_VSS_XTD1_0                       0x5215
+#define WM8962_VSS_XTD2_1                       0x5216
+#define WM8962_VSS_XTD2_0                       0x5217
+#define WM8962_VSS_XTD3_1                       0x5218
+#define WM8962_VSS_XTD3_0                       0x5219
+#define WM8962_VSS_XTD4_1                       0x521A
+#define WM8962_VSS_XTD4_0                       0x521B
+#define WM8962_VSS_XTD5_1                       0x521C
+#define WM8962_VSS_XTD5_0                       0x521D
+#define WM8962_VSS_XTD6_1                       0x521E
+#define WM8962_VSS_XTD6_0                       0x521F
+#define WM8962_VSS_XTD7_1                       0x5220
+#define WM8962_VSS_XTD7_0                       0x5221
+#define WM8962_VSS_XTD8_1                       0x5222
+#define WM8962_VSS_XTD8_0                       0x5223
+#define WM8962_VSS_XTD9_1                       0x5224
+#define WM8962_VSS_XTD9_0                       0x5225
+#define WM8962_VSS_XTD10_1                      0x5226
+#define WM8962_VSS_XTD10_0                      0x5227
+#define WM8962_VSS_XTD11_1                      0x5228
+#define WM8962_VSS_XTD11_0                      0x5229
+#define WM8962_VSS_XTD12_1                      0x522A
+#define WM8962_VSS_XTD12_0                      0x522B
+#define WM8962_VSS_XTD13_1                      0x522C
+#define WM8962_VSS_XTD13_0                      0x522D
+#define WM8962_VSS_XTD14_1                      0x522E
+#define WM8962_VSS_XTD14_0                      0x522F
+#define WM8962_VSS_XTD15_1                      0x5230
+#define WM8962_VSS_XTD15_0                      0x5231
+#define WM8962_VSS_XTD16_1                      0x5232
+#define WM8962_VSS_XTD16_0                      0x5233
+#define WM8962_VSS_XTD17_1                      0x5234
+#define WM8962_VSS_XTD17_0                      0x5235
+#define WM8962_VSS_XTD18_1                      0x5236
+#define WM8962_VSS_XTD18_0                      0x5237
+#define WM8962_VSS_XTD19_1                      0x5238
+#define WM8962_VSS_XTD19_0                      0x5239
+#define WM8962_VSS_XTD20_1                      0x523A
+#define WM8962_VSS_XTD20_0                      0x523B
+#define WM8962_VSS_XTD21_1                      0x523C
+#define WM8962_VSS_XTD21_0                      0x523D
+#define WM8962_VSS_XTD22_1                      0x523E
+#define WM8962_VSS_XTD22_0                      0x523F
+#define WM8962_VSS_XTD23_1                      0x5240
+#define WM8962_VSS_XTD23_0                      0x5241
+#define WM8962_VSS_XTD24_1                      0x5242
+#define WM8962_VSS_XTD24_0                      0x5243
+#define WM8962_VSS_XTD25_1                      0x5244
+#define WM8962_VSS_XTD25_0                      0x5245
+#define WM8962_VSS_XTD26_1                      0x5246
+#define WM8962_VSS_XTD26_0                      0x5247
+#define WM8962_VSS_XTD27_1                      0x5248
+#define WM8962_VSS_XTD27_0                      0x5249
+#define WM8962_VSS_XTD28_1                      0x524A
+#define WM8962_VSS_XTD28_0                      0x524B
+#define WM8962_VSS_XTD29_1                      0x524C
+#define WM8962_VSS_XTD29_0                      0x524D
+#define WM8962_VSS_XTD30_1                      0x524E
+#define WM8962_VSS_XTD30_0                      0x524F
+#define WM8962_VSS_XTD31_1                      0x5250
+#define WM8962_VSS_XTD31_0                      0x5251
+#define WM8962_VSS_XTD32_1                      0x5252
+#define WM8962_VSS_XTD32_0                      0x5253
+#define WM8962_VSS_XTS1_1                       0x5254
+#define WM8962_VSS_XTS1_0                       0x5255
+#define WM8962_VSS_XTS2_1                       0x5256
+#define WM8962_VSS_XTS2_0                       0x5257
+#define WM8962_VSS_XTS3_1                       0x5258
+#define WM8962_VSS_XTS3_0                       0x5259
+#define WM8962_VSS_XTS4_1                       0x525A
+#define WM8962_VSS_XTS4_0                       0x525B
+#define WM8962_VSS_XTS5_1                       0x525C
+#define WM8962_VSS_XTS5_0                       0x525D
+#define WM8962_VSS_XTS6_1                       0x525E
+#define WM8962_VSS_XTS6_0                       0x525F
+#define WM8962_VSS_XTS7_1                       0x5260
+#define WM8962_VSS_XTS7_0                       0x5261
+#define WM8962_VSS_XTS8_1                       0x5262
+#define WM8962_VSS_XTS8_0                       0x5263
+#define WM8962_VSS_XTS9_1                       0x5264
+#define WM8962_VSS_XTS9_0                       0x5265
+#define WM8962_VSS_XTS10_1                      0x5266
+#define WM8962_VSS_XTS10_0                      0x5267
+#define WM8962_VSS_XTS11_1                      0x5268
+#define WM8962_VSS_XTS11_0                      0x5269
+#define WM8962_VSS_XTS12_1                      0x526A
+#define WM8962_VSS_XTS12_0                      0x526B
+#define WM8962_VSS_XTS13_1                      0x526C
+#define WM8962_VSS_XTS13_0                      0x526D
+#define WM8962_VSS_XTS14_1                      0x526E
+#define WM8962_VSS_XTS14_0                      0x526F
+#define WM8962_VSS_XTS15_1                      0x5270
+#define WM8962_VSS_XTS15_0                      0x5271
+#define WM8962_VSS_XTS16_1                      0x5272
+#define WM8962_VSS_XTS16_0                      0x5273
+#define WM8962_VSS_XTS17_1                      0x5274
+#define WM8962_VSS_XTS17_0                      0x5275
+#define WM8962_VSS_XTS18_1                      0x5276
+#define WM8962_VSS_XTS18_0                      0x5277
+#define WM8962_VSS_XTS19_1                      0x5278
+#define WM8962_VSS_XTS19_0                      0x5279
+#define WM8962_VSS_XTS20_1                      0x527A
+#define WM8962_VSS_XTS20_0                      0x527B
+#define WM8962_VSS_XTS21_1                      0x527C
+#define WM8962_VSS_XTS21_0                      0x527D
+#define WM8962_VSS_XTS22_1                      0x527E
+#define WM8962_VSS_XTS22_0                      0x527F
+#define WM8962_VSS_XTS23_1                      0x5280
+#define WM8962_VSS_XTS23_0                      0x5281
+#define WM8962_VSS_XTS24_1                      0x5282
+#define WM8962_VSS_XTS24_0                      0x5283
+#define WM8962_VSS_XTS25_1                      0x5284
+#define WM8962_VSS_XTS25_0                      0x5285
+#define WM8962_VSS_XTS26_1                      0x5286
+#define WM8962_VSS_XTS26_0                      0x5287
+#define WM8962_VSS_XTS27_1                      0x5288
+#define WM8962_VSS_XTS27_0                      0x5289
+#define WM8962_VSS_XTS28_1                      0x528A
+#define WM8962_VSS_XTS28_0                      0x528B
+#define WM8962_VSS_XTS29_1                      0x528C
+#define WM8962_VSS_XTS29_0                      0x528D
+#define WM8962_VSS_XTS30_1                      0x528E
+#define WM8962_VSS_XTS30_0                      0x528F
+#define WM8962_VSS_XTS31_1                      0x5290
+#define WM8962_VSS_XTS31_0                      0x5291
+#define WM8962_VSS_XTS32_1                      0x5292
+#define WM8962_VSS_XTS32_0                      0x5293
+
+#define WM8962_REGISTER_COUNT                   1138
+#define WM8962_MAX_REGISTER                     0x5293
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Left Input volume
+ */
+#define WM8962_IN_VU                            0x0100  /* IN_VU */
+#define WM8962_IN_VU_MASK                       0x0100  /* IN_VU */
+#define WM8962_IN_VU_SHIFT                           8  /* IN_VU */
+#define WM8962_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM8962_INPGAL_MUTE                      0x0080  /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_MASK                 0x0080  /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_SHIFT                     7  /* INPGAL_MUTE */
+#define WM8962_INPGAL_MUTE_WIDTH                     1  /* INPGAL_MUTE */
+#define WM8962_INL_ZC                           0x0040  /* INL_ZC */
+#define WM8962_INL_ZC_MASK                      0x0040  /* INL_ZC */
+#define WM8962_INL_ZC_SHIFT                          6  /* INL_ZC */
+#define WM8962_INL_ZC_WIDTH                          1  /* INL_ZC */
+#define WM8962_INL_VOL_MASK                     0x003F  /* INL_VOL - [5:0] */
+#define WM8962_INL_VOL_SHIFT                         0  /* INL_VOL - [5:0] */
+#define WM8962_INL_VOL_WIDTH                         6  /* INL_VOL - [5:0] */
+
+/*
+ * R1 (0x01) - Right Input volume
+ */
+#define WM8962_CUST_ID_MASK                     0xF000  /* CUST_ID - [15:12] */
+#define WM8962_CUST_ID_SHIFT                        12  /* CUST_ID - [15:12] */
+#define WM8962_CUST_ID_WIDTH                         4  /* CUST_ID - [15:12] */
+#define WM8962_CHIP_REV_MASK                    0x0E00  /* CHIP_REV - [11:9] */
+#define WM8962_CHIP_REV_SHIFT                        9  /* CHIP_REV - [11:9] */
+#define WM8962_CHIP_REV_WIDTH                        3  /* CHIP_REV - [11:9] */
+#define WM8962_IN_VU                            0x0100  /* IN_VU */
+#define WM8962_IN_VU_MASK                       0x0100  /* IN_VU */
+#define WM8962_IN_VU_SHIFT                           8  /* IN_VU */
+#define WM8962_IN_VU_WIDTH                           1  /* IN_VU */
+#define WM8962_INPGAR_MUTE                      0x0080  /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_MASK                 0x0080  /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_SHIFT                     7  /* INPGAR_MUTE */
+#define WM8962_INPGAR_MUTE_WIDTH                     1  /* INPGAR_MUTE */
+#define WM8962_INR_ZC                           0x0040  /* INR_ZC */
+#define WM8962_INR_ZC_MASK                      0x0040  /* INR_ZC */
+#define WM8962_INR_ZC_SHIFT                          6  /* INR_ZC */
+#define WM8962_INR_ZC_WIDTH                          1  /* INR_ZC */
+#define WM8962_INR_VOL_MASK                     0x003F  /* INR_VOL - [5:0] */
+#define WM8962_INR_VOL_SHIFT                         0  /* INR_VOL - [5:0] */
+#define WM8962_INR_VOL_WIDTH                         6  /* INR_VOL - [5:0] */
+
+/*
+ * R2 (0x02) - HPOUTL volume
+ */
+#define WM8962_HPOUT_VU                         0x0100  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_MASK                    0x0100  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_SHIFT                        8  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_WIDTH                        1  /* HPOUT_VU */
+#define WM8962_HPOUTL_ZC                        0x0080  /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_MASK                   0x0080  /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_SHIFT                       7  /* HPOUTL_ZC */
+#define WM8962_HPOUTL_ZC_WIDTH                       1  /* HPOUTL_ZC */
+#define WM8962_HPOUTL_VOL_MASK                  0x007F  /* HPOUTL_VOL - [6:0] */
+#define WM8962_HPOUTL_VOL_SHIFT                      0  /* HPOUTL_VOL - [6:0] */
+#define WM8962_HPOUTL_VOL_WIDTH                      7  /* HPOUTL_VOL - [6:0] */
+
+/*
+ * R3 (0x03) - HPOUTR volume
+ */
+#define WM8962_HPOUT_VU                         0x0100  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_MASK                    0x0100  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_SHIFT                        8  /* HPOUT_VU */
+#define WM8962_HPOUT_VU_WIDTH                        1  /* HPOUT_VU */
+#define WM8962_HPOUTR_ZC                        0x0080  /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_MASK                   0x0080  /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_SHIFT                       7  /* HPOUTR_ZC */
+#define WM8962_HPOUTR_ZC_WIDTH                       1  /* HPOUTR_ZC */
+#define WM8962_HPOUTR_VOL_MASK                  0x007F  /* HPOUTR_VOL - [6:0] */
+#define WM8962_HPOUTR_VOL_SHIFT                      0  /* HPOUTR_VOL - [6:0] */
+#define WM8962_HPOUTR_VOL_WIDTH                      7  /* HPOUTR_VOL - [6:0] */
+
+/*
+ * R4 (0x04) - Clocking1
+ */
+#define WM8962_DSPCLK_DIV_MASK                  0x0600  /* DSPCLK_DIV - [10:9] */
+#define WM8962_DSPCLK_DIV_SHIFT                      9  /* DSPCLK_DIV - [10:9] */
+#define WM8962_DSPCLK_DIV_WIDTH                      2  /* DSPCLK_DIV - [10:9] */
+#define WM8962_ADCSYS_CLK_DIV_MASK              0x01C0  /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_ADCSYS_CLK_DIV_SHIFT                  6  /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_ADCSYS_CLK_DIV_WIDTH                  3  /* ADCSYS_CLK_DIV - [8:6] */
+#define WM8962_DACSYS_CLK_DIV_MASK              0x0038  /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_DACSYS_CLK_DIV_SHIFT                  3  /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_DACSYS_CLK_DIV_WIDTH                  3  /* DACSYS_CLK_DIV - [5:3] */
+#define WM8962_MCLKDIV_MASK                     0x0006  /* MCLKDIV - [2:1] */
+#define WM8962_MCLKDIV_SHIFT                         1  /* MCLKDIV - [2:1] */
+#define WM8962_MCLKDIV_WIDTH                         2  /* MCLKDIV - [2:1] */
+
+/*
+ * R5 (0x05) - ADC & DAC Control 1
+ */
+#define WM8962_ADCR_DAT_INV                     0x0040  /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_MASK                0x0040  /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_SHIFT                    6  /* ADCR_DAT_INV */
+#define WM8962_ADCR_DAT_INV_WIDTH                    1  /* ADCR_DAT_INV */
+#define WM8962_ADCL_DAT_INV                     0x0020  /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_MASK                0x0020  /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_SHIFT                    5  /* ADCL_DAT_INV */
+#define WM8962_ADCL_DAT_INV_WIDTH                    1  /* ADCL_DAT_INV */
+#define WM8962_DAC_MUTE_RAMP                    0x0010  /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_MASK               0x0010  /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_SHIFT                   4  /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE_RAMP_WIDTH                   1  /* DAC_MUTE_RAMP */
+#define WM8962_DAC_MUTE                         0x0008  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_MASK                    0x0008  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_SHIFT                        3  /* DAC_MUTE */
+#define WM8962_DAC_MUTE_WIDTH                        1  /* DAC_MUTE */
+#define WM8962_DAC_DEEMP_MASK                   0x0006  /* DAC_DEEMP - [2:1] */
+#define WM8962_DAC_DEEMP_SHIFT                       1  /* DAC_DEEMP - [2:1] */
+#define WM8962_DAC_DEEMP_WIDTH                       2  /* DAC_DEEMP - [2:1] */
+#define WM8962_ADC_HPF_DIS                      0x0001  /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_MASK                 0x0001  /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_SHIFT                     0  /* ADC_HPF_DIS */
+#define WM8962_ADC_HPF_DIS_WIDTH                     1  /* ADC_HPF_DIS */
+
+/*
+ * R6 (0x06) - ADC & DAC Control 2
+ */
+#define WM8962_ADC_HPF_SR_MASK                  0x3000  /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_SR_SHIFT                     12  /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_SR_WIDTH                      2  /* ADC_HPF_SR - [13:12] */
+#define WM8962_ADC_HPF_MODE                     0x0400  /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_MASK                0x0400  /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_SHIFT                   10  /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_MODE_WIDTH                    1  /* ADC_HPF_MODE */
+#define WM8962_ADC_HPF_CUT_MASK                 0x0380  /* ADC_HPF_CUT - [9:7] */
+#define WM8962_ADC_HPF_CUT_SHIFT                     7  /* ADC_HPF_CUT - [9:7] */
+#define WM8962_ADC_HPF_CUT_WIDTH                     3  /* ADC_HPF_CUT - [9:7] */
+#define WM8962_DACR_DAT_INV                     0x0040  /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_MASK                0x0040  /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_SHIFT                    6  /* DACR_DAT_INV */
+#define WM8962_DACR_DAT_INV_WIDTH                    1  /* DACR_DAT_INV */
+#define WM8962_DACL_DAT_INV                     0x0020  /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_MASK                0x0020  /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_SHIFT                    5  /* DACL_DAT_INV */
+#define WM8962_DACL_DAT_INV_WIDTH                    1  /* DACL_DAT_INV */
+#define WM8962_DAC_UNMUTE_RAMP                  0x0008  /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_MASK             0x0008  /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_SHIFT                 3  /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_UNMUTE_RAMP_WIDTH                 1  /* DAC_UNMUTE_RAMP */
+#define WM8962_DAC_MUTERATE                     0x0004  /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_MASK                0x0004  /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_SHIFT                    2  /* DAC_MUTERATE */
+#define WM8962_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+#define WM8962_DAC_HP                           0x0001  /* DAC_HP */
+#define WM8962_DAC_HP_MASK                      0x0001  /* DAC_HP */
+#define WM8962_DAC_HP_SHIFT                          0  /* DAC_HP */
+#define WM8962_DAC_HP_WIDTH                          1  /* DAC_HP */
+
+/*
+ * R7 (0x07) - Audio Interface 0
+ */
+#define WM8962_AIFDAC_TDM_MODE                  0x1000  /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_MASK             0x1000  /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_SHIFT                12  /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_MODE_WIDTH                 1  /* AIFDAC_TDM_MODE */
+#define WM8962_AIFDAC_TDM_SLOT                  0x0800  /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_MASK             0x0800  /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_SHIFT                11  /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFDAC_TDM_SLOT_WIDTH                 1  /* AIFDAC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_MODE                  0x0400  /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_MASK             0x0400  /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_SHIFT                10  /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_MODE_WIDTH                 1  /* AIFADC_TDM_MODE */
+#define WM8962_AIFADC_TDM_SLOT                  0x0200  /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_MASK             0x0200  /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_SHIFT                 9  /* AIFADC_TDM_SLOT */
+#define WM8962_AIFADC_TDM_SLOT_WIDTH                 1  /* AIFADC_TDM_SLOT */
+#define WM8962_ADC_LRSWAP                       0x0100  /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_MASK                  0x0100  /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_SHIFT                      8  /* ADC_LRSWAP */
+#define WM8962_ADC_LRSWAP_WIDTH                      1  /* ADC_LRSWAP */
+#define WM8962_BCLK_INV                         0x0080  /* BCLK_INV */
+#define WM8962_BCLK_INV_MASK                    0x0080  /* BCLK_INV */
+#define WM8962_BCLK_INV_SHIFT                        7  /* BCLK_INV */
+#define WM8962_BCLK_INV_WIDTH                        1  /* BCLK_INV */
+#define WM8962_MSTR                             0x0040  /* MSTR */
+#define WM8962_MSTR_MASK                        0x0040  /* MSTR */
+#define WM8962_MSTR_SHIFT                            6  /* MSTR */
+#define WM8962_MSTR_WIDTH                            1  /* MSTR */
+#define WM8962_DAC_LRSWAP                       0x0020  /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_MASK                  0x0020  /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_SHIFT                      5  /* DAC_LRSWAP */
+#define WM8962_DAC_LRSWAP_WIDTH                      1  /* DAC_LRSWAP */
+#define WM8962_LRCLK_INV                        0x0010  /* LRCLK_INV */
+#define WM8962_LRCLK_INV_MASK                   0x0010  /* LRCLK_INV */
+#define WM8962_LRCLK_INV_SHIFT                       4  /* LRCLK_INV */
+#define WM8962_LRCLK_INV_WIDTH                       1  /* LRCLK_INV */
+#define WM8962_WL_MASK                          0x000C  /* WL - [3:2] */
+#define WM8962_WL_SHIFT                              2  /* WL - [3:2] */
+#define WM8962_WL_WIDTH                              2  /* WL - [3:2] */
+#define WM8962_FMT_MASK                         0x0003  /* FMT - [1:0] */
+#define WM8962_FMT_SHIFT                             0  /* FMT - [1:0] */
+#define WM8962_FMT_WIDTH                             2  /* FMT - [1:0] */
+
+/*
+ * R8 (0x08) - Clocking2
+ */
+#define WM8962_CLKREG_OVD                       0x0800  /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_MASK                  0x0800  /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_SHIFT                     11  /* CLKREG_OVD */
+#define WM8962_CLKREG_OVD_WIDTH                      1  /* CLKREG_OVD */
+#define WM8962_SYSCLK_SRC_MASK                  0x0600  /* SYSCLK_SRC - [10:9] */
+#define WM8962_SYSCLK_SRC_SHIFT                      9  /* SYSCLK_SRC - [10:9] */
+#define WM8962_SYSCLK_SRC_WIDTH                      2  /* SYSCLK_SRC - [10:9] */
+#define WM8962_CLASSD_CLK_DIV_MASK              0x01C0  /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_CLASSD_CLK_DIV_SHIFT                  6  /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_CLASSD_CLK_DIV_WIDTH                  3  /* CLASSD_CLK_DIV - [8:6] */
+#define WM8962_SYSCLK_ENA                       0x0020  /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_MASK                  0x0020  /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_SHIFT                      5  /* SYSCLK_ENA */
+#define WM8962_SYSCLK_ENA_WIDTH                      1  /* SYSCLK_ENA */
+#define WM8962_BCLK_DIV_MASK                    0x000F  /* BCLK_DIV - [3:0] */
+#define WM8962_BCLK_DIV_SHIFT                        0  /* BCLK_DIV - [3:0] */
+#define WM8962_BCLK_DIV_WIDTH                        4  /* BCLK_DIV - [3:0] */
+
+/*
+ * R9 (0x09) - Audio Interface 1
+ */
+#define WM8962_AUTOMUTE_STS                     0x0800  /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_MASK                0x0800  /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_SHIFT                   11  /* AUTOMUTE_STS */
+#define WM8962_AUTOMUTE_STS_WIDTH                    1  /* AUTOMUTE_STS */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_MASK        0x0300  /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_SHIFT            8  /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE_SAMPLES_WIDTH            2  /* DAC_AUTOMUTE_SAMPLES - [9:8] */
+#define WM8962_DAC_AUTOMUTE                     0x0080  /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_MASK                0x0080  /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_SHIFT                    7  /* DAC_AUTOMUTE */
+#define WM8962_DAC_AUTOMUTE_WIDTH                    1  /* DAC_AUTOMUTE */
+#define WM8962_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8962_DAC_COMP_MASK                    0x0010  /* DAC_COMP */
+#define WM8962_DAC_COMP_SHIFT                        4  /* DAC_COMP */
+#define WM8962_DAC_COMP_WIDTH                        1  /* DAC_COMP */
+#define WM8962_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_MASK                0x0008  /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_SHIFT                    3  /* DAC_COMPMODE */
+#define WM8962_DAC_COMPMODE_WIDTH                    1  /* DAC_COMPMODE */
+#define WM8962_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8962_ADC_COMP_MASK                    0x0004  /* ADC_COMP */
+#define WM8962_ADC_COMP_SHIFT                        2  /* ADC_COMP */
+#define WM8962_ADC_COMP_WIDTH                        1  /* ADC_COMP */
+#define WM8962_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_MASK                0x0002  /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_SHIFT                    1  /* ADC_COMPMODE */
+#define WM8962_ADC_COMPMODE_WIDTH                    1  /* ADC_COMPMODE */
+#define WM8962_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8962_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8962_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8962_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R10 (0x0A) - Left DAC volume
+ */
+#define WM8962_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8962_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8962_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8962_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8962_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8962_DACL_VOL_SHIFT                        0  /* DACL_VOL - [7:0] */
+#define WM8962_DACL_VOL_WIDTH                        8  /* DACL_VOL - [7:0] */
+
+/*
+ * R11 (0x0B) - Right DAC volume
+ */
+#define WM8962_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8962_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8962_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8962_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8962_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8962_DACR_VOL_SHIFT                        0  /* DACR_VOL - [7:0] */
+#define WM8962_DACR_VOL_WIDTH                        8  /* DACR_VOL - [7:0] */
+
+/*
+ * R14 (0x0E) - Audio Interface 2
+ */
+#define WM8962_AIF_RATE_MASK                    0x07FF  /* AIF_RATE - [10:0] */
+#define WM8962_AIF_RATE_SHIFT                        0  /* AIF_RATE - [10:0] */
+#define WM8962_AIF_RATE_WIDTH                       11  /* AIF_RATE - [10:0] */
+
+/*
+ * R15 (0x0F) - Software Reset
+ */
+#define WM8962_SW_RESET_MASK                    0xFFFF  /* SW_RESET - [15:0] */
+#define WM8962_SW_RESET_SHIFT                        0  /* SW_RESET - [15:0] */
+#define WM8962_SW_RESET_WIDTH                       16  /* SW_RESET - [15:0] */
+
+/*
+ * R17 (0x11) - ALC1
+ */
+#define WM8962_ALC_INACTIVE_ENA                 0x0400  /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_MASK            0x0400  /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_SHIFT               10  /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_INACTIVE_ENA_WIDTH                1  /* ALC_INACTIVE_ENA */
+#define WM8962_ALC_LVL_MODE                     0x0200  /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_MASK                0x0200  /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_SHIFT                    9  /* ALC_LVL_MODE */
+#define WM8962_ALC_LVL_MODE_WIDTH                    1  /* ALC_LVL_MODE */
+#define WM8962_ALCL_ENA                         0x0100  /* ALCL_ENA */
+#define WM8962_ALCL_ENA_MASK                    0x0100  /* ALCL_ENA */
+#define WM8962_ALCL_ENA_SHIFT                        8  /* ALCL_ENA */
+#define WM8962_ALCL_ENA_WIDTH                        1  /* ALCL_ENA */
+#define WM8962_ALCR_ENA                         0x0080  /* ALCR_ENA */
+#define WM8962_ALCR_ENA_MASK                    0x0080  /* ALCR_ENA */
+#define WM8962_ALCR_ENA_SHIFT                        7  /* ALCR_ENA */
+#define WM8962_ALCR_ENA_WIDTH                        1  /* ALCR_ENA */
+#define WM8962_ALC_MAXGAIN_MASK                 0x0070  /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_MAXGAIN_SHIFT                     4  /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_MAXGAIN_WIDTH                     3  /* ALC_MAXGAIN - [6:4] */
+#define WM8962_ALC_LVL_MASK                     0x000F  /* ALC_LVL - [3:0] */
+#define WM8962_ALC_LVL_SHIFT                         0  /* ALC_LVL - [3:0] */
+#define WM8962_ALC_LVL_WIDTH                         4  /* ALC_LVL - [3:0] */
+
+/*
+ * R18 (0x12) - ALC2
+ */
+#define WM8962_ALC_LOCK_STS                     0x8000  /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_MASK                0x8000  /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_SHIFT                   15  /* ALC_LOCK_STS */
+#define WM8962_ALC_LOCK_STS_WIDTH                    1  /* ALC_LOCK_STS */
+#define WM8962_ALC_THRESH_STS                   0x4000  /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_MASK              0x4000  /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_SHIFT                 14  /* ALC_THRESH_STS */
+#define WM8962_ALC_THRESH_STS_WIDTH                  1  /* ALC_THRESH_STS */
+#define WM8962_ALC_SAT_STS                      0x2000  /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_MASK                 0x2000  /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_SHIFT                    13  /* ALC_SAT_STS */
+#define WM8962_ALC_SAT_STS_WIDTH                     1  /* ALC_SAT_STS */
+#define WM8962_ALC_PKOVR_STS                    0x1000  /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_MASK               0x1000  /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_SHIFT                  12  /* ALC_PKOVR_STS */
+#define WM8962_ALC_PKOVR_STS_WIDTH                   1  /* ALC_PKOVR_STS */
+#define WM8962_ALC_NGATE_STS                    0x0800  /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_MASK               0x0800  /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_SHIFT                  11  /* ALC_NGATE_STS */
+#define WM8962_ALC_NGATE_STS_WIDTH                   1  /* ALC_NGATE_STS */
+#define WM8962_ALC_ZC                           0x0080  /* ALC_ZC */
+#define WM8962_ALC_ZC_MASK                      0x0080  /* ALC_ZC */
+#define WM8962_ALC_ZC_SHIFT                          7  /* ALC_ZC */
+#define WM8962_ALC_ZC_WIDTH                          1  /* ALC_ZC */
+#define WM8962_ALC_MINGAIN_MASK                 0x0070  /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_MINGAIN_SHIFT                     4  /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_MINGAIN_WIDTH                     3  /* ALC_MINGAIN - [6:4] */
+#define WM8962_ALC_HLD_MASK                     0x000F  /* ALC_HLD - [3:0] */
+#define WM8962_ALC_HLD_SHIFT                         0  /* ALC_HLD - [3:0] */
+#define WM8962_ALC_HLD_WIDTH                         4  /* ALC_HLD - [3:0] */
+
+/*
+ * R19 (0x13) - ALC3
+ */
+#define WM8962_ALC_NGATE_GAIN_MASK              0x1C00  /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_NGATE_GAIN_SHIFT                 10  /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_NGATE_GAIN_WIDTH                  3  /* ALC_NGATE_GAIN - [12:10] */
+#define WM8962_ALC_MODE                         0x0100  /* ALC_MODE */
+#define WM8962_ALC_MODE_MASK                    0x0100  /* ALC_MODE */
+#define WM8962_ALC_MODE_SHIFT                        8  /* ALC_MODE */
+#define WM8962_ALC_MODE_WIDTH                        1  /* ALC_MODE */
+#define WM8962_ALC_DCY_MASK                     0x00F0  /* ALC_DCY - [7:4] */
+#define WM8962_ALC_DCY_SHIFT                         4  /* ALC_DCY - [7:4] */
+#define WM8962_ALC_DCY_WIDTH                         4  /* ALC_DCY - [7:4] */
+#define WM8962_ALC_ATK_MASK                     0x000F  /* ALC_ATK - [3:0] */
+#define WM8962_ALC_ATK_SHIFT                         0  /* ALC_ATK - [3:0] */
+#define WM8962_ALC_ATK_WIDTH                         4  /* ALC_ATK - [3:0] */
+
+/*
+ * R20 (0x14) - Noise Gate
+ */
+#define WM8962_ALC_NGATE_DCY_MASK               0xF000  /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_DCY_SHIFT                  12  /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_DCY_WIDTH                   4  /* ALC_NGATE_DCY - [15:12] */
+#define WM8962_ALC_NGATE_ATK_MASK               0x0F00  /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_ATK_SHIFT                   8  /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_ATK_WIDTH                   4  /* ALC_NGATE_ATK - [11:8] */
+#define WM8962_ALC_NGATE_THR_MASK               0x00F8  /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_THR_SHIFT                   3  /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_THR_WIDTH                   5  /* ALC_NGATE_THR - [7:3] */
+#define WM8962_ALC_NGATE_MODE_MASK              0x0006  /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_MODE_SHIFT                  1  /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_MODE_WIDTH                  2  /* ALC_NGATE_MODE - [2:1] */
+#define WM8962_ALC_NGATE_ENA                    0x0001  /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_MASK               0x0001  /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_SHIFT                   0  /* ALC_NGATE_ENA */
+#define WM8962_ALC_NGATE_ENA_WIDTH                   1  /* ALC_NGATE_ENA */
+
+/*
+ * R21 (0x15) - Left ADC volume
+ */
+#define WM8962_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8962_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8962_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8962_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8962_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8962_ADCL_VOL_SHIFT                        0  /* ADCL_VOL - [7:0] */
+#define WM8962_ADCL_VOL_WIDTH                        8  /* ADCL_VOL - [7:0] */
+
+/*
+ * R22 (0x16) - Right ADC volume
+ */
+#define WM8962_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8962_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8962_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8962_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8962_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8962_ADCR_VOL_SHIFT                        0  /* ADCR_VOL - [7:0] */
+#define WM8962_ADCR_VOL_WIDTH                        8  /* ADCR_VOL - [7:0] */
+
+/*
+ * R23 (0x17) - Additional control(1)
+ */
+#define WM8962_THERR_ACT                        0x0100  /* THERR_ACT */
+#define WM8962_THERR_ACT_MASK                   0x0100  /* THERR_ACT */
+#define WM8962_THERR_ACT_SHIFT                       8  /* THERR_ACT */
+#define WM8962_THERR_ACT_WIDTH                       1  /* THERR_ACT */
+#define WM8962_ADC_BIAS                         0x0040  /* ADC_BIAS */
+#define WM8962_ADC_BIAS_MASK                    0x0040  /* ADC_BIAS */
+#define WM8962_ADC_BIAS_SHIFT                        6  /* ADC_BIAS */
+#define WM8962_ADC_BIAS_WIDTH                        1  /* ADC_BIAS */
+#define WM8962_ADC_HP                           0x0020  /* ADC_HP */
+#define WM8962_ADC_HP_MASK                      0x0020  /* ADC_HP */
+#define WM8962_ADC_HP_SHIFT                          5  /* ADC_HP */
+#define WM8962_ADC_HP_WIDTH                          1  /* ADC_HP */
+#define WM8962_TOCLK_ENA                        0x0001  /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_MASK                   0x0001  /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_SHIFT                       0  /* TOCLK_ENA */
+#define WM8962_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+
+/*
+ * R24 (0x18) - Additional control(2)
+ */
+#define WM8962_AIF_TRI                          0x0008  /* AIF_TRI */
+#define WM8962_AIF_TRI_MASK                     0x0008  /* AIF_TRI */
+#define WM8962_AIF_TRI_SHIFT                         3  /* AIF_TRI */
+#define WM8962_AIF_TRI_WIDTH                         1  /* AIF_TRI */
+
+/*
+ * R25 (0x19) - Pwr Mgmt (1)
+ */
+#define WM8962_DMIC_ENA                         0x0400  /* DMIC_ENA */
+#define WM8962_DMIC_ENA_MASK                    0x0400  /* DMIC_ENA */
+#define WM8962_DMIC_ENA_SHIFT                       10  /* DMIC_ENA */
+#define WM8962_DMIC_ENA_WIDTH                        1  /* DMIC_ENA */
+#define WM8962_OPCLK_ENA                        0x0200  /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_MASK                   0x0200  /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_SHIFT                       9  /* OPCLK_ENA */
+#define WM8962_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8962_VMID_SEL_MASK                    0x0180  /* VMID_SEL - [8:7] */
+#define WM8962_VMID_SEL_SHIFT                        7  /* VMID_SEL - [8:7] */
+#define WM8962_VMID_SEL_WIDTH                        2  /* VMID_SEL - [8:7] */
+#define WM8962_BIAS_ENA                         0x0040  /* BIAS_ENA */
+#define WM8962_BIAS_ENA_MASK                    0x0040  /* BIAS_ENA */
+#define WM8962_BIAS_ENA_SHIFT                        6  /* BIAS_ENA */
+#define WM8962_BIAS_ENA_WIDTH                        1  /* BIAS_ENA */
+#define WM8962_INL_ENA                          0x0020  /* INL_ENA */
+#define WM8962_INL_ENA_MASK                     0x0020  /* INL_ENA */
+#define WM8962_INL_ENA_SHIFT                         5  /* INL_ENA */
+#define WM8962_INL_ENA_WIDTH                         1  /* INL_ENA */
+#define WM8962_INR_ENA                          0x0010  /* INR_ENA */
+#define WM8962_INR_ENA_MASK                     0x0010  /* INR_ENA */
+#define WM8962_INR_ENA_SHIFT                         4  /* INR_ENA */
+#define WM8962_INR_ENA_WIDTH                         1  /* INR_ENA */
+#define WM8962_ADCL_ENA                         0x0008  /* ADCL_ENA */
+#define WM8962_ADCL_ENA_MASK                    0x0008  /* ADCL_ENA */
+#define WM8962_ADCL_ENA_SHIFT                        3  /* ADCL_ENA */
+#define WM8962_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8962_ADCR_ENA                         0x0004  /* ADCR_ENA */
+#define WM8962_ADCR_ENA_MASK                    0x0004  /* ADCR_ENA */
+#define WM8962_ADCR_ENA_SHIFT                        2  /* ADCR_ENA */
+#define WM8962_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+#define WM8962_MICBIAS_ENA                      0x0002  /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_MASK                 0x0002  /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_SHIFT                     1  /* MICBIAS_ENA */
+#define WM8962_MICBIAS_ENA_WIDTH                     1  /* MICBIAS_ENA */
+
+/*
+ * R26 (0x1A) - Pwr Mgmt (2)
+ */
+#define WM8962_DACL_ENA                         0x0100  /* DACL_ENA */
+#define WM8962_DACL_ENA_MASK                    0x0100  /* DACL_ENA */
+#define WM8962_DACL_ENA_SHIFT                        8  /* DACL_ENA */
+#define WM8962_DACL_ENA_WIDTH                        1  /* DACL_ENA */
+#define WM8962_DACR_ENA                         0x0080  /* DACR_ENA */
+#define WM8962_DACR_ENA_MASK                    0x0080  /* DACR_ENA */
+#define WM8962_DACR_ENA_SHIFT                        7  /* DACR_ENA */
+#define WM8962_DACR_ENA_WIDTH                        1  /* DACR_ENA */
+#define WM8962_HPOUTL_PGA_ENA                   0x0040  /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_MASK              0x0040  /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_SHIFT                  6  /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTL_PGA_ENA_WIDTH                  1  /* HPOUTL_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA                   0x0020  /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_MASK              0x0020  /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_SHIFT                  5  /* HPOUTR_PGA_ENA */
+#define WM8962_HPOUTR_PGA_ENA_WIDTH                  1  /* HPOUTR_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA                  0x0010  /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_MASK             0x0010  /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_SHIFT                 4  /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTL_PGA_ENA_WIDTH                 1  /* SPKOUTL_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA                  0x0008  /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_MASK             0x0008  /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_SHIFT                 3  /* SPKOUTR_PGA_ENA */
+#define WM8962_SPKOUTR_PGA_ENA_WIDTH                 1  /* SPKOUTR_PGA_ENA */
+#define WM8962_HPOUTL_PGA_MUTE                  0x0002  /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_MASK             0x0002  /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_SHIFT                 1  /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTL_PGA_MUTE_WIDTH                 1  /* HPOUTL_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE                  0x0001  /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_MASK             0x0001  /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_SHIFT                 0  /* HPOUTR_PGA_MUTE */
+#define WM8962_HPOUTR_PGA_MUTE_WIDTH                 1  /* HPOUTR_PGA_MUTE */
+
+/*
+ * R27 (0x1B) - Additional Control (3)
+ */
+#define WM8962_SAMPLE_RATE_INT_MODE             0x0010  /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_MASK        0x0010  /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_SHIFT            4  /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_INT_MODE_WIDTH            1  /* SAMPLE_RATE_INT_MODE */
+#define WM8962_SAMPLE_RATE_MASK                 0x0007  /* SAMPLE_RATE - [2:0] */
+#define WM8962_SAMPLE_RATE_SHIFT                     0  /* SAMPLE_RATE - [2:0] */
+#define WM8962_SAMPLE_RATE_WIDTH                     3  /* SAMPLE_RATE - [2:0] */
+
+/*
+ * R28 (0x1C) - Anti-pop
+ */
+#define WM8962_STARTUP_BIAS_ENA                 0x0010  /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_MASK            0x0010  /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_SHIFT                4  /* STARTUP_BIAS_ENA */
+#define WM8962_STARTUP_BIAS_ENA_WIDTH                1  /* STARTUP_BIAS_ENA */
+#define WM8962_VMID_BUF_ENA                     0x0008  /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_MASK                0x0008  /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_SHIFT                    3  /* VMID_BUF_ENA */
+#define WM8962_VMID_BUF_ENA_WIDTH                    1  /* VMID_BUF_ENA */
+#define WM8962_VMID_RAMP                        0x0004  /* VMID_RAMP */
+#define WM8962_VMID_RAMP_MASK                   0x0004  /* VMID_RAMP */
+#define WM8962_VMID_RAMP_SHIFT                       2  /* VMID_RAMP */
+#define WM8962_VMID_RAMP_WIDTH                       1  /* VMID_RAMP */
+
+/*
+ * R30 (0x1E) - Clocking 3
+ */
+#define WM8962_DBCLK_DIV_MASK                   0xE000  /* DBCLK_DIV - [15:13] */
+#define WM8962_DBCLK_DIV_SHIFT                      13  /* DBCLK_DIV - [15:13] */
+#define WM8962_DBCLK_DIV_WIDTH                       3  /* DBCLK_DIV - [15:13] */
+#define WM8962_OPCLK_DIV_MASK                   0x1C00  /* OPCLK_DIV - [12:10] */
+#define WM8962_OPCLK_DIV_SHIFT                      10  /* OPCLK_DIV - [12:10] */
+#define WM8962_OPCLK_DIV_WIDTH                       3  /* OPCLK_DIV - [12:10] */
+#define WM8962_TOCLK_DIV_MASK                   0x0380  /* TOCLK_DIV - [9:7] */
+#define WM8962_TOCLK_DIV_SHIFT                       7  /* TOCLK_DIV - [9:7] */
+#define WM8962_TOCLK_DIV_WIDTH                       3  /* TOCLK_DIV - [9:7] */
+#define WM8962_F256KCLK_DIV_MASK                0x007E  /* F256KCLK_DIV - [6:1] */
+#define WM8962_F256KCLK_DIV_SHIFT                    1  /* F256KCLK_DIV - [6:1] */
+#define WM8962_F256KCLK_DIV_WIDTH                    6  /* F256KCLK_DIV - [6:1] */
+
+/*
+ * R31 (0x1F) - Input mixer control (1)
+ */
+#define WM8962_MIXINL_MUTE                      0x0008  /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_MASK                 0x0008  /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_SHIFT                     3  /* MIXINL_MUTE */
+#define WM8962_MIXINL_MUTE_WIDTH                     1  /* MIXINL_MUTE */
+#define WM8962_MIXINR_MUTE                      0x0004  /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_MASK                 0x0004  /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_SHIFT                     2  /* MIXINR_MUTE */
+#define WM8962_MIXINR_MUTE_WIDTH                     1  /* MIXINR_MUTE */
+#define WM8962_MIXINL_ENA                       0x0002  /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_MASK                  0x0002  /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_SHIFT                      1  /* MIXINL_ENA */
+#define WM8962_MIXINL_ENA_WIDTH                      1  /* MIXINL_ENA */
+#define WM8962_MIXINR_ENA                       0x0001  /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_MASK                  0x0001  /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_SHIFT                      0  /* MIXINR_ENA */
+#define WM8962_MIXINR_ENA_WIDTH                      1  /* MIXINR_ENA */
+
+/*
+ * R32 (0x20) - Left input mixer volume
+ */
+#define WM8962_IN2L_MIXINL_VOL_MASK             0x01C0  /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_IN2L_MIXINL_VOL_SHIFT                 6  /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_IN2L_MIXINL_VOL_WIDTH                 3  /* IN2L_MIXINL_VOL - [8:6] */
+#define WM8962_INPGAL_MIXINL_VOL_MASK           0x0038  /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_INPGAL_MIXINL_VOL_SHIFT               3  /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_INPGAL_MIXINL_VOL_WIDTH               3  /* INPGAL_MIXINL_VOL - [5:3] */
+#define WM8962_IN3L_MIXINL_VOL_MASK             0x0007  /* IN3L_MIXINL_VOL - [2:0] */
+#define WM8962_IN3L_MIXINL_VOL_SHIFT                 0  /* IN3L_MIXINL_VOL - [2:0] */
+#define WM8962_IN3L_MIXINL_VOL_WIDTH                 3  /* IN3L_MIXINL_VOL - [2:0] */
+
+/*
+ * R33 (0x21) - Right input mixer volume
+ */
+#define WM8962_IN2R_MIXINR_VOL_MASK             0x01C0  /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_IN2R_MIXINR_VOL_SHIFT                 6  /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_IN2R_MIXINR_VOL_WIDTH                 3  /* IN2R_MIXINR_VOL - [8:6] */
+#define WM8962_INPGAR_MIXINR_VOL_MASK           0x0038  /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_INPGAR_MIXINR_VOL_SHIFT               3  /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_INPGAR_MIXINR_VOL_WIDTH               3  /* INPGAR_MIXINR_VOL - [5:3] */
+#define WM8962_IN3R_MIXINR_VOL_MASK             0x0007  /* IN3R_MIXINR_VOL - [2:0] */
+#define WM8962_IN3R_MIXINR_VOL_SHIFT                 0  /* IN3R_MIXINR_VOL - [2:0] */
+#define WM8962_IN3R_MIXINR_VOL_WIDTH                 3  /* IN3R_MIXINR_VOL - [2:0] */
+
+/*
+ * R34 (0x22) - Input mixer control (2)
+ */
+#define WM8962_IN2L_TO_MIXINL                   0x0020  /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_MASK              0x0020  /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_SHIFT                  5  /* IN2L_TO_MIXINL */
+#define WM8962_IN2L_TO_MIXINL_WIDTH                  1  /* IN2L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL                   0x0010  /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_MASK              0x0010  /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_SHIFT                  4  /* IN3L_TO_MIXINL */
+#define WM8962_IN3L_TO_MIXINL_WIDTH                  1  /* IN3L_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL                 0x0008  /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_MASK            0x0008  /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_SHIFT                3  /* INPGAL_TO_MIXINL */
+#define WM8962_INPGAL_TO_MIXINL_WIDTH                1  /* INPGAL_TO_MIXINL */
+#define WM8962_IN2R_TO_MIXINR                   0x0004  /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_MASK              0x0004  /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_SHIFT                  2  /* IN2R_TO_MIXINR */
+#define WM8962_IN2R_TO_MIXINR_WIDTH                  1  /* IN2R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR                   0x0002  /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_MASK              0x0002  /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_SHIFT                  1  /* IN3R_TO_MIXINR */
+#define WM8962_IN3R_TO_MIXINR_WIDTH                  1  /* IN3R_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR                 0x0001  /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_MASK            0x0001  /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_SHIFT                0  /* INPGAR_TO_MIXINR */
+#define WM8962_INPGAR_TO_MIXINR_WIDTH                1  /* INPGAR_TO_MIXINR */
+
+/*
+ * R35 (0x23) - Input bias control
+ */
+#define WM8962_MIXIN_BIAS_MASK                  0x0038  /* MIXIN_BIAS - [5:3] */
+#define WM8962_MIXIN_BIAS_SHIFT                      3  /* MIXIN_BIAS - [5:3] */
+#define WM8962_MIXIN_BIAS_WIDTH                      3  /* MIXIN_BIAS - [5:3] */
+#define WM8962_INPGA_BIAS_MASK                  0x0007  /* INPGA_BIAS - [2:0] */
+#define WM8962_INPGA_BIAS_SHIFT                      0  /* INPGA_BIAS - [2:0] */
+#define WM8962_INPGA_BIAS_WIDTH                      3  /* INPGA_BIAS - [2:0] */
+
+/*
+ * R37 (0x25) - Left input PGA control
+ */
+#define WM8962_INPGAL_ENA                       0x0010  /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_MASK                  0x0010  /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_SHIFT                      4  /* INPGAL_ENA */
+#define WM8962_INPGAL_ENA_WIDTH                      1  /* INPGAL_ENA */
+#define WM8962_IN1L_TO_INPGAL                   0x0008  /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_MASK              0x0008  /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_SHIFT                  3  /* IN1L_TO_INPGAL */
+#define WM8962_IN1L_TO_INPGAL_WIDTH                  1  /* IN1L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL                   0x0004  /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_MASK              0x0004  /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_SHIFT                  2  /* IN2L_TO_INPGAL */
+#define WM8962_IN2L_TO_INPGAL_WIDTH                  1  /* IN2L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL                   0x0002  /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_MASK              0x0002  /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_SHIFT                  1  /* IN3L_TO_INPGAL */
+#define WM8962_IN3L_TO_INPGAL_WIDTH                  1  /* IN3L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL                   0x0001  /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_MASK              0x0001  /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_SHIFT                  0  /* IN4L_TO_INPGAL */
+#define WM8962_IN4L_TO_INPGAL_WIDTH                  1  /* IN4L_TO_INPGAL */
+
+/*
+ * R38 (0x26) - Right input PGA control
+ */
+#define WM8962_INPGAR_ENA                       0x0010  /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_MASK                  0x0010  /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_SHIFT                      4  /* INPGAR_ENA */
+#define WM8962_INPGAR_ENA_WIDTH                      1  /* INPGAR_ENA */
+#define WM8962_IN1R_TO_INPGAR                   0x0008  /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_MASK              0x0008  /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_SHIFT                  3  /* IN1R_TO_INPGAR */
+#define WM8962_IN1R_TO_INPGAR_WIDTH                  1  /* IN1R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR                   0x0004  /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_MASK              0x0004  /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_SHIFT                  2  /* IN2R_TO_INPGAR */
+#define WM8962_IN2R_TO_INPGAR_WIDTH                  1  /* IN2R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR                   0x0002  /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_MASK              0x0002  /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_SHIFT                  1  /* IN3R_TO_INPGAR */
+#define WM8962_IN3R_TO_INPGAR_WIDTH                  1  /* IN3R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR                   0x0001  /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_MASK              0x0001  /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_SHIFT                  0  /* IN4R_TO_INPGAR */
+#define WM8962_IN4R_TO_INPGAR_WIDTH                  1  /* IN4R_TO_INPGAR */
+
+/*
+ * R40 (0x28) - SPKOUTL volume
+ */
+#define WM8962_SPKOUT_VU                        0x0100  /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_MASK                   0x0100  /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_SHIFT                       8  /* SPKOUT_VU */
+#define WM8962_SPKOUT_VU_WIDTH                       1  /* SPKOUT_VU */
+#define WM8962_SPKOUTL_ZC                       0x0080  /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_MASK                  0x0080  /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_SHIFT                      7  /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_ZC_WIDTH                      1  /* SPKOUTL_ZC */
+#define WM8962_SPKOUTL_VOL_MASK                 0x007F  /* SPKOUTL_VOL - [6:0] */
+#define WM8962_SPKOUTL_VOL_SHIFT                     0  /* SPKOUTL_VOL - [6:0] */
+#define WM8962_SPKOUTL_VOL_WIDTH                     7  /* SPKOUTL_VOL - [6:0] */
+
+/*
+ * R41 (0x29) - SPKOUTR volume
+ */
+#define WM8962_SPKOUTR_ZC                       0x0080  /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_MASK                  0x0080  /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_SHIFT                      7  /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_ZC_WIDTH                      1  /* SPKOUTR_ZC */
+#define WM8962_SPKOUTR_VOL_MASK                 0x007F  /* SPKOUTR_VOL - [6:0] */
+#define WM8962_SPKOUTR_VOL_SHIFT                     0  /* SPKOUTR_VOL - [6:0] */
+#define WM8962_SPKOUTR_VOL_WIDTH                     7  /* SPKOUTR_VOL - [6:0] */
+
+/*
+ * R47 (0x2F) - Thermal Shutdown Status
+ */
+#define WM8962_TEMP_ERR_HP                      0x0008  /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_MASK                 0x0008  /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_SHIFT                     3  /* TEMP_ERR_HP */
+#define WM8962_TEMP_ERR_HP_WIDTH                     1  /* TEMP_ERR_HP */
+#define WM8962_TEMP_WARN_HP                     0x0004  /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_MASK                0x0004  /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_SHIFT                    2  /* TEMP_WARN_HP */
+#define WM8962_TEMP_WARN_HP_WIDTH                    1  /* TEMP_WARN_HP */
+#define WM8962_TEMP_ERR_SPK                     0x0002  /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_MASK                0x0002  /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_SHIFT                    1  /* TEMP_ERR_SPK */
+#define WM8962_TEMP_ERR_SPK_WIDTH                    1  /* TEMP_ERR_SPK */
+#define WM8962_TEMP_WARN_SPK                    0x0001  /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_MASK               0x0001  /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_SHIFT                   0  /* TEMP_WARN_SPK */
+#define WM8962_TEMP_WARN_SPK_WIDTH                   1  /* TEMP_WARN_SPK */
+
+/*
+ * R48 (0x30) - Additional Control (4)
+ */
+#define WM8962_MICDET_THR_MASK                  0x7000  /* MICDET_THR - [14:12] */
+#define WM8962_MICDET_THR_SHIFT                     12  /* MICDET_THR - [14:12] */
+#define WM8962_MICDET_THR_WIDTH                      3  /* MICDET_THR - [14:12] */
+#define WM8962_MICSHORT_THR_MASK                0x0C00  /* MICSHORT_THR - [11:10] */
+#define WM8962_MICSHORT_THR_SHIFT                   10  /* MICSHORT_THR - [11:10] */
+#define WM8962_MICSHORT_THR_WIDTH                    2  /* MICSHORT_THR - [11:10] */
+#define WM8962_MICDET_ENA                       0x0200  /* MICDET_ENA */
+#define WM8962_MICDET_ENA_MASK                  0x0200  /* MICDET_ENA */
+#define WM8962_MICDET_ENA_SHIFT                      9  /* MICDET_ENA */
+#define WM8962_MICDET_ENA_WIDTH                      1  /* MICDET_ENA */
+#define WM8962_MICDET_STS                       0x0080  /* MICDET_STS */
+#define WM8962_MICDET_STS_MASK                  0x0080  /* MICDET_STS */
+#define WM8962_MICDET_STS_SHIFT                      7  /* MICDET_STS */
+#define WM8962_MICDET_STS_WIDTH                      1  /* MICDET_STS */
+#define WM8962_MICSHORT_STS                     0x0040  /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_MASK                0x0040  /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_SHIFT                    6  /* MICSHORT_STS */
+#define WM8962_MICSHORT_STS_WIDTH                    1  /* MICSHORT_STS */
+#define WM8962_TEMP_ENA_HP                      0x0004  /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_MASK                 0x0004  /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_SHIFT                     2  /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_HP_WIDTH                     1  /* TEMP_ENA_HP */
+#define WM8962_TEMP_ENA_SPK                     0x0002  /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_MASK                0x0002  /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_SHIFT                    1  /* TEMP_ENA_SPK */
+#define WM8962_TEMP_ENA_SPK_WIDTH                    1  /* TEMP_ENA_SPK */
+#define WM8962_MICBIAS_LVL                      0x0001  /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_MASK                 0x0001  /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_SHIFT                     0  /* MICBIAS_LVL */
+#define WM8962_MICBIAS_LVL_WIDTH                     1  /* MICBIAS_LVL */
+
+/*
+ * R49 (0x31) - Class D Control 1
+ */
+#define WM8962_SPKOUTR_ENA                      0x0080  /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_MASK                 0x0080  /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_SHIFT                     7  /* SPKOUTR_ENA */
+#define WM8962_SPKOUTR_ENA_WIDTH                     1  /* SPKOUTR_ENA */
+#define WM8962_SPKOUTL_ENA                      0x0040  /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_MASK                 0x0040  /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_SHIFT                     6  /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_ENA_WIDTH                     1  /* SPKOUTL_ENA */
+#define WM8962_SPKOUTL_PGA_MUTE                 0x0002  /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_MASK            0x0002  /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_SHIFT                1  /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTL_PGA_MUTE_WIDTH                1  /* SPKOUTL_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE                 0x0001  /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_MASK            0x0001  /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_SHIFT                0  /* SPKOUTR_PGA_MUTE */
+#define WM8962_SPKOUTR_PGA_MUTE_WIDTH                1  /* SPKOUTR_PGA_MUTE */
+
+/*
+ * R51 (0x33) - Class D Control 2
+ */
+#define WM8962_SPK_MONO                         0x0040  /* SPK_MONO */
+#define WM8962_SPK_MONO_MASK                    0x0040  /* SPK_MONO */
+#define WM8962_SPK_MONO_SHIFT                        6  /* SPK_MONO */
+#define WM8962_SPK_MONO_WIDTH                        1  /* SPK_MONO */
+#define WM8962_CLASSD_VOL_MASK                  0x0007  /* CLASSD_VOL - [2:0] */
+#define WM8962_CLASSD_VOL_SHIFT                      0  /* CLASSD_VOL - [2:0] */
+#define WM8962_CLASSD_VOL_WIDTH                      3  /* CLASSD_VOL - [2:0] */
+
+/*
+ * R56 (0x38) - Clocking 4
+ */
+#define WM8962_SYSCLK_RATE_MASK                 0x001E  /* SYSCLK_RATE - [4:1] */
+#define WM8962_SYSCLK_RATE_SHIFT                     1  /* SYSCLK_RATE - [4:1] */
+#define WM8962_SYSCLK_RATE_WIDTH                     4  /* SYSCLK_RATE - [4:1] */
+
+/*
+ * R57 (0x39) - DAC DSP Mixing (1)
+ */
+#define WM8962_DAC_MONOMIX                      0x0200  /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_MASK                 0x0200  /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_SHIFT                     9  /* DAC_MONOMIX */
+#define WM8962_DAC_MONOMIX_WIDTH                     1  /* DAC_MONOMIX */
+#define WM8962_ADCR_DAC_SVOL_MASK               0x00F0  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADCR_DAC_SVOL_SHIFT                   4  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADCR_DAC_SVOL_WIDTH                   4  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8962_ADC_TO_DACR_MASK                 0x000C  /* ADC_TO_DACR - [3:2] */
+#define WM8962_ADC_TO_DACR_SHIFT                     2  /* ADC_TO_DACR - [3:2] */
+#define WM8962_ADC_TO_DACR_WIDTH                     2  /* ADC_TO_DACR - [3:2] */
+
+/*
+ * R58 (0x3A) - DAC DSP Mixing (2)
+ */
+#define WM8962_ADCL_DAC_SVOL_MASK               0x00F0  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADCL_DAC_SVOL_SHIFT                   4  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADCL_DAC_SVOL_WIDTH                   4  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8962_ADC_TO_DACL_MASK                 0x000C  /* ADC_TO_DACL - [3:2] */
+#define WM8962_ADC_TO_DACL_SHIFT                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8962_ADC_TO_DACL_WIDTH                     2  /* ADC_TO_DACL - [3:2] */
+
+/*
+ * R60 (0x3C) - DC Servo 0
+ */
+#define WM8962_INL_DCS_ENA                      0x0080  /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_MASK                 0x0080  /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_SHIFT                     7  /* INL_DCS_ENA */
+#define WM8962_INL_DCS_ENA_WIDTH                     1  /* INL_DCS_ENA */
+#define WM8962_INL_DCS_STARTUP                  0x0040  /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_MASK             0x0040  /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_SHIFT                 6  /* INL_DCS_STARTUP */
+#define WM8962_INL_DCS_STARTUP_WIDTH                 1  /* INL_DCS_STARTUP */
+#define WM8962_INR_DCS_ENA                      0x0008  /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_MASK                 0x0008  /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_SHIFT                     3  /* INR_DCS_ENA */
+#define WM8962_INR_DCS_ENA_WIDTH                     1  /* INR_DCS_ENA */
+#define WM8962_INR_DCS_STARTUP                  0x0004  /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_MASK             0x0004  /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_SHIFT                 2  /* INR_DCS_STARTUP */
+#define WM8962_INR_DCS_STARTUP_WIDTH                 1  /* INR_DCS_STARTUP */
+
+/*
+ * R61 (0x3D) - DC Servo 1
+ */
+#define WM8962_HP1L_DCS_ENA                     0x0080  /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_MASK                0x0080  /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_SHIFT                    7  /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_ENA_WIDTH                    1  /* HP1L_DCS_ENA */
+#define WM8962_HP1L_DCS_STARTUP                 0x0040  /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_MASK            0x0040  /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_SHIFT                6  /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_STARTUP_WIDTH                1  /* HP1L_DCS_STARTUP */
+#define WM8962_HP1L_DCS_SYNC                    0x0010  /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_MASK               0x0010  /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_SHIFT                   4  /* HP1L_DCS_SYNC */
+#define WM8962_HP1L_DCS_SYNC_WIDTH                   1  /* HP1L_DCS_SYNC */
+#define WM8962_HP1R_DCS_ENA                     0x0008  /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_MASK                0x0008  /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_SHIFT                    3  /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_ENA_WIDTH                    1  /* HP1R_DCS_ENA */
+#define WM8962_HP1R_DCS_STARTUP                 0x0004  /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_MASK            0x0004  /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_SHIFT                2  /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_STARTUP_WIDTH                1  /* HP1R_DCS_STARTUP */
+#define WM8962_HP1R_DCS_SYNC                    0x0001  /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_MASK               0x0001  /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_SHIFT                   0  /* HP1R_DCS_SYNC */
+#define WM8962_HP1R_DCS_SYNC_WIDTH                   1  /* HP1R_DCS_SYNC */
+
+/*
+ * R64 (0x40) - DC Servo 4
+ */
+#define WM8962_HP1_DCS_SYNC_STEPS_MASK          0x3F80  /* HP1_DCS_SYNC_STEPS - [13:7] */
+#define WM8962_HP1_DCS_SYNC_STEPS_SHIFT              7  /* HP1_DCS_SYNC_STEPS - [13:7] */
+#define WM8962_HP1_DCS_SYNC_STEPS_WIDTH              7  /* HP1_DCS_SYNC_STEPS - [13:7] */
+
+/*
+ * R66 (0x42) - DC Servo 6
+ */
+#define WM8962_DCS_STARTUP_DONE_INL             0x0400  /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_MASK        0x0400  /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_SHIFT           10  /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INL_WIDTH            1  /* DCS_STARTUP_DONE_INL */
+#define WM8962_DCS_STARTUP_DONE_INR             0x0200  /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_MASK        0x0200  /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_SHIFT            9  /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_INR_WIDTH            1  /* DCS_STARTUP_DONE_INR */
+#define WM8962_DCS_STARTUP_DONE_HP1L            0x0100  /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_MASK       0x0100  /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_SHIFT           8  /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1L_WIDTH           1  /* DCS_STARTUP_DONE_HP1L */
+#define WM8962_DCS_STARTUP_DONE_HP1R            0x0080  /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_MASK       0x0080  /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_SHIFT           7  /* DCS_STARTUP_DONE_HP1R */
+#define WM8962_DCS_STARTUP_DONE_HP1R_WIDTH           1  /* DCS_STARTUP_DONE_HP1R */
+
+/*
+ * R68 (0x44) - Analogue PGA Bias
+ */
+#define WM8962_HP_PGAS_BIAS_MASK                0x0007  /* HP_PGAS_BIAS - [2:0] */
+#define WM8962_HP_PGAS_BIAS_SHIFT                    0  /* HP_PGAS_BIAS - [2:0] */
+#define WM8962_HP_PGAS_BIAS_WIDTH                    3  /* HP_PGAS_BIAS - [2:0] */
+
+/*
+ * R69 (0x45) - Analogue HP 0
+ */
+#define WM8962_HP1L_RMV_SHORT                   0x0080  /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_MASK              0x0080  /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_SHIFT                  7  /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_RMV_SHORT_WIDTH                  1  /* HP1L_RMV_SHORT */
+#define WM8962_HP1L_ENA_OUTP                    0x0040  /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_MASK               0x0040  /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_SHIFT                   6  /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_OUTP_WIDTH                   1  /* HP1L_ENA_OUTP */
+#define WM8962_HP1L_ENA_DLY                     0x0020  /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_MASK                0x0020  /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_SHIFT                    5  /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA_DLY_WIDTH                    1  /* HP1L_ENA_DLY */
+#define WM8962_HP1L_ENA                         0x0010  /* HP1L_ENA */
+#define WM8962_HP1L_ENA_MASK                    0x0010  /* HP1L_ENA */
+#define WM8962_HP1L_ENA_SHIFT                        4  /* HP1L_ENA */
+#define WM8962_HP1L_ENA_WIDTH                        1  /* HP1L_ENA */
+#define WM8962_HP1R_RMV_SHORT                   0x0008  /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_MASK              0x0008  /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_SHIFT                  3  /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_RMV_SHORT_WIDTH                  1  /* HP1R_RMV_SHORT */
+#define WM8962_HP1R_ENA_OUTP                    0x0004  /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_MASK               0x0004  /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_SHIFT                   2  /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_OUTP_WIDTH                   1  /* HP1R_ENA_OUTP */
+#define WM8962_HP1R_ENA_DLY                     0x0002  /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_MASK                0x0002  /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_SHIFT                    1  /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA_DLY_WIDTH                    1  /* HP1R_ENA_DLY */
+#define WM8962_HP1R_ENA                         0x0001  /* HP1R_ENA */
+#define WM8962_HP1R_ENA_MASK                    0x0001  /* HP1R_ENA */
+#define WM8962_HP1R_ENA_SHIFT                        0  /* HP1R_ENA */
+#define WM8962_HP1R_ENA_WIDTH                        1  /* HP1R_ENA */
+
+/*
+ * R71 (0x47) - Analogue HP 2
+ */
+#define WM8962_HP1L_VOL_MASK                    0x01C0  /* HP1L_VOL - [8:6] */
+#define WM8962_HP1L_VOL_SHIFT                        6  /* HP1L_VOL - [8:6] */
+#define WM8962_HP1L_VOL_WIDTH                        3  /* HP1L_VOL - [8:6] */
+#define WM8962_HP1R_VOL_MASK                    0x0038  /* HP1R_VOL - [5:3] */
+#define WM8962_HP1R_VOL_SHIFT                        3  /* HP1R_VOL - [5:3] */
+#define WM8962_HP1R_VOL_WIDTH                        3  /* HP1R_VOL - [5:3] */
+#define WM8962_HP_BIAS_BOOST_MASK               0x0007  /* HP_BIAS_BOOST - [2:0] */
+#define WM8962_HP_BIAS_BOOST_SHIFT                   0  /* HP_BIAS_BOOST - [2:0] */
+#define WM8962_HP_BIAS_BOOST_WIDTH                   3  /* HP_BIAS_BOOST - [2:0] */
+
+/*
+ * R72 (0x48) - Charge Pump 1
+ */
+#define WM8962_CP_ENA                           0x0001  /* CP_ENA */
+#define WM8962_CP_ENA_MASK                      0x0001  /* CP_ENA */
+#define WM8962_CP_ENA_SHIFT                          0  /* CP_ENA */
+#define WM8962_CP_ENA_WIDTH                          1  /* CP_ENA */
+
+/*
+ * R82 (0x52) - Charge Pump B
+ */
+#define WM8962_CP_DYN_PWR                       0x0001  /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_MASK                  0x0001  /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_SHIFT                      0  /* CP_DYN_PWR */
+#define WM8962_CP_DYN_PWR_WIDTH                      1  /* CP_DYN_PWR */
+
+/*
+ * R87 (0x57) - Write Sequencer Control 1
+ */
+#define WM8962_WSEQ_AUTOSEQ_ENA                 0x0080  /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_MASK            0x0080  /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_SHIFT                7  /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_AUTOSEQ_ENA_WIDTH                1  /* WSEQ_AUTOSEQ_ENA */
+#define WM8962_WSEQ_ENA                         0x0020  /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_MASK                    0x0020  /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_SHIFT                        5  /* WSEQ_ENA */
+#define WM8962_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
+
+/*
+ * R90 (0x5A) - Write Sequencer Control 2
+ */
+#define WM8962_WSEQ_ABORT                       0x0100  /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_MASK                  0x0100  /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_SHIFT                      8  /* WSEQ_ABORT */
+#define WM8962_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
+#define WM8962_WSEQ_START                       0x0080  /* WSEQ_START */
+#define WM8962_WSEQ_START_MASK                  0x0080  /* WSEQ_START */
+#define WM8962_WSEQ_START_SHIFT                      7  /* WSEQ_START */
+#define WM8962_WSEQ_START_WIDTH                      1  /* WSEQ_START */
+#define WM8962_WSEQ_START_INDEX_MASK            0x007F  /* WSEQ_START_INDEX - [6:0] */
+#define WM8962_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [6:0] */
+#define WM8962_WSEQ_START_INDEX_WIDTH                7  /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R93 (0x5D) - Write Sequencer Control 3
+ */
+#define WM8962_WSEQ_CURRENT_INDEX_MASK          0x03F8  /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_CURRENT_INDEX_SHIFT              3  /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_CURRENT_INDEX_WIDTH              7  /* WSEQ_CURRENT_INDEX - [9:3] */
+#define WM8962_WSEQ_BUSY                        0x0001  /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_MASK                   0x0001  /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_SHIFT                       0  /* WSEQ_BUSY */
+#define WM8962_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
+
+/*
+ * R94 (0x5E) - Control Interface
+ */
+#define WM8962_SPI_CONTRD                       0x0040  /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_MASK                  0x0040  /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_SHIFT                      6  /* SPI_CONTRD */
+#define WM8962_SPI_CONTRD_WIDTH                      1  /* SPI_CONTRD */
+#define WM8962_SPI_4WIRE                        0x0020  /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_MASK                   0x0020  /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_SHIFT                       5  /* SPI_4WIRE */
+#define WM8962_SPI_4WIRE_WIDTH                       1  /* SPI_4WIRE */
+#define WM8962_SPI_CFG                          0x0010  /* SPI_CFG */
+#define WM8962_SPI_CFG_MASK                     0x0010  /* SPI_CFG */
+#define WM8962_SPI_CFG_SHIFT                         4  /* SPI_CFG */
+#define WM8962_SPI_CFG_WIDTH                         1  /* SPI_CFG */
+
+/*
+ * R99 (0x63) - Mixer Enables
+ */
+#define WM8962_HPMIXL_ENA                       0x0008  /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_MASK                  0x0008  /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_SHIFT                      3  /* HPMIXL_ENA */
+#define WM8962_HPMIXL_ENA_WIDTH                      1  /* HPMIXL_ENA */
+#define WM8962_HPMIXR_ENA                       0x0004  /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_MASK                  0x0004  /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_SHIFT                      2  /* HPMIXR_ENA */
+#define WM8962_HPMIXR_ENA_WIDTH                      1  /* HPMIXR_ENA */
+#define WM8962_SPKMIXL_ENA                      0x0002  /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_MASK                 0x0002  /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_SHIFT                     1  /* SPKMIXL_ENA */
+#define WM8962_SPKMIXL_ENA_WIDTH                     1  /* SPKMIXL_ENA */
+#define WM8962_SPKMIXR_ENA                      0x0001  /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_MASK                 0x0001  /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_SHIFT                     0  /* SPKMIXR_ENA */
+#define WM8962_SPKMIXR_ENA_WIDTH                     1  /* SPKMIXR_ENA */
+
+/*
+ * R100 (0x64) - Headphone Mixer (1)
+ */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA             0x0080  /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_MASK        0x0080  /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_SHIFT            7  /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_HPMIXL_TO_HPOUTL_PGA_WIDTH            1  /* HPMIXL_TO_HPOUTL_PGA */
+#define WM8962_DACL_TO_HPMIXL                   0x0020  /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_MASK              0x0020  /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_SHIFT                  5  /* DACL_TO_HPMIXL */
+#define WM8962_DACL_TO_HPMIXL_WIDTH                  1  /* DACL_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL                   0x0010  /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_MASK              0x0010  /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_SHIFT                  4  /* DACR_TO_HPMIXL */
+#define WM8962_DACR_TO_HPMIXL_WIDTH                  1  /* DACR_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL                 0x0008  /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_MASK            0x0008  /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_SHIFT                3  /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINL_TO_HPMIXL_WIDTH                1  /* MIXINL_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL                 0x0004  /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_MASK            0x0004  /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_SHIFT                2  /* MIXINR_TO_HPMIXL */
+#define WM8962_MIXINR_TO_HPMIXL_WIDTH                1  /* MIXINR_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL                   0x0002  /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_MASK              0x0002  /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_SHIFT                  1  /* IN4L_TO_HPMIXL */
+#define WM8962_IN4L_TO_HPMIXL_WIDTH                  1  /* IN4L_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL                   0x0001  /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_MASK              0x0001  /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_SHIFT                  0  /* IN4R_TO_HPMIXL */
+#define WM8962_IN4R_TO_HPMIXL_WIDTH                  1  /* IN4R_TO_HPMIXL */
+
+/*
+ * R101 (0x65) - Headphone Mixer (2)
+ */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA             0x0080  /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_MASK        0x0080  /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_SHIFT            7  /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_HPMIXR_TO_HPOUTR_PGA_WIDTH            1  /* HPMIXR_TO_HPOUTR_PGA */
+#define WM8962_DACL_TO_HPMIXR                   0x0020  /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_MASK              0x0020  /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_SHIFT                  5  /* DACL_TO_HPMIXR */
+#define WM8962_DACL_TO_HPMIXR_WIDTH                  1  /* DACL_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR                   0x0010  /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_MASK              0x0010  /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_SHIFT                  4  /* DACR_TO_HPMIXR */
+#define WM8962_DACR_TO_HPMIXR_WIDTH                  1  /* DACR_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR                 0x0008  /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_MASK            0x0008  /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_SHIFT                3  /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINL_TO_HPMIXR_WIDTH                1  /* MIXINL_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR                 0x0004  /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_MASK            0x0004  /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_SHIFT                2  /* MIXINR_TO_HPMIXR */
+#define WM8962_MIXINR_TO_HPMIXR_WIDTH                1  /* MIXINR_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR                   0x0002  /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_MASK              0x0002  /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_SHIFT                  1  /* IN4L_TO_HPMIXR */
+#define WM8962_IN4L_TO_HPMIXR_WIDTH                  1  /* IN4L_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR                   0x0001  /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_MASK              0x0001  /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_SHIFT                  0  /* IN4R_TO_HPMIXR */
+#define WM8962_IN4R_TO_HPMIXR_WIDTH                  1  /* IN4R_TO_HPMIXR */
+
+/*
+ * R102 (0x66) - Headphone Mixer (3)
+ */
+#define WM8962_HPMIXL_MUTE                      0x0100  /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_MASK                 0x0100  /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_SHIFT                     8  /* HPMIXL_MUTE */
+#define WM8962_HPMIXL_MUTE_WIDTH                     1  /* HPMIXL_MUTE */
+#define WM8962_MIXINL_HPMIXL_VOL                0x0080  /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_MASK           0x0080  /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_SHIFT               7  /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINL_HPMIXL_VOL_WIDTH               1  /* MIXINL_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL                0x0040  /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_MASK           0x0040  /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_SHIFT               6  /* MIXINR_HPMIXL_VOL */
+#define WM8962_MIXINR_HPMIXL_VOL_WIDTH               1  /* MIXINR_HPMIXL_VOL */
+#define WM8962_IN4L_HPMIXL_VOL_MASK             0x0038  /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXL_VOL_SHIFT                 3  /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXL_VOL_WIDTH                 3  /* IN4L_HPMIXL_VOL - [5:3] */
+#define WM8962_IN4R_HPMIXL_VOL_MASK             0x0007  /* IN4R_HPMIXL_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXL_VOL_SHIFT                 0  /* IN4R_HPMIXL_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXL_VOL_WIDTH                 3  /* IN4R_HPMIXL_VOL - [2:0] */
+
+/*
+ * R103 (0x67) - Headphone Mixer (4)
+ */
+#define WM8962_HPMIXR_MUTE                      0x0100  /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_MASK                 0x0100  /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_SHIFT                     8  /* HPMIXR_MUTE */
+#define WM8962_HPMIXR_MUTE_WIDTH                     1  /* HPMIXR_MUTE */
+#define WM8962_MIXINL_HPMIXR_VOL                0x0080  /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_MASK           0x0080  /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_SHIFT               7  /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINL_HPMIXR_VOL_WIDTH               1  /* MIXINL_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL                0x0040  /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_MASK           0x0040  /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_SHIFT               6  /* MIXINR_HPMIXR_VOL */
+#define WM8962_MIXINR_HPMIXR_VOL_WIDTH               1  /* MIXINR_HPMIXR_VOL */
+#define WM8962_IN4L_HPMIXR_VOL_MASK             0x0038  /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXR_VOL_SHIFT                 3  /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4L_HPMIXR_VOL_WIDTH                 3  /* IN4L_HPMIXR_VOL - [5:3] */
+#define WM8962_IN4R_HPMIXR_VOL_MASK             0x0007  /* IN4R_HPMIXR_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXR_VOL_SHIFT                 0  /* IN4R_HPMIXR_VOL - [2:0] */
+#define WM8962_IN4R_HPMIXR_VOL_WIDTH                 3  /* IN4R_HPMIXR_VOL - [2:0] */
+
+/*
+ * R105 (0x69) - Speaker Mixer (1)
+ */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA           0x0080  /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_MASK      0x0080  /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_SHIFT          7  /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_WIDTH          1  /* SPKMIXL_TO_SPKOUTL_PGA */
+#define WM8962_DACL_TO_SPKMIXL                  0x0020  /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_MASK             0x0020  /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_SHIFT                 5  /* DACL_TO_SPKMIXL */
+#define WM8962_DACL_TO_SPKMIXL_WIDTH                 1  /* DACL_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL                  0x0010  /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_MASK             0x0010  /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_SHIFT                 4  /* DACR_TO_SPKMIXL */
+#define WM8962_DACR_TO_SPKMIXL_WIDTH                 1  /* DACR_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL                0x0008  /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_MASK           0x0008  /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_SHIFT               3  /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINL_TO_SPKMIXL_WIDTH               1  /* MIXINL_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL                0x0004  /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_MASK           0x0004  /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_SHIFT               2  /* MIXINR_TO_SPKMIXL */
+#define WM8962_MIXINR_TO_SPKMIXL_WIDTH               1  /* MIXINR_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL                  0x0002  /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_MASK             0x0002  /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_SHIFT                 1  /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4L_TO_SPKMIXL_WIDTH                 1  /* IN4L_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL                  0x0001  /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_MASK             0x0001  /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_SHIFT                 0  /* IN4R_TO_SPKMIXL */
+#define WM8962_IN4R_TO_SPKMIXL_WIDTH                 1  /* IN4R_TO_SPKMIXL */
+
+/*
+ * R106 (0x6A) - Speaker Mixer (2)
+ */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA           0x0080  /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_MASK      0x0080  /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_SHIFT          7  /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_WIDTH          1  /* SPKMIXR_TO_SPKOUTR_PGA */
+#define WM8962_DACL_TO_SPKMIXR                  0x0020  /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_MASK             0x0020  /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_SHIFT                 5  /* DACL_TO_SPKMIXR */
+#define WM8962_DACL_TO_SPKMIXR_WIDTH                 1  /* DACL_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR                  0x0010  /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_MASK             0x0010  /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_SHIFT                 4  /* DACR_TO_SPKMIXR */
+#define WM8962_DACR_TO_SPKMIXR_WIDTH                 1  /* DACR_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR                0x0008  /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_MASK           0x0008  /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_SHIFT               3  /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINL_TO_SPKMIXR_WIDTH               1  /* MIXINL_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR                0x0004  /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_MASK           0x0004  /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_SHIFT               2  /* MIXINR_TO_SPKMIXR */
+#define WM8962_MIXINR_TO_SPKMIXR_WIDTH               1  /* MIXINR_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR                  0x0002  /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_MASK             0x0002  /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_SHIFT                 1  /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4L_TO_SPKMIXR_WIDTH                 1  /* IN4L_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR                  0x0001  /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_MASK             0x0001  /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_SHIFT                 0  /* IN4R_TO_SPKMIXR */
+#define WM8962_IN4R_TO_SPKMIXR_WIDTH                 1  /* IN4R_TO_SPKMIXR */
+
+/*
+ * R107 (0x6B) - Speaker Mixer (3)
+ */
+#define WM8962_SPKMIXL_MUTE                     0x0100  /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_MASK                0x0100  /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_SHIFT                    8  /* SPKMIXL_MUTE */
+#define WM8962_SPKMIXL_MUTE_WIDTH                    1  /* SPKMIXL_MUTE */
+#define WM8962_MIXINL_SPKMIXL_VOL               0x0080  /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_MASK          0x0080  /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_SHIFT              7  /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINL_SPKMIXL_VOL_WIDTH              1  /* MIXINL_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL               0x0040  /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_MASK          0x0040  /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_SHIFT              6  /* MIXINR_SPKMIXL_VOL */
+#define WM8962_MIXINR_SPKMIXL_VOL_WIDTH              1  /* MIXINR_SPKMIXL_VOL */
+#define WM8962_IN4L_SPKMIXL_VOL_MASK            0x0038  /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXL_VOL_SHIFT                3  /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXL_VOL_WIDTH                3  /* IN4L_SPKMIXL_VOL - [5:3] */
+#define WM8962_IN4R_SPKMIXL_VOL_MASK            0x0007  /* IN4R_SPKMIXL_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXL_VOL_SHIFT                0  /* IN4R_SPKMIXL_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXL_VOL_WIDTH                3  /* IN4R_SPKMIXL_VOL - [2:0] */
+
+/*
+ * R108 (0x6C) - Speaker Mixer (4)
+ */
+#define WM8962_SPKMIXR_MUTE                     0x0100  /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_MASK                0x0100  /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_SHIFT                    8  /* SPKMIXR_MUTE */
+#define WM8962_SPKMIXR_MUTE_WIDTH                    1  /* SPKMIXR_MUTE */
+#define WM8962_MIXINL_SPKMIXR_VOL               0x0080  /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_MASK          0x0080  /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_SHIFT              7  /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINL_SPKMIXR_VOL_WIDTH              1  /* MIXINL_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL               0x0040  /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_MASK          0x0040  /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_SHIFT              6  /* MIXINR_SPKMIXR_VOL */
+#define WM8962_MIXINR_SPKMIXR_VOL_WIDTH              1  /* MIXINR_SPKMIXR_VOL */
+#define WM8962_IN4L_SPKMIXR_VOL_MASK            0x0038  /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXR_VOL_SHIFT                3  /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4L_SPKMIXR_VOL_WIDTH                3  /* IN4L_SPKMIXR_VOL - [5:3] */
+#define WM8962_IN4R_SPKMIXR_VOL_MASK            0x0007  /* IN4R_SPKMIXR_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXR_VOL_SHIFT                0  /* IN4R_SPKMIXR_VOL - [2:0] */
+#define WM8962_IN4R_SPKMIXR_VOL_WIDTH                3  /* IN4R_SPKMIXR_VOL - [2:0] */
+
+/*
+ * R109 (0x6D) - Speaker Mixer (5)
+ */
+#define WM8962_DACL_SPKMIXL_VOL                 0x0080  /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_MASK            0x0080  /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_SHIFT                7  /* DACL_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXL_VOL_WIDTH                1  /* DACL_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL                 0x0040  /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_MASK            0x0040  /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_SHIFT                6  /* DACR_SPKMIXL_VOL */
+#define WM8962_DACR_SPKMIXL_VOL_WIDTH                1  /* DACR_SPKMIXL_VOL */
+#define WM8962_DACL_SPKMIXR_VOL                 0x0020  /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_MASK            0x0020  /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_SHIFT                5  /* DACL_SPKMIXR_VOL */
+#define WM8962_DACL_SPKMIXR_VOL_WIDTH                1  /* DACL_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL                 0x0010  /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_MASK            0x0010  /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_SHIFT                4  /* DACR_SPKMIXR_VOL */
+#define WM8962_DACR_SPKMIXR_VOL_WIDTH                1  /* DACR_SPKMIXR_VOL */
+
+/*
+ * R110 (0x6E) - Beep Generator (1)
+ */
+#define WM8962_BEEP_GAIN_MASK                   0x00F0  /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_GAIN_SHIFT                       4  /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_GAIN_WIDTH                       4  /* BEEP_GAIN - [7:4] */
+#define WM8962_BEEP_RATE_MASK                   0x0006  /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_RATE_SHIFT                       1  /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_RATE_WIDTH                       2  /* BEEP_RATE - [2:1] */
+#define WM8962_BEEP_ENA                         0x0001  /* BEEP_ENA */
+#define WM8962_BEEP_ENA_MASK                    0x0001  /* BEEP_ENA */
+#define WM8962_BEEP_ENA_SHIFT                        0  /* BEEP_ENA */
+#define WM8962_BEEP_ENA_WIDTH                        1  /* BEEP_ENA */
+
+/*
+ * R115 (0x73) - Oscillator Trim (3)
+ */
+#define WM8962_OSC_TRIM_XTI_MASK                0x001F  /* OSC_TRIM_XTI - [4:0] */
+#define WM8962_OSC_TRIM_XTI_SHIFT                    0  /* OSC_TRIM_XTI - [4:0] */
+#define WM8962_OSC_TRIM_XTI_WIDTH                    5  /* OSC_TRIM_XTI - [4:0] */
+
+/*
+ * R116 (0x74) - Oscillator Trim (4)
+ */
+#define WM8962_OSC_TRIM_XTO_MASK                0x001F  /* OSC_TRIM_XTO - [4:0] */
+#define WM8962_OSC_TRIM_XTO_SHIFT                    0  /* OSC_TRIM_XTO - [4:0] */
+#define WM8962_OSC_TRIM_XTO_WIDTH                    5  /* OSC_TRIM_XTO - [4:0] */
+
+/*
+ * R119 (0x77) - Oscillator Trim (7)
+ */
+#define WM8962_XTO_CAP_SEL_MASK                 0x00F0  /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTO_CAP_SEL_SHIFT                     4  /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTO_CAP_SEL_WIDTH                     4  /* XTO_CAP_SEL - [7:4] */
+#define WM8962_XTI_CAP_SEL_MASK                 0x000F  /* XTI_CAP_SEL - [3:0] */
+#define WM8962_XTI_CAP_SEL_SHIFT                     0  /* XTI_CAP_SEL - [3:0] */
+#define WM8962_XTI_CAP_SEL_WIDTH                     4  /* XTI_CAP_SEL - [3:0] */
+
+/*
+ * R124 (0x7C) - Analogue Clocking1
+ */
+#define WM8962_CLKOUT2_SEL_MASK                 0x0060  /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT2_SEL_SHIFT                     5  /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT2_SEL_WIDTH                     2  /* CLKOUT2_SEL - [6:5] */
+#define WM8962_CLKOUT3_SEL_MASK                 0x0018  /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT3_SEL_SHIFT                     3  /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT3_SEL_WIDTH                     2  /* CLKOUT3_SEL - [4:3] */
+#define WM8962_CLKOUT5_SEL                      0x0001  /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_MASK                 0x0001  /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_SHIFT                     0  /* CLKOUT5_SEL */
+#define WM8962_CLKOUT5_SEL_WIDTH                     1  /* CLKOUT5_SEL */
+
+/*
+ * R125 (0x7D) - Analogue Clocking2
+ */
+#define WM8962_PLL2_OUTDIV                      0x0080  /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_MASK                 0x0080  /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_SHIFT                     7  /* PLL2_OUTDIV */
+#define WM8962_PLL2_OUTDIV_WIDTH                     1  /* PLL2_OUTDIV */
+#define WM8962_PLL3_OUTDIV                      0x0040  /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_MASK                 0x0040  /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_SHIFT                     6  /* PLL3_OUTDIV */
+#define WM8962_PLL3_OUTDIV_WIDTH                     1  /* PLL3_OUTDIV */
+#define WM8962_PLL_SYSCLK_DIV_MASK              0x0018  /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_PLL_SYSCLK_DIV_SHIFT                  3  /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_PLL_SYSCLK_DIV_WIDTH                  2  /* PLL_SYSCLK_DIV - [4:3] */
+#define WM8962_CLKOUT3_DIV                      0x0004  /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_MASK                 0x0004  /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_SHIFT                     2  /* CLKOUT3_DIV */
+#define WM8962_CLKOUT3_DIV_WIDTH                     1  /* CLKOUT3_DIV */
+#define WM8962_CLKOUT2_DIV                      0x0002  /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_MASK                 0x0002  /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_SHIFT                     1  /* CLKOUT2_DIV */
+#define WM8962_CLKOUT2_DIV_WIDTH                     1  /* CLKOUT2_DIV */
+#define WM8962_CLKOUT5_DIV                      0x0001  /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_MASK                 0x0001  /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_SHIFT                     0  /* CLKOUT5_DIV */
+#define WM8962_CLKOUT5_DIV_WIDTH                     1  /* CLKOUT5_DIV */
+
+/*
+ * R126 (0x7E) - Analogue Clocking3
+ */
+#define WM8962_CLKOUT2_OE                       0x0008  /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_MASK                  0x0008  /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_SHIFT                      3  /* CLKOUT2_OE */
+#define WM8962_CLKOUT2_OE_WIDTH                      1  /* CLKOUT2_OE */
+#define WM8962_CLKOUT3_OE                       0x0004  /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_MASK                  0x0004  /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_SHIFT                      2  /* CLKOUT3_OE */
+#define WM8962_CLKOUT3_OE_WIDTH                      1  /* CLKOUT3_OE */
+#define WM8962_CLKOUT5_OE                       0x0001  /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_MASK                  0x0001  /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_SHIFT                      0  /* CLKOUT5_OE */
+#define WM8962_CLKOUT5_OE_WIDTH                      1  /* CLKOUT5_OE */
+
+/*
+ * R127 (0x7F) - PLL Software Reset
+ */
+#define WM8962_SW_RESET_PLL_MASK                0xFFFF  /* SW_RESET_PLL - [15:0] */
+#define WM8962_SW_RESET_PLL_SHIFT                    0  /* SW_RESET_PLL - [15:0] */
+#define WM8962_SW_RESET_PLL_WIDTH                   16  /* SW_RESET_PLL - [15:0] */
+
+/*
+ * R129 (0x81) - PLL2
+ */
+#define WM8962_OSC_ENA                          0x0080  /* OSC_ENA */
+#define WM8962_OSC_ENA_MASK                     0x0080  /* OSC_ENA */
+#define WM8962_OSC_ENA_SHIFT                         7  /* OSC_ENA */
+#define WM8962_OSC_ENA_WIDTH                         1  /* OSC_ENA */
+#define WM8962_PLL2_ENA                         0x0020  /* PLL2_ENA */
+#define WM8962_PLL2_ENA_MASK                    0x0020  /* PLL2_ENA */
+#define WM8962_PLL2_ENA_SHIFT                        5  /* PLL2_ENA */
+#define WM8962_PLL2_ENA_WIDTH                        1  /* PLL2_ENA */
+#define WM8962_PLL3_ENA                         0x0010  /* PLL3_ENA */
+#define WM8962_PLL3_ENA_MASK                    0x0010  /* PLL3_ENA */
+#define WM8962_PLL3_ENA_SHIFT                        4  /* PLL3_ENA */
+#define WM8962_PLL3_ENA_WIDTH                        1  /* PLL3_ENA */
+
+/*
+ * R131 (0x83) - PLL 4
+ */
+#define WM8962_PLL_CLK_SRC                      0x0002  /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_MASK                 0x0002  /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_SHIFT                     1  /* PLL_CLK_SRC */
+#define WM8962_PLL_CLK_SRC_WIDTH                     1  /* PLL_CLK_SRC */
+#define WM8962_FLL_TO_PLL3                      0x0001  /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_MASK                 0x0001  /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_SHIFT                     0  /* FLL_TO_PLL3 */
+#define WM8962_FLL_TO_PLL3_WIDTH                     1  /* FLL_TO_PLL3 */
+
+/*
+ * R136 (0x88) - PLL 9
+ */
+#define WM8962_PLL2_FRAC                        0x0040  /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_MASK                   0x0040  /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_SHIFT                       6  /* PLL2_FRAC */
+#define WM8962_PLL2_FRAC_WIDTH                       1  /* PLL2_FRAC */
+#define WM8962_PLL2_N_MASK                      0x001F  /* PLL2_N - [4:0] */
+#define WM8962_PLL2_N_SHIFT                          0  /* PLL2_N - [4:0] */
+#define WM8962_PLL2_N_WIDTH                          5  /* PLL2_N - [4:0] */
+
+/*
+ * R137 (0x89) - PLL 10
+ */
+#define WM8962_PLL2_K_MASK                      0x00FF  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT                          0  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH                          8  /* PLL2_K - [7:0] */
+
+/*
+ * R138 (0x8A) - PLL 11
+ */
+#define WM8962_PLL2_K_MASK                      0x00FF  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT                          0  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH                          8  /* PLL2_K - [7:0] */
+
+/*
+ * R139 (0x8B) - PLL 12
+ */
+#define WM8962_PLL2_K_MASK                      0x00FF  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_SHIFT                          0  /* PLL2_K - [7:0] */
+#define WM8962_PLL2_K_WIDTH                          8  /* PLL2_K - [7:0] */
+
+/*
+ * R140 (0x8C) - PLL 13
+ */
+#define WM8962_PLL3_FRAC                        0x0040  /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_MASK                   0x0040  /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_SHIFT                       6  /* PLL3_FRAC */
+#define WM8962_PLL3_FRAC_WIDTH                       1  /* PLL3_FRAC */
+#define WM8962_PLL3_N_MASK                      0x001F  /* PLL3_N - [4:0] */
+#define WM8962_PLL3_N_SHIFT                          0  /* PLL3_N - [4:0] */
+#define WM8962_PLL3_N_WIDTH                          5  /* PLL3_N - [4:0] */
+
+/*
+ * R141 (0x8D) - PLL 14
+ */
+#define WM8962_PLL3_K_MASK                      0x00FF  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT                          0  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH                          8  /* PLL3_K - [7:0] */
+
+/*
+ * R142 (0x8E) - PLL 15
+ */
+#define WM8962_PLL3_K_MASK                      0x00FF  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT                          0  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH                          8  /* PLL3_K - [7:0] */
+
+/*
+ * R143 (0x8F) - PLL 16
+ */
+#define WM8962_PLL3_K_MASK                      0x00FF  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_SHIFT                          0  /* PLL3_K - [7:0] */
+#define WM8962_PLL3_K_WIDTH                          8  /* PLL3_K - [7:0] */
+
+/*
+ * R155 (0x9B) - FLL Control (1)
+ */
+#define WM8962_FLL_REFCLK_SRC_MASK              0x0060  /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_REFCLK_SRC_SHIFT                  5  /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_REFCLK_SRC_WIDTH                  2  /* FLL_REFCLK_SRC - [6:5] */
+#define WM8962_FLL_FRAC                         0x0004  /* FLL_FRAC */
+#define WM8962_FLL_FRAC_MASK                    0x0004  /* FLL_FRAC */
+#define WM8962_FLL_FRAC_SHIFT                        2  /* FLL_FRAC */
+#define WM8962_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM8962_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
+#define WM8962_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM8962_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM8962_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM8962_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM8962_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R156 (0x9C) - FLL Control (2)
+ */
+#define WM8962_FLL_OUTDIV_MASK                  0x01F8  /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_OUTDIV_SHIFT                      3  /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_OUTDIV_WIDTH                      6  /* FLL_OUTDIV - [8:3] */
+#define WM8962_FLL_REFCLK_DIV_MASK              0x0003  /* FLL_REFCLK_DIV - [1:0] */
+#define WM8962_FLL_REFCLK_DIV_SHIFT                  0  /* FLL_REFCLK_DIV - [1:0] */
+#define WM8962_FLL_REFCLK_DIV_WIDTH                  2  /* FLL_REFCLK_DIV - [1:0] */
+
+/*
+ * R157 (0x9D) - FLL Control (3)
+ */
+#define WM8962_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM8962_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM8962_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R159 (0x9F) - FLL Control (5)
+ */
+#define WM8962_FLL_FRC_NCO_VAL_MASK             0x007E  /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO_VAL_SHIFT                 1  /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO_VAL_WIDTH                 6  /* FLL_FRC_NCO_VAL - [6:1] */
+#define WM8962_FLL_FRC_NCO                      0x0001  /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_MASK                 0x0001  /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_SHIFT                     0  /* FLL_FRC_NCO */
+#define WM8962_FLL_FRC_NCO_WIDTH                     1  /* FLL_FRC_NCO */
+
+/*
+ * R160 (0xA0) - FLL Control (6)
+ */
+#define WM8962_FLL_THETA_MASK                   0xFFFF  /* FLL_THETA - [15:0] */
+#define WM8962_FLL_THETA_SHIFT                       0  /* FLL_THETA - [15:0] */
+#define WM8962_FLL_THETA_WIDTH                      16  /* FLL_THETA - [15:0] */
+
+/*
+ * R161 (0xA1) - FLL Control (7)
+ */
+#define WM8962_FLL_LAMBDA_MASK                  0xFFFF  /* FLL_LAMBDA - [15:0] */
+#define WM8962_FLL_LAMBDA_SHIFT                      0  /* FLL_LAMBDA - [15:0] */
+#define WM8962_FLL_LAMBDA_WIDTH                     16  /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R162 (0xA2) - FLL Control (8)
+ */
+#define WM8962_FLL_N_MASK                       0x03FF  /* FLL_N - [9:0] */
+#define WM8962_FLL_N_SHIFT                           0  /* FLL_N - [9:0] */
+#define WM8962_FLL_N_WIDTH                          10  /* FLL_N - [9:0] */
+
+/*
+ * R252 (0xFC) - General test 1
+ */
+#define WM8962_REG_SYNC                         0x0004  /* REG_SYNC */
+#define WM8962_REG_SYNC_MASK                    0x0004  /* REG_SYNC */
+#define WM8962_REG_SYNC_SHIFT                        2  /* REG_SYNC */
+#define WM8962_REG_SYNC_WIDTH                        1  /* REG_SYNC */
+#define WM8962_AUTO_INC                         0x0001  /* AUTO_INC */
+#define WM8962_AUTO_INC_MASK                    0x0001  /* AUTO_INC */
+#define WM8962_AUTO_INC_SHIFT                        0  /* AUTO_INC */
+#define WM8962_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+/*
+ * R256 (0x100) - DF1
+ */
+#define WM8962_DRC_DF1_ENA                      0x0008  /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_MASK                 0x0008  /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_SHIFT                     3  /* DRC_DF1_ENA */
+#define WM8962_DRC_DF1_ENA_WIDTH                     1  /* DRC_DF1_ENA */
+#define WM8962_DF1_SHARED_COEFF                 0x0004  /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_MASK            0x0004  /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_SHIFT                2  /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_WIDTH                1  /* DF1_SHARED_COEFF */
+#define WM8962_DF1_SHARED_COEFF_SEL             0x0002  /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_MASK        0x0002  /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_SHIFT            1  /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_SHARED_COEFF_SEL_WIDTH            1  /* DF1_SHARED_COEFF_SEL */
+#define WM8962_DF1_ENA                          0x0001  /* DF1_ENA */
+#define WM8962_DF1_ENA_MASK                     0x0001  /* DF1_ENA */
+#define WM8962_DF1_ENA_SHIFT                         0  /* DF1_ENA */
+#define WM8962_DF1_ENA_WIDTH                         1  /* DF1_ENA */
+
+/*
+ * R257 (0x101) - DF2
+ */
+#define WM8962_DF1_COEFF_L0_MASK                0xFFFF  /* DF1_COEFF_L0 - [15:0] */
+#define WM8962_DF1_COEFF_L0_SHIFT                    0  /* DF1_COEFF_L0 - [15:0] */
+#define WM8962_DF1_COEFF_L0_WIDTH                   16  /* DF1_COEFF_L0 - [15:0] */
+
+/*
+ * R258 (0x102) - DF3
+ */
+#define WM8962_DF1_COEFF_L1_MASK                0xFFFF  /* DF1_COEFF_L1 - [15:0] */
+#define WM8962_DF1_COEFF_L1_SHIFT                    0  /* DF1_COEFF_L1 - [15:0] */
+#define WM8962_DF1_COEFF_L1_WIDTH                   16  /* DF1_COEFF_L1 - [15:0] */
+
+/*
+ * R259 (0x103) - DF4
+ */
+#define WM8962_DF1_COEFF_L2_MASK                0xFFFF  /* DF1_COEFF_L2 - [15:0] */
+#define WM8962_DF1_COEFF_L2_SHIFT                    0  /* DF1_COEFF_L2 - [15:0] */
+#define WM8962_DF1_COEFF_L2_WIDTH                   16  /* DF1_COEFF_L2 - [15:0] */
+
+/*
+ * R260 (0x104) - DF5
+ */
+#define WM8962_DF1_COEFF_R0_MASK                0xFFFF  /* DF1_COEFF_R0 - [15:0] */
+#define WM8962_DF1_COEFF_R0_SHIFT                    0  /* DF1_COEFF_R0 - [15:0] */
+#define WM8962_DF1_COEFF_R0_WIDTH                   16  /* DF1_COEFF_R0 - [15:0] */
+
+/*
+ * R261 (0x105) - DF6
+ */
+#define WM8962_DF1_COEFF_R1_MASK                0xFFFF  /* DF1_COEFF_R1 - [15:0] */
+#define WM8962_DF1_COEFF_R1_SHIFT                    0  /* DF1_COEFF_R1 - [15:0] */
+#define WM8962_DF1_COEFF_R1_WIDTH                   16  /* DF1_COEFF_R1 - [15:0] */
+
+/*
+ * R262 (0x106) - DF7
+ */
+#define WM8962_DF1_COEFF_R2_MASK                0xFFFF  /* DF1_COEFF_R2 - [15:0] */
+#define WM8962_DF1_COEFF_R2_SHIFT                    0  /* DF1_COEFF_R2 - [15:0] */
+#define WM8962_DF1_COEFF_R2_WIDTH                   16  /* DF1_COEFF_R2 - [15:0] */
+
+/*
+ * R264 (0x108) - LHPF1
+ */
+#define WM8962_LHPF_MODE                        0x0002  /* LHPF_MODE */
+#define WM8962_LHPF_MODE_MASK                   0x0002  /* LHPF_MODE */
+#define WM8962_LHPF_MODE_SHIFT                       1  /* LHPF_MODE */
+#define WM8962_LHPF_MODE_WIDTH                       1  /* LHPF_MODE */
+#define WM8962_LHPF_ENA                         0x0001  /* LHPF_ENA */
+#define WM8962_LHPF_ENA_MASK                    0x0001  /* LHPF_ENA */
+#define WM8962_LHPF_ENA_SHIFT                        0  /* LHPF_ENA */
+#define WM8962_LHPF_ENA_WIDTH                        1  /* LHPF_ENA */
+
+/*
+ * R265 (0x109) - LHPF2
+ */
+#define WM8962_LHPF_COEFF_MASK                  0xFFFF  /* LHPF_COEFF - [15:0] */
+#define WM8962_LHPF_COEFF_SHIFT                      0  /* LHPF_COEFF - [15:0] */
+#define WM8962_LHPF_COEFF_WIDTH                     16  /* LHPF_COEFF - [15:0] */
+
+/*
+ * R268 (0x10C) - THREED1
+ */
+#define WM8962_ADC_MONOMIX                      0x0040  /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_MASK                 0x0040  /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_SHIFT                     6  /* ADC_MONOMIX */
+#define WM8962_ADC_MONOMIX_WIDTH                     1  /* ADC_MONOMIX */
+#define WM8962_THREED_SIGN_L                    0x0020  /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_MASK               0x0020  /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_SHIFT                   5  /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_L_WIDTH                   1  /* THREED_SIGN_L */
+#define WM8962_THREED_SIGN_R                    0x0010  /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_MASK               0x0010  /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_SHIFT                   4  /* THREED_SIGN_R */
+#define WM8962_THREED_SIGN_R_WIDTH                   1  /* THREED_SIGN_R */
+#define WM8962_THREED_LHPF_MODE                 0x0004  /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_MASK            0x0004  /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_SHIFT                2  /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_MODE_WIDTH                1  /* THREED_LHPF_MODE */
+#define WM8962_THREED_LHPF_ENA                  0x0002  /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_MASK             0x0002  /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_SHIFT                 1  /* THREED_LHPF_ENA */
+#define WM8962_THREED_LHPF_ENA_WIDTH                 1  /* THREED_LHPF_ENA */
+#define WM8962_THREED_ENA                       0x0001  /* THREED_ENA */
+#define WM8962_THREED_ENA_MASK                  0x0001  /* THREED_ENA */
+#define WM8962_THREED_ENA_SHIFT                      0  /* THREED_ENA */
+#define WM8962_THREED_ENA_WIDTH                      1  /* THREED_ENA */
+
+/*
+ * R269 (0x10D) - THREED2
+ */
+#define WM8962_THREED_FGAINL_MASK               0xF800  /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_FGAINL_SHIFT                  11  /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_FGAINL_WIDTH                   5  /* THREED_FGAINL - [15:11] */
+#define WM8962_THREED_CGAINL_MASK               0x07C0  /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_CGAINL_SHIFT                   6  /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_CGAINL_WIDTH                   5  /* THREED_CGAINL - [10:6] */
+#define WM8962_THREED_DELAYL_MASK               0x003C  /* THREED_DELAYL - [5:2] */
+#define WM8962_THREED_DELAYL_SHIFT                   2  /* THREED_DELAYL - [5:2] */
+#define WM8962_THREED_DELAYL_WIDTH                   4  /* THREED_DELAYL - [5:2] */
+
+/*
+ * R270 (0x10E) - THREED3
+ */
+#define WM8962_THREED_LHPF_COEFF_MASK           0xFFFF  /* THREED_LHPF_COEFF - [15:0] */
+#define WM8962_THREED_LHPF_COEFF_SHIFT               0  /* THREED_LHPF_COEFF - [15:0] */
+#define WM8962_THREED_LHPF_COEFF_WIDTH              16  /* THREED_LHPF_COEFF - [15:0] */
+
+/*
+ * R271 (0x10F) - THREED4
+ */
+#define WM8962_THREED_FGAINR_MASK               0xF800  /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_FGAINR_SHIFT                  11  /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_FGAINR_WIDTH                   5  /* THREED_FGAINR - [15:11] */
+#define WM8962_THREED_CGAINR_MASK               0x07C0  /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_CGAINR_SHIFT                   6  /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_CGAINR_WIDTH                   5  /* THREED_CGAINR - [10:6] */
+#define WM8962_THREED_DELAYR_MASK               0x003C  /* THREED_DELAYR - [5:2] */
+#define WM8962_THREED_DELAYR_SHIFT                   2  /* THREED_DELAYR - [5:2] */
+#define WM8962_THREED_DELAYR_WIDTH                   4  /* THREED_DELAYR - [5:2] */
+
+/*
+ * R276 (0x114) - DRC 1
+ */
+#define WM8962_DRC_SIG_DET_RMS_MASK             0x7C00  /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_RMS_SHIFT                10  /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_RMS_WIDTH                 5  /* DRC_SIG_DET_RMS - [14:10] */
+#define WM8962_DRC_SIG_DET_PK_MASK              0x0300  /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_SIG_DET_PK_SHIFT                  8  /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_SIG_DET_PK_WIDTH                  2  /* DRC_SIG_DET_PK - [9:8] */
+#define WM8962_DRC_NG_ENA                       0x0080  /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_MASK                  0x0080  /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_SHIFT                      7  /* DRC_NG_ENA */
+#define WM8962_DRC_NG_ENA_WIDTH                      1  /* DRC_NG_ENA */
+#define WM8962_DRC_SIG_DET_MODE                 0x0040  /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_MASK            0x0040  /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_SHIFT                6  /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET_MODE_WIDTH                1  /* DRC_SIG_DET_MODE */
+#define WM8962_DRC_SIG_DET                      0x0020  /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_MASK                 0x0020  /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_SHIFT                     5  /* DRC_SIG_DET */
+#define WM8962_DRC_SIG_DET_WIDTH                     1  /* DRC_SIG_DET */
+#define WM8962_DRC_KNEE2_OP_ENA                 0x0010  /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_MASK            0x0010  /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_SHIFT                4  /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_KNEE2_OP_ENA_WIDTH                1  /* DRC_KNEE2_OP_ENA */
+#define WM8962_DRC_QR                           0x0008  /* DRC_QR */
+#define WM8962_DRC_QR_MASK                      0x0008  /* DRC_QR */
+#define WM8962_DRC_QR_SHIFT                          3  /* DRC_QR */
+#define WM8962_DRC_QR_WIDTH                          1  /* DRC_QR */
+#define WM8962_DRC_ANTICLIP                     0x0004  /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_MASK                0x0004  /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_SHIFT                    2  /* DRC_ANTICLIP */
+#define WM8962_DRC_ANTICLIP_WIDTH                    1  /* DRC_ANTICLIP */
+#define WM8962_DRC_MODE                         0x0002  /* DRC_MODE */
+#define WM8962_DRC_MODE_MASK                    0x0002  /* DRC_MODE */
+#define WM8962_DRC_MODE_SHIFT                        1  /* DRC_MODE */
+#define WM8962_DRC_MODE_WIDTH                        1  /* DRC_MODE */
+#define WM8962_DRC_ENA                          0x0001  /* DRC_ENA */
+#define WM8962_DRC_ENA_MASK                     0x0001  /* DRC_ENA */
+#define WM8962_DRC_ENA_SHIFT                         0  /* DRC_ENA */
+#define WM8962_DRC_ENA_WIDTH                         1  /* DRC_ENA */
+
+/*
+ * R277 (0x115) - DRC 2
+ */
+#define WM8962_DRC_ATK_MASK                     0x1E00  /* DRC_ATK - [12:9] */
+#define WM8962_DRC_ATK_SHIFT                         9  /* DRC_ATK - [12:9] */
+#define WM8962_DRC_ATK_WIDTH                         4  /* DRC_ATK - [12:9] */
+#define WM8962_DRC_DCY_MASK                     0x01E0  /* DRC_DCY - [8:5] */
+#define WM8962_DRC_DCY_SHIFT                         5  /* DRC_DCY - [8:5] */
+#define WM8962_DRC_DCY_WIDTH                         4  /* DRC_DCY - [8:5] */
+#define WM8962_DRC_MINGAIN_MASK                 0x001C  /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MINGAIN_SHIFT                     2  /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MINGAIN_WIDTH                     3  /* DRC_MINGAIN - [4:2] */
+#define WM8962_DRC_MAXGAIN_MASK                 0x0003  /* DRC_MAXGAIN - [1:0] */
+#define WM8962_DRC_MAXGAIN_SHIFT                     0  /* DRC_MAXGAIN - [1:0] */
+#define WM8962_DRC_MAXGAIN_WIDTH                     2  /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R278 (0x116) - DRC 3
+ */
+#define WM8962_DRC_NG_MINGAIN_MASK              0xF000  /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_NG_MINGAIN_SHIFT                 12  /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_NG_MINGAIN_WIDTH                  4  /* DRC_NG_MINGAIN - [15:12] */
+#define WM8962_DRC_QR_THR_MASK                  0x0C00  /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_THR_SHIFT                     10  /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_THR_WIDTH                      2  /* DRC_QR_THR - [11:10] */
+#define WM8962_DRC_QR_DCY_MASK                  0x0300  /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_QR_DCY_SHIFT                      8  /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_QR_DCY_WIDTH                      2  /* DRC_QR_DCY - [9:8] */
+#define WM8962_DRC_NG_EXP_MASK                  0x00C0  /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_NG_EXP_SHIFT                      6  /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_NG_EXP_WIDTH                      2  /* DRC_NG_EXP - [7:6] */
+#define WM8962_DRC_HI_COMP_MASK                 0x0038  /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_HI_COMP_SHIFT                     3  /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_HI_COMP_WIDTH                     3  /* DRC_HI_COMP - [5:3] */
+#define WM8962_DRC_LO_COMP_MASK                 0x0007  /* DRC_LO_COMP - [2:0] */
+#define WM8962_DRC_LO_COMP_SHIFT                     0  /* DRC_LO_COMP - [2:0] */
+#define WM8962_DRC_LO_COMP_WIDTH                     3  /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R279 (0x117) - DRC 4
+ */
+#define WM8962_DRC_KNEE_IP_MASK                 0x07E0  /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_IP_SHIFT                     5  /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_IP_WIDTH                     6  /* DRC_KNEE_IP - [10:5] */
+#define WM8962_DRC_KNEE_OP_MASK                 0x001F  /* DRC_KNEE_OP - [4:0] */
+#define WM8962_DRC_KNEE_OP_SHIFT                     0  /* DRC_KNEE_OP - [4:0] */
+#define WM8962_DRC_KNEE_OP_WIDTH                     5  /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R280 (0x118) - DRC 5
+ */
+#define WM8962_DRC_KNEE2_IP_MASK                0x03E0  /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_IP_SHIFT                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_IP_WIDTH                    5  /* DRC_KNEE2_IP - [9:5] */
+#define WM8962_DRC_KNEE2_OP_MASK                0x001F  /* DRC_KNEE2_OP - [4:0] */
+#define WM8962_DRC_KNEE2_OP_SHIFT                    0  /* DRC_KNEE2_OP - [4:0] */
+#define WM8962_DRC_KNEE2_OP_WIDTH                    5  /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R285 (0x11D) - Tloopback
+ */
+#define WM8962_TLB_ENA                          0x0002  /* TLB_ENA */
+#define WM8962_TLB_ENA_MASK                     0x0002  /* TLB_ENA */
+#define WM8962_TLB_ENA_SHIFT                         1  /* TLB_ENA */
+#define WM8962_TLB_ENA_WIDTH                         1  /* TLB_ENA */
+#define WM8962_TLB_MODE                         0x0001  /* TLB_MODE */
+#define WM8962_TLB_MODE_MASK                    0x0001  /* TLB_MODE */
+#define WM8962_TLB_MODE_SHIFT                        0  /* TLB_MODE */
+#define WM8962_TLB_MODE_WIDTH                        1  /* TLB_MODE */
+
+/*
+ * R335 (0x14F) - EQ1
+ */
+#define WM8962_EQ_SHARED_COEFF                  0x0004  /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_MASK             0x0004  /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_SHIFT                 2  /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_WIDTH                 1  /* EQ_SHARED_COEFF */
+#define WM8962_EQ_SHARED_COEFF_SEL              0x0002  /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_MASK         0x0002  /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_SHIFT             1  /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_SHARED_COEFF_SEL_WIDTH             1  /* EQ_SHARED_COEFF_SEL */
+#define WM8962_EQ_ENA                           0x0001  /* EQ_ENA */
+#define WM8962_EQ_ENA_MASK                      0x0001  /* EQ_ENA */
+#define WM8962_EQ_ENA_SHIFT                          0  /* EQ_ENA */
+#define WM8962_EQ_ENA_WIDTH                          1  /* EQ_ENA */
+
+/*
+ * R336 (0x150) - EQ2
+ */
+#define WM8962_EQL_B1_GAIN_MASK                 0xF800  /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B1_GAIN_SHIFT                    11  /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B1_GAIN_WIDTH                     5  /* EQL_B1_GAIN - [15:11] */
+#define WM8962_EQL_B2_GAIN_MASK                 0x07C0  /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B2_GAIN_SHIFT                     6  /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B2_GAIN_WIDTH                     5  /* EQL_B2_GAIN - [10:6] */
+#define WM8962_EQL_B3_GAIN_MASK                 0x003E  /* EQL_B3_GAIN - [5:1] */
+#define WM8962_EQL_B3_GAIN_SHIFT                     1  /* EQL_B3_GAIN - [5:1] */
+#define WM8962_EQL_B3_GAIN_WIDTH                     5  /* EQL_B3_GAIN - [5:1] */
+
+/*
+ * R337 (0x151) - EQ3
+ */
+#define WM8962_EQL_B4_GAIN_MASK                 0xF800  /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B4_GAIN_SHIFT                    11  /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B4_GAIN_WIDTH                     5  /* EQL_B4_GAIN - [15:11] */
+#define WM8962_EQL_B5_GAIN_MASK                 0x07C0  /* EQL_B5_GAIN - [10:6] */
+#define WM8962_EQL_B5_GAIN_SHIFT                     6  /* EQL_B5_GAIN - [10:6] */
+#define WM8962_EQL_B5_GAIN_WIDTH                     5  /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R338 (0x152) - EQ4
+ */
+#define WM8962_EQL_B1_A_MASK                    0xFFFF  /* EQL_B1_A - [15:0] */
+#define WM8962_EQL_B1_A_SHIFT                        0  /* EQL_B1_A - [15:0] */
+#define WM8962_EQL_B1_A_WIDTH                       16  /* EQL_B1_A - [15:0] */
+
+/*
+ * R339 (0x153) - EQ5
+ */
+#define WM8962_EQL_B1_B_MASK                    0xFFFF  /* EQL_B1_B - [15:0] */
+#define WM8962_EQL_B1_B_SHIFT                        0  /* EQL_B1_B - [15:0] */
+#define WM8962_EQL_B1_B_WIDTH                       16  /* EQL_B1_B - [15:0] */
+
+/*
+ * R340 (0x154) - EQ6
+ */
+#define WM8962_EQL_B1_PG_MASK                   0xFFFF  /* EQL_B1_PG - [15:0] */
+#define WM8962_EQL_B1_PG_SHIFT                       0  /* EQL_B1_PG - [15:0] */
+#define WM8962_EQL_B1_PG_WIDTH                      16  /* EQL_B1_PG - [15:0] */
+
+/*
+ * R341 (0x155) - EQ7
+ */
+#define WM8962_EQL_B2_A_MASK                    0xFFFF  /* EQL_B2_A - [15:0] */
+#define WM8962_EQL_B2_A_SHIFT                        0  /* EQL_B2_A - [15:0] */
+#define WM8962_EQL_B2_A_WIDTH                       16  /* EQL_B2_A - [15:0] */
+
+/*
+ * R342 (0x156) - EQ8
+ */
+#define WM8962_EQL_B2_B_MASK                    0xFFFF  /* EQL_B2_B - [15:0] */
+#define WM8962_EQL_B2_B_SHIFT                        0  /* EQL_B2_B - [15:0] */
+#define WM8962_EQL_B2_B_WIDTH                       16  /* EQL_B2_B - [15:0] */
+
+/*
+ * R343 (0x157) - EQ9
+ */
+#define WM8962_EQL_B2_C_MASK                    0xFFFF  /* EQL_B2_C - [15:0] */
+#define WM8962_EQL_B2_C_SHIFT                        0  /* EQL_B2_C - [15:0] */
+#define WM8962_EQL_B2_C_WIDTH                       16  /* EQL_B2_C - [15:0] */
+
+/*
+ * R344 (0x158) - EQ10
+ */
+#define WM8962_EQL_B2_PG_MASK                   0xFFFF  /* EQL_B2_PG - [15:0] */
+#define WM8962_EQL_B2_PG_SHIFT                       0  /* EQL_B2_PG - [15:0] */
+#define WM8962_EQL_B2_PG_WIDTH                      16  /* EQL_B2_PG - [15:0] */
+
+/*
+ * R345 (0x159) - EQ11
+ */
+#define WM8962_EQL_B3_A_MASK                    0xFFFF  /* EQL_B3_A - [15:0] */
+#define WM8962_EQL_B3_A_SHIFT                        0  /* EQL_B3_A - [15:0] */
+#define WM8962_EQL_B3_A_WIDTH                       16  /* EQL_B3_A - [15:0] */
+
+/*
+ * R346 (0x15A) - EQ12
+ */
+#define WM8962_EQL_B3_B_MASK                    0xFFFF  /* EQL_B3_B - [15:0] */
+#define WM8962_EQL_B3_B_SHIFT                        0  /* EQL_B3_B - [15:0] */
+#define WM8962_EQL_B3_B_WIDTH                       16  /* EQL_B3_B - [15:0] */
+
+/*
+ * R347 (0x15B) - EQ13
+ */
+#define WM8962_EQL_B3_C_MASK                    0xFFFF  /* EQL_B3_C - [15:0] */
+#define WM8962_EQL_B3_C_SHIFT                        0  /* EQL_B3_C - [15:0] */
+#define WM8962_EQL_B3_C_WIDTH                       16  /* EQL_B3_C - [15:0] */
+
+/*
+ * R348 (0x15C) - EQ14
+ */
+#define WM8962_EQL_B3_PG_MASK                   0xFFFF  /* EQL_B3_PG - [15:0] */
+#define WM8962_EQL_B3_PG_SHIFT                       0  /* EQL_B3_PG - [15:0] */
+#define WM8962_EQL_B3_PG_WIDTH                      16  /* EQL_B3_PG - [15:0] */
+
+/*
+ * R349 (0x15D) - EQ15
+ */
+#define WM8962_EQL_B4_A_MASK                    0xFFFF  /* EQL_B4_A - [15:0] */
+#define WM8962_EQL_B4_A_SHIFT                        0  /* EQL_B4_A - [15:0] */
+#define WM8962_EQL_B4_A_WIDTH                       16  /* EQL_B4_A - [15:0] */
+
+/*
+ * R350 (0x15E) - EQ16
+ */
+#define WM8962_EQL_B4_B_MASK                    0xFFFF  /* EQL_B4_B - [15:0] */
+#define WM8962_EQL_B4_B_SHIFT                        0  /* EQL_B4_B - [15:0] */
+#define WM8962_EQL_B4_B_WIDTH                       16  /* EQL_B4_B - [15:0] */
+
+/*
+ * R351 (0x15F) - EQ17
+ */
+#define WM8962_EQL_B4_C_MASK                    0xFFFF  /* EQL_B4_C - [15:0] */
+#define WM8962_EQL_B4_C_SHIFT                        0  /* EQL_B4_C - [15:0] */
+#define WM8962_EQL_B4_C_WIDTH                       16  /* EQL_B4_C - [15:0] */
+
+/*
+ * R352 (0x160) - EQ18
+ */
+#define WM8962_EQL_B4_PG_MASK                   0xFFFF  /* EQL_B4_PG - [15:0] */
+#define WM8962_EQL_B4_PG_SHIFT                       0  /* EQL_B4_PG - [15:0] */
+#define WM8962_EQL_B4_PG_WIDTH                      16  /* EQL_B4_PG - [15:0] */
+
+/*
+ * R353 (0x161) - EQ19
+ */
+#define WM8962_EQL_B5_A_MASK                    0xFFFF  /* EQL_B5_A - [15:0] */
+#define WM8962_EQL_B5_A_SHIFT                        0  /* EQL_B5_A - [15:0] */
+#define WM8962_EQL_B5_A_WIDTH                       16  /* EQL_B5_A - [15:0] */
+
+/*
+ * R354 (0x162) - EQ20
+ */
+#define WM8962_EQL_B5_B_MASK                    0xFFFF  /* EQL_B5_B - [15:0] */
+#define WM8962_EQL_B5_B_SHIFT                        0  /* EQL_B5_B - [15:0] */
+#define WM8962_EQL_B5_B_WIDTH                       16  /* EQL_B5_B - [15:0] */
+
+/*
+ * R355 (0x163) - EQ21
+ */
+#define WM8962_EQL_B5_PG_MASK                   0xFFFF  /* EQL_B5_PG - [15:0] */
+#define WM8962_EQL_B5_PG_SHIFT                       0  /* EQL_B5_PG - [15:0] */
+#define WM8962_EQL_B5_PG_WIDTH                      16  /* EQL_B5_PG - [15:0] */
+
+/*
+ * R356 (0x164) - EQ22
+ */
+#define WM8962_EQR_B1_GAIN_MASK                 0xF800  /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B1_GAIN_SHIFT                    11  /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B1_GAIN_WIDTH                     5  /* EQR_B1_GAIN - [15:11] */
+#define WM8962_EQR_B2_GAIN_MASK                 0x07C0  /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B2_GAIN_SHIFT                     6  /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B2_GAIN_WIDTH                     5  /* EQR_B2_GAIN - [10:6] */
+#define WM8962_EQR_B3_GAIN_MASK                 0x003E  /* EQR_B3_GAIN - [5:1] */
+#define WM8962_EQR_B3_GAIN_SHIFT                     1  /* EQR_B3_GAIN - [5:1] */
+#define WM8962_EQR_B3_GAIN_WIDTH                     5  /* EQR_B3_GAIN - [5:1] */
+
+/*
+ * R357 (0x165) - EQ23
+ */
+#define WM8962_EQR_B4_GAIN_MASK                 0xF800  /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B4_GAIN_SHIFT                    11  /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B4_GAIN_WIDTH                     5  /* EQR_B4_GAIN - [15:11] */
+#define WM8962_EQR_B5_GAIN_MASK                 0x07C0  /* EQR_B5_GAIN - [10:6] */
+#define WM8962_EQR_B5_GAIN_SHIFT                     6  /* EQR_B5_GAIN - [10:6] */
+#define WM8962_EQR_B5_GAIN_WIDTH                     5  /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R358 (0x166) - EQ24
+ */
+#define WM8962_EQR_B1_A_MASK                    0xFFFF  /* EQR_B1_A - [15:0] */
+#define WM8962_EQR_B1_A_SHIFT                        0  /* EQR_B1_A - [15:0] */
+#define WM8962_EQR_B1_A_WIDTH                       16  /* EQR_B1_A - [15:0] */
+
+/*
+ * R359 (0x167) - EQ25
+ */
+#define WM8962_EQR_B1_B_MASK                    0xFFFF  /* EQR_B1_B - [15:0] */
+#define WM8962_EQR_B1_B_SHIFT                        0  /* EQR_B1_B - [15:0] */
+#define WM8962_EQR_B1_B_WIDTH                       16  /* EQR_B1_B - [15:0] */
+
+/*
+ * R360 (0x168) - EQ26
+ */
+#define WM8962_EQR_B1_PG_MASK                   0xFFFF  /* EQR_B1_PG - [15:0] */
+#define WM8962_EQR_B1_PG_SHIFT                       0  /* EQR_B1_PG - [15:0] */
+#define WM8962_EQR_B1_PG_WIDTH                      16  /* EQR_B1_PG - [15:0] */
+
+/*
+ * R361 (0x169) - EQ27
+ */
+#define WM8962_EQR_B2_A_MASK                    0xFFFF  /* EQR_B2_A - [15:0] */
+#define WM8962_EQR_B2_A_SHIFT                        0  /* EQR_B2_A - [15:0] */
+#define WM8962_EQR_B2_A_WIDTH                       16  /* EQR_B2_A - [15:0] */
+
+/*
+ * R362 (0x16A) - EQ28
+ */
+#define WM8962_EQR_B2_B_MASK                    0xFFFF  /* EQR_B2_B - [15:0] */
+#define WM8962_EQR_B2_B_SHIFT                        0  /* EQR_B2_B - [15:0] */
+#define WM8962_EQR_B2_B_WIDTH                       16  /* EQR_B2_B - [15:0] */
+
+/*
+ * R363 (0x16B) - EQ29
+ */
+#define WM8962_EQR_B2_C_MASK                    0xFFFF  /* EQR_B2_C - [15:0] */
+#define WM8962_EQR_B2_C_SHIFT                        0  /* EQR_B2_C - [15:0] */
+#define WM8962_EQR_B2_C_WIDTH                       16  /* EQR_B2_C - [15:0] */
+
+/*
+ * R364 (0x16C) - EQ30
+ */
+#define WM8962_EQR_B2_PG_MASK                   0xFFFF  /* EQR_B2_PG - [15:0] */
+#define WM8962_EQR_B2_PG_SHIFT                       0  /* EQR_B2_PG - [15:0] */
+#define WM8962_EQR_B2_PG_WIDTH                      16  /* EQR_B2_PG - [15:0] */
+
+/*
+ * R365 (0x16D) - EQ31
+ */
+#define WM8962_EQR_B3_A_MASK                    0xFFFF  /* EQR_B3_A - [15:0] */
+#define WM8962_EQR_B3_A_SHIFT                        0  /* EQR_B3_A - [15:0] */
+#define WM8962_EQR_B3_A_WIDTH                       16  /* EQR_B3_A - [15:0] */
+
+/*
+ * R366 (0x16E) - EQ32
+ */
+#define WM8962_EQR_B3_B_MASK                    0xFFFF  /* EQR_B3_B - [15:0] */
+#define WM8962_EQR_B3_B_SHIFT                        0  /* EQR_B3_B - [15:0] */
+#define WM8962_EQR_B3_B_WIDTH                       16  /* EQR_B3_B - [15:0] */
+
+/*
+ * R367 (0x16F) - EQ33
+ */
+#define WM8962_EQR_B3_C_MASK                    0xFFFF  /* EQR_B3_C - [15:0] */
+#define WM8962_EQR_B3_C_SHIFT                        0  /* EQR_B3_C - [15:0] */
+#define WM8962_EQR_B3_C_WIDTH                       16  /* EQR_B3_C - [15:0] */
+
+/*
+ * R368 (0x170) - EQ34
+ */
+#define WM8962_EQR_B3_PG_MASK                   0xFFFF  /* EQR_B3_PG - [15:0] */
+#define WM8962_EQR_B3_PG_SHIFT                       0  /* EQR_B3_PG - [15:0] */
+#define WM8962_EQR_B3_PG_WIDTH                      16  /* EQR_B3_PG - [15:0] */
+
+/*
+ * R369 (0x171) - EQ35
+ */
+#define WM8962_EQR_B4_A_MASK                    0xFFFF  /* EQR_B4_A - [15:0] */
+#define WM8962_EQR_B4_A_SHIFT                        0  /* EQR_B4_A - [15:0] */
+#define WM8962_EQR_B4_A_WIDTH                       16  /* EQR_B4_A - [15:0] */
+
+/*
+ * R370 (0x172) - EQ36
+ */
+#define WM8962_EQR_B4_B_MASK                    0xFFFF  /* EQR_B4_B - [15:0] */
+#define WM8962_EQR_B4_B_SHIFT                        0  /* EQR_B4_B - [15:0] */
+#define WM8962_EQR_B4_B_WIDTH                       16  /* EQR_B4_B - [15:0] */
+
+/*
+ * R371 (0x173) - EQ37
+ */
+#define WM8962_EQR_B4_C_MASK                    0xFFFF  /* EQR_B4_C - [15:0] */
+#define WM8962_EQR_B4_C_SHIFT                        0  /* EQR_B4_C - [15:0] */
+#define WM8962_EQR_B4_C_WIDTH                       16  /* EQR_B4_C - [15:0] */
+
+/*
+ * R372 (0x174) - EQ38
+ */
+#define WM8962_EQR_B4_PG_MASK                   0xFFFF  /* EQR_B4_PG - [15:0] */
+#define WM8962_EQR_B4_PG_SHIFT                       0  /* EQR_B4_PG - [15:0] */
+#define WM8962_EQR_B4_PG_WIDTH                      16  /* EQR_B4_PG - [15:0] */
+
+/*
+ * R373 (0x175) - EQ39
+ */
+#define WM8962_EQR_B5_A_MASK                    0xFFFF  /* EQR_B5_A - [15:0] */
+#define WM8962_EQR_B5_A_SHIFT                        0  /* EQR_B5_A - [15:0] */
+#define WM8962_EQR_B5_A_WIDTH                       16  /* EQR_B5_A - [15:0] */
+
+/*
+ * R374 (0x176) - EQ40
+ */
+#define WM8962_EQR_B5_B_MASK                    0xFFFF  /* EQR_B5_B - [15:0] */
+#define WM8962_EQR_B5_B_SHIFT                        0  /* EQR_B5_B - [15:0] */
+#define WM8962_EQR_B5_B_WIDTH                       16  /* EQR_B5_B - [15:0] */
+
+/*
+ * R375 (0x177) - EQ41
+ */
+#define WM8962_EQR_B5_PG_MASK                   0xFFFF  /* EQR_B5_PG - [15:0] */
+#define WM8962_EQR_B5_PG_SHIFT                       0  /* EQR_B5_PG - [15:0] */
+#define WM8962_EQR_B5_PG_WIDTH                      16  /* EQR_B5_PG - [15:0] */
+
+/*
+ * R513 (0x201) - GPIO 2
+ */
+#define WM8962_GP2_POL                          0x0400  /* GP2_POL */
+#define WM8962_GP2_POL_MASK                     0x0400  /* GP2_POL */
+#define WM8962_GP2_POL_SHIFT                        10  /* GP2_POL */
+#define WM8962_GP2_POL_WIDTH                         1  /* GP2_POL */
+#define WM8962_GP2_LVL                          0x0040  /* GP2_LVL */
+#define WM8962_GP2_LVL_MASK                     0x0040  /* GP2_LVL */
+#define WM8962_GP2_LVL_SHIFT                         6  /* GP2_LVL */
+#define WM8962_GP2_LVL_WIDTH                         1  /* GP2_LVL */
+#define WM8962_GP2_FN_MASK                      0x001F  /* GP2_FN - [4:0] */
+#define WM8962_GP2_FN_SHIFT                          0  /* GP2_FN - [4:0] */
+#define WM8962_GP2_FN_WIDTH                          5  /* GP2_FN - [4:0] */
+
+/*
+ * R514 (0x202) - GPIO 3
+ */
+#define WM8962_GP3_POL                          0x0400  /* GP3_POL */
+#define WM8962_GP3_POL_MASK                     0x0400  /* GP3_POL */
+#define WM8962_GP3_POL_SHIFT                        10  /* GP3_POL */
+#define WM8962_GP3_POL_WIDTH                         1  /* GP3_POL */
+#define WM8962_GP3_LVL                          0x0040  /* GP3_LVL */
+#define WM8962_GP3_LVL_MASK                     0x0040  /* GP3_LVL */
+#define WM8962_GP3_LVL_SHIFT                         6  /* GP3_LVL */
+#define WM8962_GP3_LVL_WIDTH                         1  /* GP3_LVL */
+#define WM8962_GP3_FN_MASK                      0x001F  /* GP3_FN - [4:0] */
+#define WM8962_GP3_FN_SHIFT                          0  /* GP3_FN - [4:0] */
+#define WM8962_GP3_FN_WIDTH                          5  /* GP3_FN - [4:0] */
+
+/*
+ * R516 (0x204) - GPIO 5
+ */
+#define WM8962_GP5_DIR                          0x8000  /* GP5_DIR */
+#define WM8962_GP5_DIR_MASK                     0x8000  /* GP5_DIR */
+#define WM8962_GP5_DIR_SHIFT                        15  /* GP5_DIR */
+#define WM8962_GP5_DIR_WIDTH                         1  /* GP5_DIR */
+#define WM8962_GP5_PU                           0x4000  /* GP5_PU */
+#define WM8962_GP5_PU_MASK                      0x4000  /* GP5_PU */
+#define WM8962_GP5_PU_SHIFT                         14  /* GP5_PU */
+#define WM8962_GP5_PU_WIDTH                          1  /* GP5_PU */
+#define WM8962_GP5_PD                           0x2000  /* GP5_PD */
+#define WM8962_GP5_PD_MASK                      0x2000  /* GP5_PD */
+#define WM8962_GP5_PD_SHIFT                         13  /* GP5_PD */
+#define WM8962_GP5_PD_WIDTH                          1  /* GP5_PD */
+#define WM8962_GP5_POL                          0x0400  /* GP5_POL */
+#define WM8962_GP5_POL_MASK                     0x0400  /* GP5_POL */
+#define WM8962_GP5_POL_SHIFT                        10  /* GP5_POL */
+#define WM8962_GP5_POL_WIDTH                         1  /* GP5_POL */
+#define WM8962_GP5_OP_CFG                       0x0200  /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_MASK                  0x0200  /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_SHIFT                      9  /* GP5_OP_CFG */
+#define WM8962_GP5_OP_CFG_WIDTH                      1  /* GP5_OP_CFG */
+#define WM8962_GP5_DB                           0x0100  /* GP5_DB */
+#define WM8962_GP5_DB_MASK                      0x0100  /* GP5_DB */
+#define WM8962_GP5_DB_SHIFT                          8  /* GP5_DB */
+#define WM8962_GP5_DB_WIDTH                          1  /* GP5_DB */
+#define WM8962_GP5_LVL                          0x0040  /* GP5_LVL */
+#define WM8962_GP5_LVL_MASK                     0x0040  /* GP5_LVL */
+#define WM8962_GP5_LVL_SHIFT                         6  /* GP5_LVL */
+#define WM8962_GP5_LVL_WIDTH                         1  /* GP5_LVL */
+#define WM8962_GP5_FN_MASK                      0x001F  /* GP5_FN - [4:0] */
+#define WM8962_GP5_FN_SHIFT                          0  /* GP5_FN - [4:0] */
+#define WM8962_GP5_FN_WIDTH                          5  /* GP5_FN - [4:0] */
+
+/*
+ * R517 (0x205) - GPIO 6
+ */
+#define WM8962_GP6_DIR                          0x8000  /* GP6_DIR */
+#define WM8962_GP6_DIR_MASK                     0x8000  /* GP6_DIR */
+#define WM8962_GP6_DIR_SHIFT                        15  /* GP6_DIR */
+#define WM8962_GP6_DIR_WIDTH                         1  /* GP6_DIR */
+#define WM8962_GP6_PU                           0x4000  /* GP6_PU */
+#define WM8962_GP6_PU_MASK                      0x4000  /* GP6_PU */
+#define WM8962_GP6_PU_SHIFT                         14  /* GP6_PU */
+#define WM8962_GP6_PU_WIDTH                          1  /* GP6_PU */
+#define WM8962_GP6_PD                           0x2000  /* GP6_PD */
+#define WM8962_GP6_PD_MASK                      0x2000  /* GP6_PD */
+#define WM8962_GP6_PD_SHIFT                         13  /* GP6_PD */
+#define WM8962_GP6_PD_WIDTH                          1  /* GP6_PD */
+#define WM8962_GP6_POL                          0x0400  /* GP6_POL */
+#define WM8962_GP6_POL_MASK                     0x0400  /* GP6_POL */
+#define WM8962_GP6_POL_SHIFT                        10  /* GP6_POL */
+#define WM8962_GP6_POL_WIDTH                         1  /* GP6_POL */
+#define WM8962_GP6_OP_CFG                       0x0200  /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_MASK                  0x0200  /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_SHIFT                      9  /* GP6_OP_CFG */
+#define WM8962_GP6_OP_CFG_WIDTH                      1  /* GP6_OP_CFG */
+#define WM8962_GP6_DB                           0x0100  /* GP6_DB */
+#define WM8962_GP6_DB_MASK                      0x0100  /* GP6_DB */
+#define WM8962_GP6_DB_SHIFT                          8  /* GP6_DB */
+#define WM8962_GP6_DB_WIDTH                          1  /* GP6_DB */
+#define WM8962_GP6_LVL                          0x0040  /* GP6_LVL */
+#define WM8962_GP6_LVL_MASK                     0x0040  /* GP6_LVL */
+#define WM8962_GP6_LVL_SHIFT                         6  /* GP6_LVL */
+#define WM8962_GP6_LVL_WIDTH                         1  /* GP6_LVL */
+#define WM8962_GP6_FN_MASK                      0x001F  /* GP6_FN - [4:0] */
+#define WM8962_GP6_FN_SHIFT                          0  /* GP6_FN - [4:0] */
+#define WM8962_GP6_FN_WIDTH                          5  /* GP6_FN - [4:0] */
+
+/*
+ * R560 (0x230) - Interrupt Status 1
+ */
+#define WM8962_GP6_EINT                         0x0020  /* GP6_EINT */
+#define WM8962_GP6_EINT_MASK                    0x0020  /* GP6_EINT */
+#define WM8962_GP6_EINT_SHIFT                        5  /* GP6_EINT */
+#define WM8962_GP6_EINT_WIDTH                        1  /* GP6_EINT */
+#define WM8962_GP5_EINT                         0x0010  /* GP5_EINT */
+#define WM8962_GP5_EINT_MASK                    0x0010  /* GP5_EINT */
+#define WM8962_GP5_EINT_SHIFT                        4  /* GP5_EINT */
+#define WM8962_GP5_EINT_WIDTH                        1  /* GP5_EINT */
+
+/*
+ * R561 (0x231) - Interrupt Status 2
+ */
+#define WM8962_MICSCD_EINT                      0x8000  /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_MASK                 0x8000  /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_SHIFT                    15  /* MICSCD_EINT */
+#define WM8962_MICSCD_EINT_WIDTH                     1  /* MICSCD_EINT */
+#define WM8962_MICD_EINT                        0x4000  /* MICD_EINT */
+#define WM8962_MICD_EINT_MASK                   0x4000  /* MICD_EINT */
+#define WM8962_MICD_EINT_SHIFT                      14  /* MICD_EINT */
+#define WM8962_MICD_EINT_WIDTH                       1  /* MICD_EINT */
+#define WM8962_FIFOS_ERR_EINT                   0x2000  /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_MASK              0x2000  /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_SHIFT                 13  /* FIFOS_ERR_EINT */
+#define WM8962_FIFOS_ERR_EINT_WIDTH                  1  /* FIFOS_ERR_EINT */
+#define WM8962_ALC_LOCK_EINT                    0x1000  /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_MASK               0x1000  /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_SHIFT                  12  /* ALC_LOCK_EINT */
+#define WM8962_ALC_LOCK_EINT_WIDTH                   1  /* ALC_LOCK_EINT */
+#define WM8962_ALC_THRESH_EINT                  0x0800  /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_MASK             0x0800  /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_SHIFT                11  /* ALC_THRESH_EINT */
+#define WM8962_ALC_THRESH_EINT_WIDTH                 1  /* ALC_THRESH_EINT */
+#define WM8962_ALC_SAT_EINT                     0x0400  /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_MASK                0x0400  /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_SHIFT                   10  /* ALC_SAT_EINT */
+#define WM8962_ALC_SAT_EINT_WIDTH                    1  /* ALC_SAT_EINT */
+#define WM8962_ALC_PKOVR_EINT                   0x0200  /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_MASK              0x0200  /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_SHIFT                  9  /* ALC_PKOVR_EINT */
+#define WM8962_ALC_PKOVR_EINT_WIDTH                  1  /* ALC_PKOVR_EINT */
+#define WM8962_ALC_NGATE_EINT                   0x0100  /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_MASK              0x0100  /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_SHIFT                  8  /* ALC_NGATE_EINT */
+#define WM8962_ALC_NGATE_EINT_WIDTH                  1  /* ALC_NGATE_EINT */
+#define WM8962_WSEQ_DONE_EINT                   0x0080  /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_MASK              0x0080  /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_SHIFT                  7  /* WSEQ_DONE_EINT */
+#define WM8962_WSEQ_DONE_EINT_WIDTH                  1  /* WSEQ_DONE_EINT */
+#define WM8962_DRC_ACTDET_EINT                  0x0040  /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_MASK             0x0040  /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_SHIFT                 6  /* DRC_ACTDET_EINT */
+#define WM8962_DRC_ACTDET_EINT_WIDTH                 1  /* DRC_ACTDET_EINT */
+#define WM8962_FLL_LOCK_EINT                    0x0020  /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_MASK               0x0020  /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_SHIFT                   5  /* FLL_LOCK_EINT */
+#define WM8962_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT                   0x0008  /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_MASK              0x0008  /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_SHIFT                  3  /* PLL3_LOCK_EINT */
+#define WM8962_PLL3_LOCK_EINT_WIDTH                  1  /* PLL3_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT                   0x0004  /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_MASK              0x0004  /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_SHIFT                  2  /* PLL2_LOCK_EINT */
+#define WM8962_PLL2_LOCK_EINT_WIDTH                  1  /* PLL2_LOCK_EINT */
+#define WM8962_TEMP_SHUT_EINT                   0x0001  /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_MASK              0x0001  /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_SHIFT                  0  /* TEMP_SHUT_EINT */
+#define WM8962_TEMP_SHUT_EINT_WIDTH                  1  /* TEMP_SHUT_EINT */
+
+/*
+ * R568 (0x238) - Interrupt Status 1 Mask
+ */
+#define WM8962_IM_GP6_EINT                      0x0020  /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_MASK                 0x0020  /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_SHIFT                     5  /* IM_GP6_EINT */
+#define WM8962_IM_GP6_EINT_WIDTH                     1  /* IM_GP6_EINT */
+#define WM8962_IM_GP5_EINT                      0x0010  /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_MASK                 0x0010  /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_SHIFT                     4  /* IM_GP5_EINT */
+#define WM8962_IM_GP5_EINT_WIDTH                     1  /* IM_GP5_EINT */
+
+/*
+ * R569 (0x239) - Interrupt Status 2 Mask
+ */
+#define WM8962_IM_MICSCD_EINT                   0x8000  /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_MASK              0x8000  /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_SHIFT                 15  /* IM_MICSCD_EINT */
+#define WM8962_IM_MICSCD_EINT_WIDTH                  1  /* IM_MICSCD_EINT */
+#define WM8962_IM_MICD_EINT                     0x4000  /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_MASK                0x4000  /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_SHIFT                   14  /* IM_MICD_EINT */
+#define WM8962_IM_MICD_EINT_WIDTH                    1  /* IM_MICD_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT                0x2000  /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_MASK           0x2000  /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_SHIFT              13  /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_FIFOS_ERR_EINT_WIDTH               1  /* IM_FIFOS_ERR_EINT */
+#define WM8962_IM_ALC_LOCK_EINT                 0x1000  /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_MASK            0x1000  /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_SHIFT               12  /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_LOCK_EINT_WIDTH                1  /* IM_ALC_LOCK_EINT */
+#define WM8962_IM_ALC_THRESH_EINT               0x0800  /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_MASK          0x0800  /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_SHIFT             11  /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_THRESH_EINT_WIDTH              1  /* IM_ALC_THRESH_EINT */
+#define WM8962_IM_ALC_SAT_EINT                  0x0400  /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_MASK             0x0400  /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_SHIFT                10  /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_SAT_EINT_WIDTH                 1  /* IM_ALC_SAT_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT                0x0200  /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_MASK           0x0200  /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_SHIFT               9  /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_PKOVR_EINT_WIDTH               1  /* IM_ALC_PKOVR_EINT */
+#define WM8962_IM_ALC_NGATE_EINT                0x0100  /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_MASK           0x0100  /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_SHIFT               8  /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_ALC_NGATE_EINT_WIDTH               1  /* IM_ALC_NGATE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT                0x0080  /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_MASK           0x0080  /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_SHIFT               7  /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_WSEQ_DONE_EINT_WIDTH               1  /* IM_WSEQ_DONE_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT               0x0040  /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_MASK          0x0040  /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_SHIFT              6  /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_DRC_ACTDET_EINT_WIDTH              1  /* IM_DRC_ACTDET_EINT */
+#define WM8962_IM_FLL_LOCK_EINT                 0x0020  /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_MASK            0x0020  /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_SHIFT                5  /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT                0x0008  /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_MASK           0x0008  /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_SHIFT               3  /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL3_LOCK_EINT_WIDTH               1  /* IM_PLL3_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT                0x0004  /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_MASK           0x0004  /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_SHIFT               2  /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_PLL2_LOCK_EINT_WIDTH               1  /* IM_PLL2_LOCK_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT                0x0001  /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_MASK           0x0001  /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_SHIFT               0  /* IM_TEMP_SHUT_EINT */
+#define WM8962_IM_TEMP_SHUT_EINT_WIDTH               1  /* IM_TEMP_SHUT_EINT */
+
+/*
+ * R576 (0x240) - Interrupt Control
+ */
+#define WM8962_IRQ_POL                          0x0001  /* IRQ_POL */
+#define WM8962_IRQ_POL_MASK                     0x0001  /* IRQ_POL */
+#define WM8962_IRQ_POL_SHIFT                         0  /* IRQ_POL */
+#define WM8962_IRQ_POL_WIDTH                         1  /* IRQ_POL */
+
+/*
+ * R584 (0x248) - IRQ Debounce
+ */
+#define WM8962_FLL_LOCK_DB                      0x0020  /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_MASK                 0x0020  /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_SHIFT                     5  /* FLL_LOCK_DB */
+#define WM8962_FLL_LOCK_DB_WIDTH                     1  /* FLL_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB                     0x0008  /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_MASK                0x0008  /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_SHIFT                    3  /* PLL3_LOCK_DB */
+#define WM8962_PLL3_LOCK_DB_WIDTH                    1  /* PLL3_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB                     0x0004  /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_MASK                0x0004  /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_SHIFT                    2  /* PLL2_LOCK_DB */
+#define WM8962_PLL2_LOCK_DB_WIDTH                    1  /* PLL2_LOCK_DB */
+#define WM8962_TEMP_SHUT_DB                     0x0001  /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_MASK                0x0001  /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_SHIFT                    0  /* TEMP_SHUT_DB */
+#define WM8962_TEMP_SHUT_DB_WIDTH                    1  /* TEMP_SHUT_DB */
+
+/*
+ * R586 (0x24A) -  MICINT Source Pol
+ */
+#define WM8962_MICSCD_IRQ_POL                   0x8000  /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_MASK              0x8000  /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_SHIFT                 15  /* MICSCD_IRQ_POL */
+#define WM8962_MICSCD_IRQ_POL_WIDTH                  1  /* MICSCD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL                     0x4000  /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_MASK                0x4000  /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_SHIFT                   14  /* MICD_IRQ_POL */
+#define WM8962_MICD_IRQ_POL_WIDTH                    1  /* MICD_IRQ_POL */
+
+/*
+ * R768 (0x300) - DSP2 Power Management
+ */
+#define WM8962_DSP2_ENA                         0x0001  /* DSP2_ENA */
+#define WM8962_DSP2_ENA_MASK                    0x0001  /* DSP2_ENA */
+#define WM8962_DSP2_ENA_SHIFT                        0  /* DSP2_ENA */
+#define WM8962_DSP2_ENA_WIDTH                        1  /* DSP2_ENA */
+
+/*
+ * R1037 (0x40D) - DSP2_ExecControl
+ */
+#define WM8962_DSP2_STOPC                       0x0020  /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_MASK                  0x0020  /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_SHIFT                      5  /* DSP2_STOPC */
+#define WM8962_DSP2_STOPC_WIDTH                      1  /* DSP2_STOPC */
+#define WM8962_DSP2_STOPS                       0x0010  /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_MASK                  0x0010  /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_SHIFT                      4  /* DSP2_STOPS */
+#define WM8962_DSP2_STOPS_WIDTH                      1  /* DSP2_STOPS */
+#define WM8962_DSP2_STOPI                       0x0008  /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_MASK                  0x0008  /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_SHIFT                      3  /* DSP2_STOPI */
+#define WM8962_DSP2_STOPI_WIDTH                      1  /* DSP2_STOPI */
+#define WM8962_DSP2_STOP                        0x0004  /* DSP2_STOP */
+#define WM8962_DSP2_STOP_MASK                   0x0004  /* DSP2_STOP */
+#define WM8962_DSP2_STOP_SHIFT                       2  /* DSP2_STOP */
+#define WM8962_DSP2_STOP_WIDTH                       1  /* DSP2_STOP */
+#define WM8962_DSP2_RUNR                        0x0002  /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_MASK                   0x0002  /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_SHIFT                       1  /* DSP2_RUNR */
+#define WM8962_DSP2_RUNR_WIDTH                       1  /* DSP2_RUNR */
+#define WM8962_DSP2_RUN                         0x0001  /* DSP2_RUN */
+#define WM8962_DSP2_RUN_MASK                    0x0001  /* DSP2_RUN */
+#define WM8962_DSP2_RUN_SHIFT                        0  /* DSP2_RUN */
+#define WM8962_DSP2_RUN_WIDTH                        1  /* DSP2_RUN */
+
+/*
+ * R8192 (0x2000) - DSP2 Instruction RAM 0
+ */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_MASK  0x03FF  /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_SHIFT      0  /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_WIDTH     10  /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
+
+/*
+ * R9216 (0x2400) - DSP2 Address RAM 2
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_MASK 0x003F  /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_SHIFT      0  /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_WIDTH      6  /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
+
+/*
+ * R9217 (0x2401) - DSP2 Address RAM 1
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_MASK 0xFFFF  /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_SHIFT      0  /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_WIDTH     16  /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
+
+/*
+ * R9218 (0x2402) - DSP2 Address RAM 0
+ */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_MASK  0xFFFF  /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_SHIFT      0  /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_WIDTH     16  /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
+
+/*
+ * R12288 (0x3000) - DSP2 Data1 RAM 1
+ */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_MASK 0x00FF  /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_SHIFT      0  /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_23_16_WIDTH      8  /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R12289 (0x3001) - DSP2 Data1 RAM 0
+ */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_MASK  0xFFFF  /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_SHIFT      0  /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA1_RAM_384_24_15_0_WIDTH     16  /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R13312 (0x3400) - DSP2 Data2 RAM 1
+ */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_MASK 0x00FF  /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_SHIFT      0  /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_23_16_WIDTH      8  /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R13313 (0x3401) - DSP2 Data2 RAM 0
+ */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_MASK  0xFFFF  /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_SHIFT      0  /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA2_RAM_384_24_15_0_WIDTH     16  /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R14336 (0x3800) - DSP2 Data3 RAM 1
+ */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_MASK 0x00FF  /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_SHIFT      0  /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_23_16_WIDTH      8  /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
+
+/*
+ * R14337 (0x3801) - DSP2 Data3 RAM 0
+ */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_MASK  0xFFFF  /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_SHIFT      0  /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+#define WM8962_DSP2_DATA3_RAM_384_24_15_0_WIDTH     16  /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
+
+/*
+ * R15360 (0x3C00) - DSP2 Coeff RAM 0
+ */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_MASK   0x07FF  /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_SHIFT       0  /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+#define WM8962_DSP2_CMAP_RAM_384_11_10_0_WIDTH      11  /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
+
+/*
+ * R16384 (0x4000) - RETUNEADC_SHARED_COEFF_1
+ */
+#define WM8962_ADC_RETUNE_SCV                   0x0080  /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_MASK              0x0080  /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_SHIFT                  7  /* ADC_RETUNE_SCV */
+#define WM8962_ADC_RETUNE_SCV_WIDTH                  1  /* ADC_RETUNE_SCV */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_MASK 0x007F  /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_SHIFT      0  /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_22_16_WIDTH      7  /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
+
+/*
+ * R16385 (0x4001) - RETUNEADC_SHARED_COEFF_0
+ */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_MASK 0xFFFF  /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_SHIFT      0  /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEADC_SHARED_COEFF_15_00_WIDTH     16  /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
+
+/*
+ * R16386 (0x4002) - RETUNEDAC_SHARED_COEFF_1
+ */
+#define WM8962_DAC_RETUNE_SCV                   0x0080  /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_MASK              0x0080  /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_SHIFT                  7  /* DAC_RETUNE_SCV */
+#define WM8962_DAC_RETUNE_SCV_WIDTH                  1  /* DAC_RETUNE_SCV */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_MASK 0x007F  /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_SHIFT      0  /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_WIDTH      7  /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
+
+/*
+ * R16387 (0x4003) - RETUNEDAC_SHARED_COEFF_0
+ */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_MASK 0xFFFF  /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_SHIFT      0  /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_WIDTH     16  /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
+
+/*
+ * R16388 (0x4004) - SOUNDSTAGE_ENABLES_1
+ */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_MASK    0x00FF  /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_SHIFT        0  /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+#define WM8962_SOUNDSTAGE_ENABLES_23_16_WIDTH        8  /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
+
+/*
+ * R16389 (0x4005) - SOUNDSTAGE_ENABLES_0
+ */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_MASK    0xFFC0  /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_SHIFT        6  /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_SOUNDSTAGE_ENABLES_15_06_WIDTH       10  /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
+#define WM8962_RTN_ADC_ENA                      0x0020  /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_MASK                 0x0020  /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_SHIFT                     5  /* RTN_ADC_ENA */
+#define WM8962_RTN_ADC_ENA_WIDTH                     1  /* RTN_ADC_ENA */
+#define WM8962_RTN_DAC_ENA                      0x0010  /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_MASK                 0x0010  /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_SHIFT                     4  /* RTN_DAC_ENA */
+#define WM8962_RTN_DAC_ENA_WIDTH                     1  /* RTN_DAC_ENA */
+#define WM8962_HDBASS_ENA                       0x0008  /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_MASK                  0x0008  /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_SHIFT                      3  /* HDBASS_ENA */
+#define WM8962_HDBASS_ENA_WIDTH                      1  /* HDBASS_ENA */
+#define WM8962_HPF2_ENA                         0x0004  /* HPF2_ENA */
+#define WM8962_HPF2_ENA_MASK                    0x0004  /* HPF2_ENA */
+#define WM8962_HPF2_ENA_SHIFT                        2  /* HPF2_ENA */
+#define WM8962_HPF2_ENA_WIDTH                        1  /* HPF2_ENA */
+#define WM8962_HPF1_ENA                         0x0002  /* HPF1_ENA */
+#define WM8962_HPF1_ENA_MASK                    0x0002  /* HPF1_ENA */
+#define WM8962_HPF1_ENA_SHIFT                        1  /* HPF1_ENA */
+#define WM8962_HPF1_ENA_WIDTH                        1  /* HPF1_ENA */
+#define WM8962_VSS_ENA                          0x0001  /* VSS_ENA */
+#define WM8962_VSS_ENA_MASK                     0x0001  /* VSS_ENA */
+#define WM8962_VSS_ENA_SHIFT                         0  /* VSS_ENA */
+#define WM8962_VSS_ENA_WIDTH                         1  /* VSS_ENA */
+
+int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#endif
index a99620f..63f6dbf 100644 (file)
 
 #include "wm8971.h"
 
-#define WM8971_VERSION "0.9"
-
 #define        WM8971_REG_COUNT                43
 
 static struct workqueue_struct *wm8971_workq = NULL;
 
 /* codec private data */
 struct wm8971_priv {
+       enum snd_soc_control_type control_type;
        unsigned int sysclk;
 };
 
@@ -492,8 +491,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
        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 snd_soc_codec *codec = rtd->codec;
        struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
        u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
@@ -573,8 +571,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = {
        .set_sysclk     = wm8971_set_dai_sysclk,
 };
 
-struct snd_soc_dai wm8971_dai = {
-       .name = "WM8971",
+static struct snd_soc_dai_driver wm8971_dai = {
+       .name = "wm8971-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -589,7 +587,6 @@ struct snd_soc_dai wm8971_dai = {
                .formats = WM8971_FORMATS,},
        .ops = &wm8971_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8971_dai);
 
 static void wm8971_work(struct work_struct *work)
 {
@@ -598,19 +595,14 @@ static void wm8971_work(struct work_struct *work)
        wm8971_set_bias_level(codec, codec->bias_level);
 }
 
-static int wm8971_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8971_resume(struct platform_device *pdev)
+static int wm8971_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -639,37 +631,24 @@ 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_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int reg, ret = 0;
-
-       codec->name = "WM8971";
-       codec->owner = THIS_MODULE;
-       codec->set_bias_level = wm8971_set_bias_level;
-       codec->dai = &wm8971_dai;
-       codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
-       codec->num_dai = 1;
-       codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL);
-
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
+       struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
+       u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
-       wm8971_reset(codec);
+       INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
+       wm8971_workq = create_workqueue("wm8971");
+       if (wm8971_workq == NULL)
+               return -ENOMEM;
 
-       /* 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;
-       }
+       wm8971_reset(codec);
 
        /* charge output caps - set vmid to 5k for quick power up */
        reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
@@ -704,40 +683,54 @@ static int wm8971_init(struct snd_soc_device *socdev,
        wm8971_add_widgets(codec);
 
        return ret;
-
-err:
-       kfree(codec->reg_cache);
-       return ret;
 }
 
-/* If the i2c layer weren't so broken, we could pass this kind of data
-   around */
-static struct snd_soc_device *wm8971_socdev;
 
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+/* power down chip */
+static int wm8971_remove(struct snd_soc_codec *codec)
+{
+       wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       if (wm8971_workq)
+               destroy_workqueue(wm8971_workq);
+       return 0;
+}
 
-static int wm8971_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
+       .probe =        wm8971_probe,
+       .remove =       wm8971_remove,
+       .suspend =      wm8971_suspend,
+       .resume =       wm8971_resume,
+       .set_bias_level = wm8971_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8971_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8971_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = wm8971_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8971_priv *wm8971;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
+       wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+       if (wm8971 == NULL)
+               return -ENOMEM;
 
-       codec->control_data = i2c;
+       i2c_set_clientdata(i2c, wm8971);
 
-       ret = wm8971_init(socdev, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8971, &wm8971_dai, 1);
        if (ret < 0)
-               pr_err("failed to initialise WM8971\n");
-
+               kfree(wm8971);
        return ret;
 }
 
-static int wm8971_i2c_remove(struct i2c_client *client)
+static __devexit int wm8971_i2c_remove(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -749,148 +742,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
 
 static struct i2c_driver wm8971_i2c_driver = {
        .driver = {
-               .name = "WM8971 I2C Codec",
+               .name = "wm8971-codec",
                .owner = THIS_MODULE,
        },
-       .probe    = wm8971_i2c_probe,
-       .remove   = wm8971_i2c_remove,
+       .probe =    wm8971_i2c_probe,
+       .remove =   __devexit_p(wm8971_i2c_remove),
        .id_table = wm8971_i2c_id,
 };
-
-static int wm8971_add_i2c_device(struct platform_device *pdev,
-                                const struct wm8971_setup_data *setup)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&wm8971_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "wm8971", 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(&wm8971_i2c_driver);
-       return -ENODEV;
-}
-
 #endif
 
-static int wm8971_probe(struct platform_device *pdev)
+static int __init wm8971_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct wm8971_setup_data *setup;
-       struct snd_soc_codec *codec;
-       struct wm8971_priv *wm8971;
        int ret = 0;
-
-       pr_info("WM8971 Audio Codec %s", WM8971_VERSION);
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
-       if (wm8971 == NULL) {
-               kfree(codec);
-               return -ENOMEM;
-       }
-
-       snd_soc_codec_set_drvdata(codec, wm8971);
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       wm8971_socdev = socdev;
-
-       INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
-       wm8971_workq = create_workqueue("wm8971");
-       if (wm8971_workq == NULL) {
-               kfree(snd_soc_codec_get_drvdata(codec));
-               kfree(codec);
-               return -ENOMEM;
-       }
-
-#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               ret = wm8971_add_i2c_device(pdev, setup);
-       }
-#endif
-       /* Add other interfaces here */
-
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8971_i2c_driver);
        if (ret != 0) {
-               destroy_workqueue(wm8971_workq);
-               kfree(snd_soc_codec_get_drvdata(codec));
-               kfree(codec);
+               printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
+                      ret);
        }
-
-       return ret;
-}
-
-/* power down chip */
-static int wm8971_remove(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       if (wm8971_workq)
-               destroy_workqueue(wm8971_workq);
-       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(&wm8971_i2c_driver);
 #endif
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8971 = {
-       .probe =        wm8971_probe,
-       .remove =       wm8971_remove,
-       .suspend =      wm8971_suspend,
-       .resume =       wm8971_resume,
-};
-
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
-
-static int __init wm8971_modinit(void)
-{
-       return snd_soc_register_dai(&wm8971_dai);
+       return ret;
 }
 module_init(wm8971_modinit);
 
 static void __exit wm8971_exit(void)
 {
-       snd_soc_unregister_dai(&wm8971_dai);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8971_i2c_driver);
+#endif
 }
 module_exit(wm8971_exit);
 
index ef4f08f..f31c38f 100644 (file)
 
 #define WM8971_SYSCLK  0
 
-struct wm8971_setup_data {
-       int i2c_bus;
-       unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8971_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8971;
-
 #endif
index 1468fe1..b4363f6 100644 (file)
@@ -51,12 +51,10 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
 #define WM8974_POWER1_BUFIOEN 0x04
 
 struct wm8974_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        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" };
@@ -566,8 +564,8 @@ static struct snd_soc_dai_ops wm8974_ops = {
        .set_pll = wm8974_set_dai_pll,
 };
 
-struct snd_soc_dai wm8974_dai = {
-       .name = "WM8974 HiFi",
+static struct snd_soc_dai_driver wm8974_dai = {
+       .name = "wm8974-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -583,21 +581,15 @@ struct snd_soc_dai wm8974_dai = {
        .ops = &wm8974_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8974_dai);
 
-static int wm8974_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8974_suspend(struct snd_soc_codec *codec, 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)
+static int wm8974_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -613,156 +605,72 @@ static int wm8974_resume(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8974_probe(struct platform_device *pdev)
+static int wm8974_probe(struct snd_soc_codec *codec)
 {
-       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;
+       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);
+               return ret;
        }
 
-       socdev->card->codec = wm8974_codec;
-       codec = wm8974_codec;
-
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = wm8974_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+               dev_err(codec->dev, "Failed to issue reset\n");
+               return ret;
        }
 
+       wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        snd_soc_add_controls(codec, wm8974_snd_controls,
                             ARRAY_SIZE(wm8974_snd_controls));
        wm8974_add_widgets(codec);
 
        return ret;
-
-pcm_err:
-       return ret;
 }
 
 /* power down chip */
-static int wm8974_remove(struct platform_device *pdev)
+static int wm8974_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm8974 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
        .probe =        wm8974_probe,
        .remove =       wm8974_remove,
        .suspend =      wm8974_suspend,
        .resume =       wm8974_resume,
+       .set_bias_level = wm8974_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8974_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8974_reg,
 };
-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");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, 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;
-}
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 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;
+       int ret;
 
        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);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8974, &wm8974_dai, 1);
+       if (ret < 0)
+               kfree(wm8974);
+       return ret;
 }
 
 static __devexit int wm8974_i2c_remove(struct i2c_client *client)
 {
-       struct wm8974_priv *wm8974 = i2c_get_clientdata(client);
-       wm8974_unregister(wm8974);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -774,23 +682,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
 
 static struct i2c_driver wm8974_i2c_driver = {
        .driver = {
-               .name = "WM8974",
+               .name = "wm8974-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8974_i2c_probe,
        .remove =   __devexit_p(wm8974_i2c_remove),
        .id_table = wm8974_i2c_id,
 };
+#endif
 
 static int __init wm8974_modinit(void)
 {
-       return i2c_add_driver(&wm8974_i2c_driver);
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8974_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+       return ret;
 }
 module_init(wm8974_modinit);
 
 static void __exit wm8974_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8974_i2c_driver);
+#endif
 }
 module_exit(wm8974_exit);
 
index 896a7f0..3c94e7b 100644 (file)
@@ -83,7 +83,4 @@
 #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
index 8a1ad77..13b979a 100644 (file)
@@ -31,8 +31,6 @@
 
 #include "wm8978.h"
 
-static struct snd_soc_codec *wm8978_codec;
-
 /* wm8978 register cache. Note that register 0 is not included in the cache. */
 static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
        0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */
@@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
 
 /* codec private data */
 struct wm8978_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        unsigned int f_pllout;
        unsigned int f_mclk;
        unsigned int f_256fs;
@@ -374,8 +373,8 @@ struct wm8978_pll_div {
 
 #define FIXED_PLL_SIZE (1 << 24)
 
-static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,
-                       unsigned int source)
+static void pll_factors(struct snd_soc_codec *codec,
+               struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source)
 {
        u64 k_part;
        unsigned int k, n_div, n_mod;
@@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,
        }
 
        if (n_div < 6 || n_div > 12)
-               dev_warn(wm8978_codec->dev,
+               dev_warn(codec->dev,
                         "WM8978 N value exceeds recommended range! N = %u\n",
                         n_div);
 
@@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
        dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__,
                wm8978->f_mclk, wm8978->f_pllout);
 
-       pll_factors(&pll_div, f2, wm8978->f_mclk);
+       pll_factors(codec, &pll_div, f2, wm8978->f_mclk);
 
        dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n",
                __func__, pll_div.n, pll_div.k, pll_div.div2);
@@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
        /* Word length mask = 0x60 */
        u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
@@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = {
 };
 
 /* Also supports 12kHz */
-struct snd_soc_dai wm8978_dai = {
-       .name = "WM8978 HiFi",
-       .id = 1,
+static struct snd_soc_dai_driver wm8978_dai = {
+       .name = "wm8978-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = {
        },
        .ops = &wm8978_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8978_dai);
 
-static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
        /* Also switch PLL off */
        snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
@@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int wm8978_resume(struct platform_device *pdev)
+static int wm8978_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
        int i;
        u16 *cache = codec->reg_cache;
@@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8978_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8978_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8978_codec;
-       codec = wm8978_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, wm8978_snd_controls,
-                            ARRAY_SIZE(wm8978_snd_controls));
-       wm8978_add_widgets(codec);
-
-pcm_err:
-       return ret;
-}
-
-/* power down chip */
-static int wm8978_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_wm8978 = {
-       .probe          = wm8978_probe,
-       .remove         = wm8978_remove,
-       .suspend        = wm8978_suspend,
-       .resume         = wm8978_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978);
-
 /*
  * These registers contain an "update" bit - bit 8. This means, for example,
  * that one can write new DAC digital volume for both channels, but only when
@@ -1000,44 +943,23 @@ static const int update_reg[] = {
        WM8978_ROUT2_SPK_CONTROL,
 };
 
-static __devinit int wm8978_register(struct wm8978_priv *wm8978)
+static int wm8978_probe(struct snd_soc_codec *codec)
 {
-       int ret, i;
-       struct snd_soc_codec *codec = &wm8978->codec;
-
-       if (wm8978_codec) {
-               dev_err(codec->dev, "Another WM8978 is registered\n");
-               return -EINVAL;
-       }
+       struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+       int ret = 0, i;
 
        /*
         * Set default system clock to PLL, it is more precise, this is also the
         * default hardware setting
         */
        wm8978->sysclk = WM8978_PLL;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8978);
-       codec->name = "WM8978";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8978_set_bias_level;
-       codec->dai = &wm8978_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = WM8978_CACHEREGNUM;
-       codec->reg_cache = &wm8978->reg_cache;
-
+       codec->control_data = wm8978->control_data;
        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;
+               return ret;
        }
 
-       memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg));
-
        /*
         * Set the update bit in all registers, that have one. This way all
         * writes to those registers will also cause the update bit to be
@@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978)
        ret = snd_soc_write(codec, WM8978_RESET, 0);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               goto err;
+               return ret;
        }
 
-       wm8978_dai.dev = codec->dev;
-
        wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       wm8978_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(&wm8978_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+       snd_soc_add_controls(codec, wm8978_snd_controls,
+                            ARRAY_SIZE(wm8978_snd_controls));
+       wm8978_add_widgets(codec);
 
        return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       return ret;
 }
 
-static __devexit void wm8978_unregister(struct wm8978_priv *wm8978)
+/* power down chip */
+static int wm8978_remove(struct snd_soc_codec *codec)
 {
-       wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8978_dai);
-       snd_soc_unregister_codec(&wm8978->codec);
-       wm8978_codec = NULL;
+       wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
+       .probe =        wm8978_probe,
+       .remove =       wm8978_remove,
+       .suspend =      wm8978_suspend,
+       .resume =       wm8978_resume,
+       .set_bias_level = wm8978_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8978_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8978_reg,
+};
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
-       int ret;
        struct wm8978_priv *wm8978;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
        if (wm8978 == NULL)
                return -ENOMEM;
 
-       codec = &wm8978->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-
        i2c_set_clientdata(i2c, wm8978);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
+       wm8978->control_data = i2c;
 
-       ret = wm8978_register(wm8978);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8978, &wm8978_dai, 1);
        if (ret < 0)
                kfree(wm8978);
-
        return ret;
 }
 
 static __devexit int wm8978_i2c_remove(struct i2c_client *client)
 {
-       struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
-       wm8978_unregister(wm8978);
-       kfree(wm8978);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
 
 static struct i2c_driver wm8978_i2c_driver = {
        .driver = {
-               .name = "WM8978",
+               .name = "wm8978",
                .owner = THIS_MODULE,
        },
        .probe =    wm8978_i2c_probe,
        .remove =   __devexit_p(wm8978_i2c_remove),
        .id_table = wm8978_i2c_id,
 };
+#endif
 
 static int __init wm8978_modinit(void)
 {
-       return i2c_add_driver(&wm8978_i2c_driver);
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8978_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+       return ret;
 }
 module_init(wm8978_modinit);
 
 static void __exit wm8978_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8978_i2c_driver);
+#endif
 }
 module_exit(wm8978_exit);
 
index 56ec832..c75525b 100644 (file)
@@ -80,7 +80,4 @@ enum wm8978_sysclk_src {
        WM8978_MCLK
 };
 
-extern struct snd_soc_dai wm8978_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8978;
-
 #endif /* __WM8978_H__ */
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
new file mode 100644 (file)
index 0000000..fd2e7cc
--- /dev/null
@@ -0,0 +1,1192 @@
+/*
+ * wm8985.c  --  WM8985 ALSA SoC Audio driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * TODO:
+ *  o Add OUT3/OUT4 mixer controls.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8985.h"
+
+#define WM8985_NUM_SUPPLIES 4
+static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
+       "DCVDD",
+       "DBVDD",
+       "AVDD1",
+       "AVDD2"
+};
+
+static const u16 wm8985_reg_defs[] = {
+       0x0000,     /* R0  - Software Reset */
+       0x0000,     /* R1  - Power management 1 */
+       0x0000,     /* R2  - Power management 2 */
+       0x0000,     /* R3  - Power management 3 */
+       0x0050,     /* R4  - Audio Interface */
+       0x0000,     /* R5  - Companding control */
+       0x0140,     /* R6  - Clock Gen control */
+       0x0000,     /* R7  - Additional control */
+       0x0000,     /* R8  - GPIO Control */
+       0x0000,     /* R9  - Jack Detect Control 1 */
+       0x0000,     /* R10 - DAC Control */
+       0x00FF,     /* R11 - Left DAC digital Vol */
+       0x00FF,     /* R12 - Right DAC digital vol */
+       0x0000,     /* R13 - Jack Detect Control 2 */
+       0x0100,     /* R14 - ADC Control */
+       0x00FF,     /* R15 - Left ADC Digital Vol */
+       0x00FF,     /* R16 - Right ADC Digital Vol */
+       0x0000,     /* R17 */
+       0x012C,     /* R18 - EQ1 - low shelf */
+       0x002C,     /* R19 - EQ2 - peak 1 */
+       0x002C,     /* R20 - EQ3 - peak 2 */
+       0x002C,     /* R21 - EQ4 - peak 3 */
+       0x002C,     /* R22 - EQ5 - high shelf */
+       0x0000,     /* R23 */
+       0x0032,     /* R24 - DAC Limiter 1 */
+       0x0000,     /* R25 - DAC Limiter 2 */
+       0x0000,     /* R26 */
+       0x0000,     /* R27 - Notch Filter 1 */
+       0x0000,     /* R28 - Notch Filter 2 */
+       0x0000,     /* R29 - Notch Filter 3 */
+       0x0000,     /* R30 - Notch Filter 4 */
+       0x0000,     /* R31 */
+       0x0038,     /* R32 - ALC control 1 */
+       0x000B,     /* R33 - ALC control 2 */
+       0x0032,     /* R34 - ALC control 3 */
+       0x0000,     /* R35 - Noise Gate */
+       0x0008,     /* R36 - PLL N */
+       0x000C,     /* R37 - PLL K 1 */
+       0x0093,     /* R38 - PLL K 2 */
+       0x00E9,     /* R39 - PLL K 3 */
+       0x0000,     /* R40 */
+       0x0000,     /* R41 - 3D control */
+       0x0000,     /* R42 - OUT4 to ADC */
+       0x0000,     /* R43 - Beep control */
+       0x0033,     /* R44 - Input ctrl */
+       0x0010,     /* R45 - Left INP PGA gain ctrl */
+       0x0010,     /* R46 - Right INP PGA gain ctrl */
+       0x0100,     /* R47 - Left ADC BOOST ctrl */
+       0x0100,     /* R48 - Right ADC BOOST ctrl */
+       0x0002,     /* R49 - Output ctrl */
+       0x0001,     /* R50 - Left mixer ctrl */
+       0x0001,     /* R51 - Right mixer ctrl */
+       0x0039,     /* R52 - LOUT1 (HP) volume ctrl */
+       0x0039,     /* R53 - ROUT1 (HP) volume ctrl */
+       0x0039,     /* R54 - LOUT2 (SPK) volume ctrl */
+       0x0039,     /* R55 - ROUT2 (SPK) volume ctrl */
+       0x0001,     /* R56 - OUT3 mixer ctrl */
+       0x0001,     /* R57 - OUT4 (MONO) mix ctrl */
+       0x0001,     /* R58 */
+       0x0000,     /* R59 */
+       0x0004,     /* R60 - OUTPUT ctrl */
+       0x0000,     /* R61 - BIAS CTRL */
+       0x0180,     /* R62 */
+       0x0000      /* R63 */
+};
+
+/*
+ * latch bit 8 of these registers to ensure instant
+ * volume updates
+ */
+static const int volume_update_regs[] = {
+       WM8985_LEFT_DAC_DIGITAL_VOL,
+       WM8985_RIGHT_DAC_DIGITAL_VOL,
+       WM8985_LEFT_ADC_DIGITAL_VOL,
+       WM8985_RIGHT_ADC_DIGITAL_VOL,
+       WM8985_LOUT2_SPK_VOLUME_CTRL,
+       WM8985_ROUT2_SPK_VOLUME_CTRL,
+       WM8985_LOUT1_HP_VOLUME_CTRL,
+       WM8985_ROUT1_HP_VOLUME_CTRL,
+       WM8985_LEFT_INP_PGA_GAIN_CTRL,
+       WM8985_RIGHT_INP_PGA_GAIN_CTRL
+};
+
+struct wm8985_priv {
+       enum snd_soc_control_type control_type;
+       struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
+       unsigned int sysclk;
+       unsigned int bclk;
+};
+
+static const struct {
+       int div;
+       int ratio;
+} fs_ratios[] = {
+       { 10, 128 },
+       { 15, 192 },
+       { 20, 256 },
+       { 30, 384 },
+       { 40, 512 },
+       { 60, 768 },
+       { 80, 1024 },
+       { 120, 1536 }
+};
+
+static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 };
+
+static const int bclk_divs[] = {
+       1, 2, 4, 8, 16, 32
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol);
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol);
+
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0);
+static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0);
+static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0);
+static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0);
+static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
+
+static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
+static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7,
+                                 alc_sel_text);
+
+static const char *alc_mode_text[] = { "ALC", "Limiter" };
+static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8,
+                                 alc_mode_text);
+
+static const char *filter_mode_text[] = { "Audio", "Application" };
+static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7,
+                                 filter_mode_text);
+
+static const char *eq_bw_text[] = { "Narrow", "Wide" };
+static const char *eqmode_text[] = { "Capture", "Playback" };
+static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
+
+static const char *eq1_cutoff_text[] = {
+       "80Hz", "105Hz", "135Hz", "175Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5,
+                                 eq1_cutoff_text);
+static const char *eq2_cutoff_text[] = {
+       "230Hz", "300Hz", "385Hz", "500Hz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5,
+                                 eq2_cutoff_text);
+static const char *eq3_cutoff_text[] = {
+       "650Hz", "850Hz", "1.1kHz", "1.4kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5,
+                                 eq3_cutoff_text);
+static const char *eq4_cutoff_text[] = {
+       "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text);
+static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5,
+                                 eq4_cutoff_text);
+static const char *eq5_cutoff_text[] = {
+       "5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
+};
+static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5,
+                                 eq5_cutoff_text);
+
+static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
+static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
+
+static const char *depth_3d_text[] = {
+       "Off",
+       "6.67%",
+       "13.3%",
+       "20%",
+       "26.7%",
+       "33.3%",
+       "40%",
+       "46.6%",
+       "53.3%",
+       "60%",
+       "66.7%",
+       "73.3%",
+       "80%",
+       "86.7%",
+       "93.3%",
+       "100%"
+};
+static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0,
+                                 depth_3d_text);
+
+static const struct snd_kcontrol_new wm8985_snd_controls[] = {
+       SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL,
+               0, 1, 0),
+
+       SOC_ENUM("ALC Capture Function", alc_sel),
+       SOC_SINGLE_TLV("ALC Capture Max Volume", WM8985_ALC_CONTROL_1,
+               3, 7, 0, alc_max_tlv),
+       SOC_SINGLE_TLV("ALC Capture Min Volume", WM8985_ALC_CONTROL_1,
+               0, 7, 0, alc_min_tlv),
+       SOC_SINGLE_TLV("ALC Capture Target Volume", WM8985_ALC_CONTROL_2,
+               0, 15, 0, alc_tar_tlv),
+       SOC_SINGLE("ALC Capture Attack", WM8985_ALC_CONTROL_3, 0, 10, 0),
+       SOC_SINGLE("ALC Capture Hold", WM8985_ALC_CONTROL_2, 4, 10, 0),
+       SOC_SINGLE("ALC Capture Decay", WM8985_ALC_CONTROL_3, 4, 10, 0),
+       SOC_ENUM("ALC Mode", alc_mode),
+       SOC_SINGLE("ALC Capture NG Switch", WM8985_NOISE_GATE,
+               3, 1, 0),
+       SOC_SINGLE("ALC Capture NG Threshold", WM8985_NOISE_GATE,
+               0, 7, 1),
+
+       SOC_DOUBLE_R_TLV("Capture Volume", WM8985_LEFT_ADC_DIGITAL_VOL,
+               WM8985_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv),
+       SOC_DOUBLE_R("Capture PGA ZC Switch", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+               WM8985_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0),
+       SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+               WM8985_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv),
+
+       SOC_DOUBLE_R_TLV("Capture PGA Boost Volume",
+               WM8985_LEFT_ADC_BOOST_CTRL, WM8985_RIGHT_ADC_BOOST_CTRL,
+               8, 1, 0, pga_boost_tlv),
+
+       SOC_DOUBLE("ADC Inversion Switch", WM8985_ADC_CONTROL, 0, 1, 1, 0),
+       SOC_SINGLE("ADC 128x Oversampling Switch", WM8985_ADC_CONTROL, 8, 1, 0),
+
+       SOC_DOUBLE_R_TLV("Playback Volume", WM8985_LEFT_DAC_DIGITAL_VOL,
+               WM8985_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv),
+
+       SOC_SINGLE("DAC Playback Limiter Switch", WM8985_DAC_LIMITER_1, 8, 1, 0),
+       SOC_SINGLE("DAC Playback Limiter Decay", WM8985_DAC_LIMITER_1, 4, 10, 0),
+       SOC_SINGLE("DAC Playback Limiter Attack", WM8985_DAC_LIMITER_1, 0, 11, 0),
+       SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8985_DAC_LIMITER_2,
+               4, 7, 1, lim_thresh_tlv),
+       SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8985_DAC_LIMITER_2,
+               0, 12, 0, lim_boost_tlv),
+       SOC_DOUBLE("DAC Inversion Switch", WM8985_DAC_CONTROL, 0, 1, 1, 0),
+       SOC_SINGLE("DAC Auto Mute Switch", WM8985_DAC_CONTROL, 2, 1, 0),
+       SOC_SINGLE("DAC 128x Oversampling Switch", WM8985_DAC_CONTROL, 3, 1, 0),
+
+       SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8985_LOUT1_HP_VOLUME_CTRL,
+               WM8985_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv),
+       SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
+               WM8985_ROUT1_HP_VOLUME_CTRL, 7, 1, 0),
+       SOC_DOUBLE_R("Headphone Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
+               WM8985_ROUT1_HP_VOLUME_CTRL, 6, 1, 1),
+
+       SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8985_LOUT2_SPK_VOLUME_CTRL,
+               WM8985_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv),
+       SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
+               WM8985_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0),
+       SOC_DOUBLE_R("Speaker Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
+               WM8985_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1),
+
+       SOC_SINGLE("High Pass Filter Switch", WM8985_ADC_CONTROL, 8, 1, 0),
+       SOC_ENUM("High Pass Filter Mode", filter_mode),
+       SOC_SINGLE("High Pass Filter Cutoff", WM8985_ADC_CONTROL, 4, 7, 0),
+
+       SOC_DOUBLE_R_TLV("Aux Bypass Volume",
+               WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0,
+               aux_tlv),
+
+       SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",
+               WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 2, 7, 0,
+               bypass_tlv),
+
+       SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put),
+       SOC_ENUM("EQ1 Cutoff", eq1_cutoff),
+       SOC_SINGLE_TLV("EQ1 Volume", WM8985_EQ1_LOW_SHELF,  0, 24, 1, eq_tlv),
+       SOC_ENUM("EQ2 Bandwith", eq2_bw),
+       SOC_ENUM("EQ2 Cutoff", eq2_cutoff),
+       SOC_SINGLE_TLV("EQ2 Volume", WM8985_EQ2_PEAK_1, 0, 24, 1, eq_tlv),
+       SOC_ENUM("EQ3 Bandwith", eq3_bw),
+       SOC_ENUM("EQ3 Cutoff", eq3_cutoff),
+       SOC_SINGLE_TLV("EQ3 Volume", WM8985_EQ3_PEAK_2, 0, 24, 1, eq_tlv),
+       SOC_ENUM("EQ4 Bandwith", eq4_bw),
+       SOC_ENUM("EQ4 Cutoff", eq4_cutoff),
+       SOC_SINGLE_TLV("EQ4 Volume", WM8985_EQ4_PEAK_3, 0, 24, 1, eq_tlv),
+       SOC_ENUM("EQ5 Cutoff", eq5_cutoff),
+       SOC_SINGLE_TLV("EQ5 Volume", WM8985_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
+
+       SOC_ENUM("3D Depth", depth_3d),
+
+       SOC_ENUM("Speaker Mode", speaker_mode)
+};
+
+static const struct snd_kcontrol_new left_out_mixer[] = {
+       SOC_DAPM_SINGLE("Line Switch", WM8985_LEFT_MIXER_CTRL, 1, 1, 0),
+       SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0),
+       SOC_DAPM_SINGLE("PCM Switch", WM8985_LEFT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_out_mixer[] = {
+       SOC_DAPM_SINGLE("Line Switch", WM8985_RIGHT_MIXER_CTRL, 1, 1, 0),
+       SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0),
+       SOC_DAPM_SINGLE("PCM Switch", WM8985_RIGHT_MIXER_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_input_mixer[] = {
+       SOC_DAPM_SINGLE("L2 Switch", WM8985_INPUT_CTRL, 2, 1, 0),
+       SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 1, 1, 0),
+       SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_input_mixer[] = {
+       SOC_DAPM_SINGLE("R2 Switch", WM8985_INPUT_CTRL, 6, 1, 0),
+       SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 5, 1, 0),
+       SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_boost_mixer[] = {
+       SOC_DAPM_SINGLE_TLV("L2 Volume", WM8985_LEFT_ADC_BOOST_CTRL,
+               4, 7, 0, boost_tlv),
+       SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8985_LEFT_ADC_BOOST_CTRL,
+               0, 7, 0, boost_tlv)
+};
+
+static const struct snd_kcontrol_new right_boost_mixer[] = {
+       SOC_DAPM_SINGLE_TLV("R2 Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
+               4, 7, 0, boost_tlv),
+       SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
+               0, 7, 0, boost_tlv)
+};
+
+static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
+       SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8985_POWER_MANAGEMENT_3,
+               0, 0),
+       SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8985_POWER_MANAGEMENT_3,
+               1, 0),
+       SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8985_POWER_MANAGEMENT_2,
+               0, 0),
+       SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8985_POWER_MANAGEMENT_2,
+               1, 0),
+
+       SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
+               2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
+       SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
+               3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
+
+       SND_SOC_DAPM_MIXER("Left Input Mixer", WM8985_POWER_MANAGEMENT_2,
+               2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),
+       SND_SOC_DAPM_MIXER("Right Input Mixer", WM8985_POWER_MANAGEMENT_2,
+               3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),
+
+       SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
+               4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
+       SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
+               5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
+
+       SND_SOC_DAPM_PGA("Left Capture PGA", WM8985_LEFT_INP_PGA_GAIN_CTRL,
+               6, 1, NULL, 0),
+       SND_SOC_DAPM_PGA("Right Capture PGA", WM8985_RIGHT_INP_PGA_GAIN_CTRL,
+               6, 1, NULL, 0),
+
+       SND_SOC_DAPM_PGA("Left Headphone Out", WM8985_POWER_MANAGEMENT_2,
+               7, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right Headphone Out", WM8985_POWER_MANAGEMENT_2,
+               8, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("Left Speaker Out", WM8985_POWER_MANAGEMENT_3,
+               5, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
+               6, 0, NULL, 0),
+
+       SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
+
+       SND_SOC_DAPM_INPUT("LIN"),
+       SND_SOC_DAPM_INPUT("LIP"),
+       SND_SOC_DAPM_INPUT("RIN"),
+       SND_SOC_DAPM_INPUT("RIP"),
+       SND_SOC_DAPM_INPUT("AUXL"),
+       SND_SOC_DAPM_INPUT("AUXR"),
+       SND_SOC_DAPM_INPUT("L2"),
+       SND_SOC_DAPM_INPUT("R2"),
+       SND_SOC_DAPM_OUTPUT("HPL"),
+       SND_SOC_DAPM_OUTPUT("HPR"),
+       SND_SOC_DAPM_OUTPUT("SPKL"),
+       SND_SOC_DAPM_OUTPUT("SPKR")
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       { "Right Output Mixer", "PCM Switch", "Right DAC" },
+       { "Right Output Mixer", "Aux Switch", "AUXR" },
+       { "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
+
+       { "Left Output Mixer", "PCM Switch", "Left DAC" },
+       { "Left Output Mixer", "Aux Switch", "AUXL" },
+       { "Left Output Mixer", "Line Switch", "Left Boost Mixer" },
+
+       { "Right Headphone Out", NULL, "Right Output Mixer" },
+       { "HPR", NULL, "Right Headphone Out" },
+
+       { "Left Headphone Out", NULL, "Left Output Mixer" },
+       { "HPL", NULL, "Left Headphone Out" },
+
+       { "Right Speaker Out", NULL, "Right Output Mixer" },
+       { "SPKR", NULL, "Right Speaker Out" },
+
+       { "Left Speaker Out", NULL, "Left Output Mixer" },
+       { "SPKL", NULL, "Left Speaker Out" },
+
+       { "Right ADC", NULL, "Right Boost Mixer" },
+
+       { "Right Boost Mixer", "AUXR Volume", "AUXR" },
+       { "Right Boost Mixer", NULL, "Right Capture PGA" },
+       { "Right Boost Mixer", "R2 Volume", "R2" },
+
+       { "Left ADC", NULL, "Left Boost Mixer" },
+
+       { "Left Boost Mixer", "AUXL Volume", "AUXL" },
+       { "Left Boost Mixer", NULL, "Left Capture PGA" },
+       { "Left Boost Mixer", "L2 Volume", "L2" },
+
+       { "Right Capture PGA", NULL, "Right Input Mixer" },
+       { "Left Capture PGA", NULL, "Left Input Mixer" },
+
+       { "Right Input Mixer", "R2 Switch", "R2" },
+       { "Right Input Mixer", "MicN Switch", "RIN" },
+       { "Right Input Mixer", "MicP Switch", "RIP" },
+
+       { "Left Input Mixer", "L2 Switch", "L2" },
+       { "Left Input Mixer", "MicN Switch", "LIN" },
+       { "Left Input Mixer", "MicP Switch", "LIP" },
+};
+
+static int eqmode_get(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int reg;
+
+       reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
+       if (reg & WM8985_EQ3DMODE)
+               ucontrol->value.integer.value[0] = 1;
+       else
+               ucontrol->value.integer.value[0] = 0;
+
+       return 0;
+}
+
+static int eqmode_put(struct snd_kcontrol *kcontrol,
+                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       unsigned int regpwr2, regpwr3;
+       unsigned int reg_eq;
+
+       if (ucontrol->value.integer.value[0] != 0
+                       && ucontrol->value.integer.value[0] != 1)
+               return -EINVAL;
+
+       reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
+       switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) {
+       case 0:
+               if (!ucontrol->value.integer.value[0])
+                       return 0;
+               break;
+       case 1:
+               if (ucontrol->value.integer.value[0])
+                       return 0;
+               break;
+       }
+
+       regpwr2 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_2);
+       regpwr3 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_3);
+       /* disable the DACs and ADCs */
+       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_2,
+                           WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0);
+       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_3,
+                           WM8985_DACENR_MASK | WM8985_DACENL_MASK, 0);
+       snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
+                           WM8985_M128ENB_MASK, WM8985_M128ENB);
+       /* set the desired eqmode */
+       snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF,
+                           WM8985_EQ3DMODE_MASK,
+                           ucontrol->value.integer.value[0]
+                           << WM8985_EQ3DMODE_SHIFT);
+       /* restore DAC/ADC configuration */
+       snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2);
+       snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, regpwr3);
+       return 0;
+}
+
+static int wm8985_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, wm8985_dapm_widgets,
+                                 ARRAY_SIZE(wm8985_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map,
+                               ARRAY_SIZE(audio_map));
+       return 0;
+}
+
+static int wm8985_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
+}
+
+static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+
+       return snd_soc_update_bits(codec, WM8985_DAC_CONTROL,
+                                  WM8985_SOFTMUTE_MASK,
+                                  !!mute << WM8985_SOFTMUTE_SHIFT);
+}
+
+static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec;
+       u16 format, master, bcp, lrp;
+
+       codec = dai->codec;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               format = 0x2;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               format = 0x0;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               format = 0x1;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               format = 0x3;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown dai format\n");
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+                           WM8985_FMT_MASK, format << WM8985_FMT_SHIFT);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               master = 0;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown master/slave configuration\n");
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                           WM8985_MS_MASK, master << WM8985_MS_SHIFT);
+
+       /* frame inversion is not valid for dsp modes */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_IB_IF:
+               case SND_SOC_DAIFMT_NB_IF:
+                       return -EINVAL;
+               default:
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+
+       bcp = lrp = 0;
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               bcp = lrp = 1;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               bcp = 1;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               lrp = 1;
+               break;
+       default:
+               dev_err(dai->dev, "Unknown polarity configuration\n");
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+                           WM8985_LRP_MASK, lrp << WM8985_LRP_SHIFT);
+       snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+                           WM8985_BCP_MASK, bcp << WM8985_BCP_SHIFT);
+       return 0;
+}
+
+static int wm8985_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       int i;
+       struct snd_soc_codec *codec;
+       struct wm8985_priv *wm8985;
+       u16 blen, srate_idx;
+       unsigned int tmp;
+       int srate_best;
+
+       codec = dai->codec;
+       wm8985 = snd_soc_codec_get_drvdata(codec);
+
+       wm8985->bclk = snd_soc_params_to_bclk(params);
+       if ((int)wm8985->bclk < 0)
+               return wm8985->bclk;
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               blen = 0x0;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               blen = 0x1;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               blen = 0x2;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               blen = 0x3;
+               break;
+       default:
+               dev_err(dai->dev, "Unsupported word length %u\n",
+                       params_format(params));
+               return -EINVAL;
+       }
+
+       snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
+                           WM8985_WL_MASK, blen << WM8985_WL_SHIFT);
+
+       /*
+        * match to the nearest possible sample rate and rely
+        * on the array index to configure the SR register
+        */
+       srate_idx = 0;
+       srate_best = abs(srates[0] - params_rate(params));
+       for (i = 1; i < ARRAY_SIZE(srates); ++i) {
+               if (abs(srates[i] - params_rate(params)) >= srate_best)
+                       continue;
+               srate_idx = i;
+               srate_best = abs(srates[i] - params_rate(params));
+       }
+
+       dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]);
+       snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
+                           WM8985_SR_MASK, srate_idx << WM8985_SR_SHIFT);
+
+       dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8985->bclk);
+       dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8985->sysclk);
+
+       for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) {
+               if (wm8985->sysclk / params_rate(params)
+                               == fs_ratios[i].ratio)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(fs_ratios)) {
+               dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n",
+                       wm8985->sysclk, params_rate(params));
+               return -EINVAL;
+       }
+
+       dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio);
+       snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                           WM8985_MCLKDIV_MASK, i << WM8985_MCLKDIV_SHIFT);
+
+       /* select the appropriate bclk divider */
+       tmp = (wm8985->sysclk / fs_ratios[i].div) * 10;
+       for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) {
+               if (wm8985->bclk == tmp / bclk_divs[i])
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(bclk_divs)) {
+               dev_err(dai->dev, "No matching BCLK divider found\n");
+               return -EINVAL;
+       }
+
+       dev_dbg(dai->dev, "BCLK div = %d\n", i);
+       snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                           WM8985_BCLKDIV_MASK, i << WM8985_BCLKDIV_SHIFT);
+       return 0;
+}
+
+struct pll_div {
+       u32 div2:1;
+       u32 n:4;
+       u32 k:24;
+};
+
+#define FIXED_PLL_SIZE ((1ULL << 24) * 10)
+static int pll_factors(struct pll_div *pll_div, unsigned int target,
+                      unsigned int source)
+{
+       u64 Kpart;
+       unsigned long int K, Ndiv, Nmod;
+
+       pll_div->div2 = 0;
+       Ndiv = target / source;
+       if (Ndiv < 6) {
+               source >>= 1;
+               pll_div->div2 = 1;
+               Ndiv = target / source;
+       }
+
+       if (Ndiv < 6 || Ndiv > 12) {
+               printk(KERN_ERR "%s: WM8985 N value is not within"
+                      " the recommended range: %lu\n", __func__, Ndiv);
+               return -EINVAL;
+       }
+       pll_div->n = Ndiv;
+
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (u64)Nmod;
+
+       do_div(Kpart, source);
+
+       K = Kpart & 0xffffffff;
+       if ((K % 10) >= 5)
+               K += 5;
+       K /= 10;
+       pll_div->k = K;
+
+       return 0;
+}
+
+static int wm8985_set_pll(struct snd_soc_dai *dai, int pll_id,
+                         int source, unsigned int freq_in,
+                         unsigned int freq_out)
+{
+       int ret;
+       struct snd_soc_codec *codec;
+       struct pll_div pll_div;
+
+       codec = dai->codec;
+       if (freq_in && freq_out) {
+               ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);
+               if (ret)
+                       return ret;
+       }
+
+       /* disable the PLL before reprogramming it */
+       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                           WM8985_PLLEN_MASK, 0);
+       
+       if (!freq_in || !freq_out)
+               return 0;
+
+       /* set PLLN and PRESCALE */
+       snd_soc_write(codec, WM8985_PLL_N,
+                     (pll_div.div2 << WM8985_PLL_PRESCALE_SHIFT)
+                     | pll_div.n);
+       /* set PLLK */
+       snd_soc_write(codec, WM8985_PLL_K_3, pll_div.k & 0x1ff);
+       snd_soc_write(codec, WM8985_PLL_K_2, (pll_div.k >> 9) & 0x1ff);
+       snd_soc_write(codec, WM8985_PLL_K_1, (pll_div.k >> 18));
+       /* set the source of the clock to be the PLL */
+       snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                           WM8985_CLKSEL_MASK, WM8985_CLKSEL);
+       /* enable the PLL */
+       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                           WM8985_PLLEN_MASK, WM8985_PLLEN);
+       return 0;
+}
+
+static int wm8985_set_sysclk(struct snd_soc_dai *dai,
+                            int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec;
+       struct wm8985_priv *wm8985;
+
+       codec = dai->codec;
+       wm8985 = snd_soc_codec_get_drvdata(codec);
+
+       switch (clk_id) {
+       case WM8985_CLKSRC_MCLK:
+               snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                                   WM8985_CLKSEL_MASK, 0);
+               snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                   WM8985_PLLEN_MASK, 0);
+               break;
+       case WM8985_CLKSRC_PLL:
+               snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
+                                   WM8985_CLKSEL_MASK, WM8985_CLKSEL);
+               break;
+       default:
+               dev_err(dai->dev, "Unknown clock source %d\n", clk_id);
+               return -EINVAL;
+       }
+
+       wm8985->sysclk = freq;
+       return 0;
+}
+
+static void wm8985_sync_cache(struct snd_soc_codec *codec)
+{
+       short i;
+       u16 *cache;
+
+       if (!codec->cache_sync)
+               return;
+       codec->cache_only = 0;
+       /* restore cache */
+       cache = codec->reg_cache;
+       for (i = 0; i < codec->driver->reg_cache_size; i++) {
+               if (i == WM8985_SOFTWARE_RESET
+                               || cache[i] == wm8985_reg_defs[i])
+                       continue;
+               snd_soc_write(codec, i, cache[i]);
+       }
+       codec->cache_sync = 0;
+}
+
+static int wm8985_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       int ret;
+       struct wm8985_priv *wm8985;
+
+       wm8985 = snd_soc_codec_get_drvdata(codec);
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               /* VMID at 75k */
+               snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                   WM8985_VMIDSEL_MASK,
+                                   1 << WM8985_VMIDSEL_SHIFT);
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
+                                                   wm8985->supplies);
+                       if (ret) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       wm8985_sync_cache(codec);
+
+                       /* enable anti-pop features */
+                       snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
+                                           WM8985_POBCTRL_MASK,
+                                           WM8985_POBCTRL);
+                       /* enable thermal shutdown */
+                       snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+                                           WM8985_TSDEN_MASK, WM8985_TSDEN);
+                       snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+                                           WM8985_TSOPCTRL_MASK,
+                                           WM8985_TSOPCTRL);
+                       /* enable BIASEN */
+                       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                           WM8985_BIASEN_MASK, WM8985_BIASEN);
+                       /* VMID at 75k */
+                       snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                           WM8985_VMIDSEL_MASK,
+                                           1 << WM8985_VMIDSEL_SHIFT);
+                       msleep(500);
+                       /* disable anti-pop features */
+                       snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
+                                           WM8985_POBCTRL_MASK, 0);
+               }
+               /* VMID at 300k */
+               snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                   WM8985_VMIDSEL_MASK,
+                                   2 << WM8985_VMIDSEL_SHIFT);
+               break;
+       case SND_SOC_BIAS_OFF:
+               /* disable thermal shutdown */
+               snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+                                   WM8985_TSOPCTRL_MASK, 0);
+               snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
+                                   WM8985_TSDEN_MASK, 0);
+               /* disable VMIDSEL and BIASEN */
+               snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
+                                   WM8985_VMIDSEL_MASK | WM8985_BIASEN_MASK,
+                                   0);
+               snd_soc_write(codec, WM8985_POWER_MANAGEMENT_1, 0);
+               snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
+               snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
+
+               codec->cache_sync = 1;
+
+               regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
+                                      wm8985->supplies);
+               break;
+       }
+
+       codec->bias_level = level;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+       wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8985_resume(struct snd_soc_codec *codec)
+{
+       wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+}
+#else
+#define wm8985_suspend NULL
+#define wm8985_resume NULL
+#endif
+
+static int wm8985_remove(struct snd_soc_codec *codec)
+{
+       struct wm8985_priv *wm8985;
+
+       wm8985 = snd_soc_codec_get_drvdata(codec);
+       wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+       return 0;
+}
+
+static int wm8985_probe(struct snd_soc_codec *codec)
+{
+       size_t i;
+       struct wm8985_priv *wm8985;
+       int ret;
+       u16 *cache;
+
+       wm8985 = snd_soc_codec_get_drvdata(codec);
+
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++)
+               wm8985->supplies[i].supply = wm8985_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies),
+                                wm8985->supplies);
+       if (ret) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
+                                   wm8985->supplies);
+       if (ret) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_reg_get;
+       }
+
+       ret = wm8985_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               goto err_reg_enable;
+       }
+
+       cache = codec->reg_cache;
+       /* latch volume update bits */
+       for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
+               cache[volume_update_regs[i]] |= 0x100;
+       /* enable BIASCUT */
+       cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
+       codec->cache_sync = 1;
+
+       snd_soc_add_controls(codec, wm8985_snd_controls,
+                            ARRAY_SIZE(wm8985_snd_controls));
+       wm8985_add_widgets(codec);
+
+       wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       return 0;
+
+err_reg_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+err_reg_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
+       return ret;
+}
+
+static struct snd_soc_dai_ops wm8985_dai_ops = {
+       .digital_mute = wm8985_dac_mute,
+       .hw_params = wm8985_hw_params,
+       .set_fmt = wm8985_set_fmt,
+       .set_sysclk = wm8985_set_sysclk,
+       .set_pll = wm8985_set_pll
+};
+
+#define WM8985_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_driver wm8985_dai = {
+       .name = "wm8985-hifi",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = WM8985_FORMATS,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = WM8985_FORMATS,
+       },
+       .ops = &wm8985_dai_ops,
+       .symmetric_rates = 1
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
+       .probe = wm8985_probe,
+       .remove = wm8985_remove,
+       .suspend = wm8985_suspend,
+       .resume = wm8985_resume,
+       .set_bias_level = wm8985_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8985_reg_defs
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8985_spi_probe(struct spi_device *spi)
+{
+       struct wm8985_priv *wm8985;
+       int ret;
+
+       wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+       if (!wm8985)
+               return -ENOMEM;
+
+       wm8985->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8985);
+
+       ret = snd_soc_register_codec(&spi->dev,
+                                    &soc_codec_dev_wm8985, &wm8985_dai, 1);
+       if (ret < 0)
+               kfree(wm8985);
+       return ret;
+}
+
+static int __devexit wm8985_spi_remove(struct spi_device *spi)
+{
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
+       return 0;
+}
+
+static struct spi_driver wm8985_spi_driver = {
+       .driver = {
+               .name = "wm8985",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm8985_spi_probe,
+       .remove = __devexit_p(wm8985_spi_remove)
+};
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8985_priv *wm8985;
+       int ret;
+
+       wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+       if (!wm8985)
+               return -ENOMEM;
+
+       wm8985->control_type = SND_SOC_I2C;
+       i2c_set_clientdata(i2c, wm8985);
+
+       ret = snd_soc_register_codec(&i2c->dev,
+                                    &soc_codec_dev_wm8985, &wm8985_dai, 1);
+       if (ret < 0)
+               kfree(wm8985);
+       return ret;
+}
+
+static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+{
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
+       return 0;
+}
+
+static const struct i2c_device_id wm8985_i2c_id[] = {
+       { "wm8985", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
+
+static struct i2c_driver wm8985_i2c_driver = {
+       .driver = {
+               .name = "wm8985",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm8985_i2c_probe,
+       .remove = __devexit_p(wm8985_i2c_remove),
+       .id_table = wm8985_i2c_id
+};
+#endif
+
+static int __init wm8985_modinit(void)
+{
+       int ret = 0;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8985_i2c_driver);
+       if (ret) {
+               printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       ret = spi_register_driver(&wm8985_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register wm8985 SPI driver: %d\n",
+                      ret);
+       }
+#endif
+       return ret;
+}
+module_init(wm8985_modinit);
+
+static void __exit wm8985_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8985_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8985_spi_driver);
+#endif
+}
+module_exit(wm8985_exit);
+
+MODULE_DESCRIPTION("ASoC WM8985 driver");
+MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8985.h b/sound/soc/codecs/wm8985.h
new file mode 100644 (file)
index 0000000..2e71ff5
--- /dev/null
@@ -0,0 +1,1045 @@
+/*
+ * wm8985.h  --  WM8985 ASoC driver
+ *
+ * Copyright 2010 Wolfson Microelectronics plc
+ *
+ * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WM8985_H
+#define _WM8985_H
+
+#define WM8985_SOFTWARE_RESET                   0x00
+#define WM8985_POWER_MANAGEMENT_1               0x01
+#define WM8985_POWER_MANAGEMENT_2               0x02
+#define WM8985_POWER_MANAGEMENT_3               0x03
+#define WM8985_AUDIO_INTERFACE                  0x04
+#define WM8985_COMPANDING_CONTROL               0x05
+#define WM8985_CLOCK_GEN_CONTROL                0x06
+#define WM8985_ADDITIONAL_CONTROL               0x07
+#define WM8985_GPIO_CONTROL                     0x08
+#define WM8985_JACK_DETECT_CONTROL_1            0x09
+#define WM8985_DAC_CONTROL                      0x0A
+#define WM8985_LEFT_DAC_DIGITAL_VOL             0x0B
+#define WM8985_RIGHT_DAC_DIGITAL_VOL            0x0C
+#define WM8985_JACK_DETECT_CONTROL_2            0x0D
+#define WM8985_ADC_CONTROL                      0x0E
+#define WM8985_LEFT_ADC_DIGITAL_VOL             0x0F
+#define WM8985_RIGHT_ADC_DIGITAL_VOL            0x10
+#define WM8985_EQ1_LOW_SHELF                    0x12
+#define WM8985_EQ2_PEAK_1                       0x13
+#define WM8985_EQ3_PEAK_2                       0x14
+#define WM8985_EQ4_PEAK_3                       0x15
+#define WM8985_EQ5_HIGH_SHELF                   0x16
+#define WM8985_DAC_LIMITER_1                    0x18
+#define WM8985_DAC_LIMITER_2                    0x19
+#define WM8985_NOTCH_FILTER_1                   0x1B
+#define WM8985_NOTCH_FILTER_2                   0x1C
+#define WM8985_NOTCH_FILTER_3                   0x1D
+#define WM8985_NOTCH_FILTER_4                   0x1E
+#define WM8985_ALC_CONTROL_1                    0x20
+#define WM8985_ALC_CONTROL_2                    0x21
+#define WM8985_ALC_CONTROL_3                    0x22
+#define WM8985_NOISE_GATE                       0x23
+#define WM8985_PLL_N                            0x24
+#define WM8985_PLL_K_1                          0x25
+#define WM8985_PLL_K_2                          0x26
+#define WM8985_PLL_K_3                          0x27
+#define WM8985_3D_CONTROL                       0x29
+#define WM8985_OUT4_TO_ADC                      0x2A
+#define WM8985_BEEP_CONTROL                     0x2B
+#define WM8985_INPUT_CTRL                       0x2C
+#define WM8985_LEFT_INP_PGA_GAIN_CTRL           0x2D
+#define WM8985_RIGHT_INP_PGA_GAIN_CTRL          0x2E
+#define WM8985_LEFT_ADC_BOOST_CTRL              0x2F
+#define WM8985_RIGHT_ADC_BOOST_CTRL             0x30
+#define WM8985_OUTPUT_CTRL0                     0x31
+#define WM8985_LEFT_MIXER_CTRL                  0x32
+#define WM8985_RIGHT_MIXER_CTRL                 0x33
+#define WM8985_LOUT1_HP_VOLUME_CTRL             0x34
+#define WM8985_ROUT1_HP_VOLUME_CTRL             0x35
+#define WM8985_LOUT2_SPK_VOLUME_CTRL            0x36
+#define WM8985_ROUT2_SPK_VOLUME_CTRL            0x37
+#define WM8985_OUT3_MIXER_CTRL                  0x38
+#define WM8985_OUT4_MONO_MIX_CTRL               0x39
+#define WM8985_OUTPUT_CTRL1                     0x3C
+#define WM8985_BIAS_CTRL                        0x3D
+
+#define WM8985_REGISTER_COUNT                   59
+#define WM8985_MAX_REGISTER                     0x3F
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8985_SOFTWARE_RESET_MASK              0x01FF  /* SOFTWARE_RESET - [8:0] */
+#define WM8985_SOFTWARE_RESET_SHIFT                  0  /* SOFTWARE_RESET - [8:0] */
+#define WM8985_SOFTWARE_RESET_WIDTH                  9  /* SOFTWARE_RESET - [8:0] */
+
+/*
+ * R1 (0x01) - Power management 1
+ */
+#define WM8985_OUT4MIXEN                        0x0080  /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_MASK                   0x0080  /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_SHIFT                       7  /* OUT4MIXEN */
+#define WM8985_OUT4MIXEN_WIDTH                       1  /* OUT4MIXEN */
+#define WM8985_OUT3MIXEN                        0x0040  /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_MASK                   0x0040  /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_SHIFT                       6  /* OUT3MIXEN */
+#define WM8985_OUT3MIXEN_WIDTH                       1  /* OUT3MIXEN */
+#define WM8985_PLLEN                            0x0020  /* PLLEN */
+#define WM8985_PLLEN_MASK                       0x0020  /* PLLEN */
+#define WM8985_PLLEN_SHIFT                           5  /* PLLEN */
+#define WM8985_PLLEN_WIDTH                           1  /* PLLEN */
+#define WM8985_MICBEN                           0x0010  /* MICBEN */
+#define WM8985_MICBEN_MASK                      0x0010  /* MICBEN */
+#define WM8985_MICBEN_SHIFT                          4  /* MICBEN */
+#define WM8985_MICBEN_WIDTH                          1  /* MICBEN */
+#define WM8985_BIASEN                           0x0008  /* BIASEN */
+#define WM8985_BIASEN_MASK                      0x0008  /* BIASEN */
+#define WM8985_BIASEN_SHIFT                          3  /* BIASEN */
+#define WM8985_BIASEN_WIDTH                          1  /* BIASEN */
+#define WM8985_BUFIOEN                          0x0004  /* BUFIOEN */
+#define WM8985_BUFIOEN_MASK                     0x0004  /* BUFIOEN */
+#define WM8985_BUFIOEN_SHIFT                         2  /* BUFIOEN */
+#define WM8985_BUFIOEN_WIDTH                         1  /* BUFIOEN */
+#define WM8985_VMIDSEL                          0x0003  /* VMIDSEL */
+#define WM8985_VMIDSEL_MASK                     0x0003  /* VMIDSEL - [1:0] */
+#define WM8985_VMIDSEL_SHIFT                         0  /* VMIDSEL - [1:0] */
+#define WM8985_VMIDSEL_WIDTH                         2  /* VMIDSEL - [1:0] */
+
+/*
+ * R2 (0x02) - Power management 2
+ */
+#define WM8985_ROUT1EN                          0x0100  /* ROUT1EN */
+#define WM8985_ROUT1EN_MASK                     0x0100  /* ROUT1EN */
+#define WM8985_ROUT1EN_SHIFT                         8  /* ROUT1EN */
+#define WM8985_ROUT1EN_WIDTH                         1  /* ROUT1EN */
+#define WM8985_LOUT1EN                          0x0080  /* LOUT1EN */
+#define WM8985_LOUT1EN_MASK                     0x0080  /* LOUT1EN */
+#define WM8985_LOUT1EN_SHIFT                         7  /* LOUT1EN */
+#define WM8985_LOUT1EN_WIDTH                         1  /* LOUT1EN */
+#define WM8985_SLEEP                            0x0040  /* SLEEP */
+#define WM8985_SLEEP_MASK                       0x0040  /* SLEEP */
+#define WM8985_SLEEP_SHIFT                           6  /* SLEEP */
+#define WM8985_SLEEP_WIDTH                           1  /* SLEEP */
+#define WM8985_BOOSTENR                         0x0020  /* BOOSTENR */
+#define WM8985_BOOSTENR_MASK                    0x0020  /* BOOSTENR */
+#define WM8985_BOOSTENR_SHIFT                        5  /* BOOSTENR */
+#define WM8985_BOOSTENR_WIDTH                        1  /* BOOSTENR */
+#define WM8985_BOOSTENL                         0x0010  /* BOOSTENL */
+#define WM8985_BOOSTENL_MASK                    0x0010  /* BOOSTENL */
+#define WM8985_BOOSTENL_SHIFT                        4  /* BOOSTENL */
+#define WM8985_BOOSTENL_WIDTH                        1  /* BOOSTENL */
+#define WM8985_INPGAENR                         0x0008  /* INPGAENR */
+#define WM8985_INPGAENR_MASK                    0x0008  /* INPGAENR */
+#define WM8985_INPGAENR_SHIFT                        3  /* INPGAENR */
+#define WM8985_INPGAENR_WIDTH                        1  /* INPGAENR */
+#define WM8985_INPPGAENL                        0x0004  /* INPPGAENL */
+#define WM8985_INPPGAENL_MASK                   0x0004  /* INPPGAENL */
+#define WM8985_INPPGAENL_SHIFT                       2  /* INPPGAENL */
+#define WM8985_INPPGAENL_WIDTH                       1  /* INPPGAENL */
+#define WM8985_ADCENR                           0x0002  /* ADCENR */
+#define WM8985_ADCENR_MASK                      0x0002  /* ADCENR */
+#define WM8985_ADCENR_SHIFT                          1  /* ADCENR */
+#define WM8985_ADCENR_WIDTH                          1  /* ADCENR */
+#define WM8985_ADCENL                           0x0001  /* ADCENL */
+#define WM8985_ADCENL_MASK                      0x0001  /* ADCENL */
+#define WM8985_ADCENL_SHIFT                          0  /* ADCENL */
+#define WM8985_ADCENL_WIDTH                          1  /* ADCENL */
+
+/*
+ * R3 (0x03) - Power management 3
+ */
+#define WM8985_OUT4EN                           0x0100  /* OUT4EN */
+#define WM8985_OUT4EN_MASK                      0x0100  /* OUT4EN */
+#define WM8985_OUT4EN_SHIFT                          8  /* OUT4EN */
+#define WM8985_OUT4EN_WIDTH                          1  /* OUT4EN */
+#define WM8985_OUT3EN                           0x0080  /* OUT3EN */
+#define WM8985_OUT3EN_MASK                      0x0080  /* OUT3EN */
+#define WM8985_OUT3EN_SHIFT                          7  /* OUT3EN */
+#define WM8985_OUT3EN_WIDTH                          1  /* OUT3EN */
+#define WM8985_ROUT2EN                          0x0040  /* ROUT2EN */
+#define WM8985_ROUT2EN_MASK                     0x0040  /* ROUT2EN */
+#define WM8985_ROUT2EN_SHIFT                         6  /* ROUT2EN */
+#define WM8985_ROUT2EN_WIDTH                         1  /* ROUT2EN */
+#define WM8985_LOUT2EN                          0x0020  /* LOUT2EN */
+#define WM8985_LOUT2EN_MASK                     0x0020  /* LOUT2EN */
+#define WM8985_LOUT2EN_SHIFT                         5  /* LOUT2EN */
+#define WM8985_LOUT2EN_WIDTH                         1  /* LOUT2EN */
+#define WM8985_RMIXEN                           0x0008  /* RMIXEN */
+#define WM8985_RMIXEN_MASK                      0x0008  /* RMIXEN */
+#define WM8985_RMIXEN_SHIFT                          3  /* RMIXEN */
+#define WM8985_RMIXEN_WIDTH                          1  /* RMIXEN */
+#define WM8985_LMIXEN                           0x0004  /* LMIXEN */
+#define WM8985_LMIXEN_MASK                      0x0004  /* LMIXEN */
+#define WM8985_LMIXEN_SHIFT                          2  /* LMIXEN */
+#define WM8985_LMIXEN_WIDTH                          1  /* LMIXEN */
+#define WM8985_DACENR                           0x0002  /* DACENR */
+#define WM8985_DACENR_MASK                      0x0002  /* DACENR */
+#define WM8985_DACENR_SHIFT                          1  /* DACENR */
+#define WM8985_DACENR_WIDTH                          1  /* DACENR */
+#define WM8985_DACENL                           0x0001  /* DACENL */
+#define WM8985_DACENL_MASK                      0x0001  /* DACENL */
+#define WM8985_DACENL_SHIFT                          0  /* DACENL */
+#define WM8985_DACENL_WIDTH                          1  /* DACENL */
+
+/*
+ * R4 (0x04) - Audio Interface
+ */
+#define WM8985_BCP                              0x0100  /* BCP */
+#define WM8985_BCP_MASK                         0x0100  /* BCP */
+#define WM8985_BCP_SHIFT                             8  /* BCP */
+#define WM8985_BCP_WIDTH                             1  /* BCP */
+#define WM8985_LRP                              0x0080  /* LRP */
+#define WM8985_LRP_MASK                         0x0080  /* LRP */
+#define WM8985_LRP_SHIFT                             7  /* LRP */
+#define WM8985_LRP_WIDTH                             1  /* LRP */
+#define WM8985_WL_MASK                          0x0060  /* WL - [6:5] */
+#define WM8985_WL_SHIFT                              5  /* WL - [6:5] */
+#define WM8985_WL_WIDTH                              2  /* WL - [6:5] */
+#define WM8985_FMT_MASK                         0x0018  /* FMT - [4:3] */
+#define WM8985_FMT_SHIFT                             3  /* FMT - [4:3] */
+#define WM8985_FMT_WIDTH                             2  /* FMT - [4:3] */
+#define WM8985_DLRSWAP                          0x0004  /* DLRSWAP */
+#define WM8985_DLRSWAP_MASK                     0x0004  /* DLRSWAP */
+#define WM8985_DLRSWAP_SHIFT                         2  /* DLRSWAP */
+#define WM8985_DLRSWAP_WIDTH                         1  /* DLRSWAP */
+#define WM8985_ALRSWAP                          0x0002  /* ALRSWAP */
+#define WM8985_ALRSWAP_MASK                     0x0002  /* ALRSWAP */
+#define WM8985_ALRSWAP_SHIFT                         1  /* ALRSWAP */
+#define WM8985_ALRSWAP_WIDTH                         1  /* ALRSWAP */
+#define WM8985_MONO                             0x0001  /* MONO */
+#define WM8985_MONO_MASK                        0x0001  /* MONO */
+#define WM8985_MONO_SHIFT                            0  /* MONO */
+#define WM8985_MONO_WIDTH                            1  /* MONO */
+
+/*
+ * R5 (0x05) - Companding control
+ */
+#define WM8985_WL8                              0x0020  /* WL8 */
+#define WM8985_WL8_MASK                         0x0020  /* WL8 */
+#define WM8985_WL8_SHIFT                             5  /* WL8 */
+#define WM8985_WL8_WIDTH                             1  /* WL8 */
+#define WM8985_DAC_COMP_MASK                    0x0018  /* DAC_COMP - [4:3] */
+#define WM8985_DAC_COMP_SHIFT                        3  /* DAC_COMP - [4:3] */
+#define WM8985_DAC_COMP_WIDTH                        2  /* DAC_COMP - [4:3] */
+#define WM8985_ADC_COMP_MASK                    0x0006  /* ADC_COMP - [2:1] */
+#define WM8985_ADC_COMP_SHIFT                        1  /* ADC_COMP - [2:1] */
+#define WM8985_ADC_COMP_WIDTH                        2  /* ADC_COMP - [2:1] */
+#define WM8985_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8985_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8985_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8985_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clock Gen control
+ */
+#define WM8985_CLKSEL                           0x0100  /* CLKSEL */
+#define WM8985_CLKSEL_MASK                      0x0100  /* CLKSEL */
+#define WM8985_CLKSEL_SHIFT                          8  /* CLKSEL */
+#define WM8985_CLKSEL_WIDTH                          1  /* CLKSEL */
+#define WM8985_MCLKDIV_MASK                     0x00E0  /* MCLKDIV - [7:5] */
+#define WM8985_MCLKDIV_SHIFT                         5  /* MCLKDIV - [7:5] */
+#define WM8985_MCLKDIV_WIDTH                         3  /* MCLKDIV - [7:5] */
+#define WM8985_BCLKDIV_MASK                     0x001C  /* BCLKDIV - [4:2] */
+#define WM8985_BCLKDIV_SHIFT                         2  /* BCLKDIV - [4:2] */
+#define WM8985_BCLKDIV_WIDTH                         3  /* BCLKDIV - [4:2] */
+#define WM8985_MS                               0x0001  /* MS */
+#define WM8985_MS_MASK                          0x0001  /* MS */
+#define WM8985_MS_SHIFT                              0  /* MS */
+#define WM8985_MS_WIDTH                              1  /* MS */
+
+/*
+ * R7 (0x07) - Additional control
+ */
+#define WM8985_M128ENB                          0x0100  /* M128ENB */
+#define WM8985_M128ENB_MASK                     0x0100  /* M128ENB */
+#define WM8985_M128ENB_SHIFT                         8  /* M128ENB */
+#define WM8985_M128ENB_WIDTH                         1  /* M128ENB */
+#define WM8985_DCLKDIV_MASK                     0x00F0  /* DCLKDIV - [7:4] */
+#define WM8985_DCLKDIV_SHIFT                         4  /* DCLKDIV - [7:4] */
+#define WM8985_DCLKDIV_WIDTH                         4  /* DCLKDIV - [7:4] */
+#define WM8985_SR_MASK                          0x000E  /* SR - [3:1] */
+#define WM8985_SR_SHIFT                              1  /* SR - [3:1] */
+#define WM8985_SR_WIDTH                              3  /* SR - [3:1] */
+#define WM8985_SLOWCLKEN                        0x0001  /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_MASK                   0x0001  /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_SHIFT                       0  /* SLOWCLKEN */
+#define WM8985_SLOWCLKEN_WIDTH                       1  /* SLOWCLKEN */
+
+/*
+ * R8 (0x08) - GPIO Control
+ */
+#define WM8985_GPIO1GP                          0x0100  /* GPIO1GP */
+#define WM8985_GPIO1GP_MASK                     0x0100  /* GPIO1GP */
+#define WM8985_GPIO1GP_SHIFT                         8  /* GPIO1GP */
+#define WM8985_GPIO1GP_WIDTH                         1  /* GPIO1GP */
+#define WM8985_GPIO1GPU                         0x0080  /* GPIO1GPU */
+#define WM8985_GPIO1GPU_MASK                    0x0080  /* GPIO1GPU */
+#define WM8985_GPIO1GPU_SHIFT                        7  /* GPIO1GPU */
+#define WM8985_GPIO1GPU_WIDTH                        1  /* GPIO1GPU */
+#define WM8985_GPIO1GPD                         0x0040  /* GPIO1GPD */
+#define WM8985_GPIO1GPD_MASK                    0x0040  /* GPIO1GPD */
+#define WM8985_GPIO1GPD_SHIFT                        6  /* GPIO1GPD */
+#define WM8985_GPIO1GPD_WIDTH                        1  /* GPIO1GPD */
+#define WM8985_GPIO1POL                         0x0008  /* GPIO1POL */
+#define WM8985_GPIO1POL_MASK                    0x0008  /* GPIO1POL */
+#define WM8985_GPIO1POL_SHIFT                        3  /* GPIO1POL */
+#define WM8985_GPIO1POL_WIDTH                        1  /* GPIO1POL */
+#define WM8985_GPIO1SEL_MASK                    0x0007  /* GPIO1SEL - [2:0] */
+#define WM8985_GPIO1SEL_SHIFT                        0  /* GPIO1SEL - [2:0] */
+#define WM8985_GPIO1SEL_WIDTH                        3  /* GPIO1SEL - [2:0] */
+
+/*
+ * R9 (0x09) - Jack Detect Control 1
+ */
+#define WM8985_JD_EN                            0x0040  /* JD_EN */
+#define WM8985_JD_EN_MASK                       0x0040  /* JD_EN */
+#define WM8985_JD_EN_SHIFT                           6  /* JD_EN */
+#define WM8985_JD_EN_WIDTH                           1  /* JD_EN */
+#define WM8985_JD_SEL_MASK                      0x0030  /* JD_SEL - [5:4] */
+#define WM8985_JD_SEL_SHIFT                          4  /* JD_SEL - [5:4] */
+#define WM8985_JD_SEL_WIDTH                          2  /* JD_SEL - [5:4] */
+
+/*
+ * R10 (0x0A) - DAC Control
+ */
+#define WM8985_SOFTMUTE                         0x0040  /* SOFTMUTE */
+#define WM8985_SOFTMUTE_MASK                    0x0040  /* SOFTMUTE */
+#define WM8985_SOFTMUTE_SHIFT                        6  /* SOFTMUTE */
+#define WM8985_SOFTMUTE_WIDTH                        1  /* SOFTMUTE */
+#define WM8985_DACOSR128                        0x0008  /* DACOSR128 */
+#define WM8985_DACOSR128_MASK                   0x0008  /* DACOSR128 */
+#define WM8985_DACOSR128_SHIFT                       3  /* DACOSR128 */
+#define WM8985_DACOSR128_WIDTH                       1  /* DACOSR128 */
+#define WM8985_AMUTE                            0x0004  /* AMUTE */
+#define WM8985_AMUTE_MASK                       0x0004  /* AMUTE */
+#define WM8985_AMUTE_SHIFT                           2  /* AMUTE */
+#define WM8985_AMUTE_WIDTH                           1  /* AMUTE */
+#define WM8985_DACPOLR                          0x0002  /* DACPOLR */
+#define WM8985_DACPOLR_MASK                     0x0002  /* DACPOLR */
+#define WM8985_DACPOLR_SHIFT                         1  /* DACPOLR */
+#define WM8985_DACPOLR_WIDTH                         1  /* DACPOLR */
+#define WM8985_DACPOLL                          0x0001  /* DACPOLL */
+#define WM8985_DACPOLL_MASK                     0x0001  /* DACPOLL */
+#define WM8985_DACPOLL_SHIFT                         0  /* DACPOLL */
+#define WM8985_DACPOLL_WIDTH                         1  /* DACPOLL */
+
+/*
+ * R11 (0x0B) - Left DAC digital Vol
+ */
+#define WM8985_DACVU                            0x0100  /* DACVU */
+#define WM8985_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8985_DACVU_SHIFT                           8  /* DACVU */
+#define WM8985_DACVU_WIDTH                           1  /* DACVU */
+#define WM8985_DACVOLL_MASK                     0x00FF  /* DACVOLL - [7:0] */
+#define WM8985_DACVOLL_SHIFT                         0  /* DACVOLL - [7:0] */
+#define WM8985_DACVOLL_WIDTH                         8  /* DACVOLL - [7:0] */
+
+/*
+ * R12 (0x0C) - Right DAC digital vol
+ */
+#define WM8985_DACVU                            0x0100  /* DACVU */
+#define WM8985_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8985_DACVU_SHIFT                           8  /* DACVU */
+#define WM8985_DACVU_WIDTH                           1  /* DACVU */
+#define WM8985_DACVOLR_MASK                     0x00FF  /* DACVOLR - [7:0] */
+#define WM8985_DACVOLR_SHIFT                         0  /* DACVOLR - [7:0] */
+#define WM8985_DACVOLR_WIDTH                         8  /* DACVOLR - [7:0] */
+
+/*
+ * R13 (0x0D) - Jack Detect Control 2
+ */
+#define WM8985_JD_EN1_MASK                      0x00F0  /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN1_SHIFT                          4  /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN1_WIDTH                          4  /* JD_EN1 - [7:4] */
+#define WM8985_JD_EN0_MASK                      0x000F  /* JD_EN0 - [3:0] */
+#define WM8985_JD_EN0_SHIFT                          0  /* JD_EN0 - [3:0] */
+#define WM8985_JD_EN0_WIDTH                          4  /* JD_EN0 - [3:0] */
+
+/*
+ * R14 (0x0E) - ADC Control
+ */
+#define WM8985_HPFEN                            0x0100  /* HPFEN */
+#define WM8985_HPFEN_MASK                       0x0100  /* HPFEN */
+#define WM8985_HPFEN_SHIFT                           8  /* HPFEN */
+#define WM8985_HPFEN_WIDTH                           1  /* HPFEN */
+#define WM8985_HPFAPP                           0x0080  /* HPFAPP */
+#define WM8985_HPFAPP_MASK                      0x0080  /* HPFAPP */
+#define WM8985_HPFAPP_SHIFT                          7  /* HPFAPP */
+#define WM8985_HPFAPP_WIDTH                          1  /* HPFAPP */
+#define WM8985_HPFCUT_MASK                      0x0070  /* HPFCUT - [6:4] */
+#define WM8985_HPFCUT_SHIFT                          4  /* HPFCUT - [6:4] */
+#define WM8985_HPFCUT_WIDTH                          3  /* HPFCUT - [6:4] */
+#define WM8985_ADCOSR128                        0x0008  /* ADCOSR128 */
+#define WM8985_ADCOSR128_MASK                   0x0008  /* ADCOSR128 */
+#define WM8985_ADCOSR128_SHIFT                       3  /* ADCOSR128 */
+#define WM8985_ADCOSR128_WIDTH                       1  /* ADCOSR128 */
+#define WM8985_ADCRPOL                          0x0002  /* ADCRPOL */
+#define WM8985_ADCRPOL_MASK                     0x0002  /* ADCRPOL */
+#define WM8985_ADCRPOL_SHIFT                         1  /* ADCRPOL */
+#define WM8985_ADCRPOL_WIDTH                         1  /* ADCRPOL */
+#define WM8985_ADCLPOL                          0x0001  /* ADCLPOL */
+#define WM8985_ADCLPOL_MASK                     0x0001  /* ADCLPOL */
+#define WM8985_ADCLPOL_SHIFT                         0  /* ADCLPOL */
+#define WM8985_ADCLPOL_WIDTH                         1  /* ADCLPOL */
+
+/*
+ * R15 (0x0F) - Left ADC Digital Vol
+ */
+#define WM8985_ADCVU                            0x0100  /* ADCVU */
+#define WM8985_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8985_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8985_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8985_ADCVOLL_MASK                     0x00FF  /* ADCVOLL - [7:0] */
+#define WM8985_ADCVOLL_SHIFT                         0  /* ADCVOLL - [7:0] */
+#define WM8985_ADCVOLL_WIDTH                         8  /* ADCVOLL - [7:0] */
+
+/*
+ * R16 (0x10) - Right ADC Digital Vol
+ */
+#define WM8985_ADCVU                            0x0100  /* ADCVU */
+#define WM8985_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8985_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8985_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8985_ADCVOLR_MASK                     0x00FF  /* ADCVOLR - [7:0] */
+#define WM8985_ADCVOLR_SHIFT                         0  /* ADCVOLR - [7:0] */
+#define WM8985_ADCVOLR_WIDTH                         8  /* ADCVOLR - [7:0] */
+
+/*
+ * R18 (0x12) - EQ1 - low shelf
+ */
+#define WM8985_EQ3DMODE                         0x0100  /* EQ3DMODE */
+#define WM8985_EQ3DMODE_MASK                    0x0100  /* EQ3DMODE */
+#define WM8985_EQ3DMODE_SHIFT                        8  /* EQ3DMODE */
+#define WM8985_EQ3DMODE_WIDTH                        1  /* EQ3DMODE */
+#define WM8985_EQ1C_MASK                        0x0060  /* EQ1C - [6:5] */
+#define WM8985_EQ1C_SHIFT                            5  /* EQ1C - [6:5] */
+#define WM8985_EQ1C_WIDTH                            2  /* EQ1C - [6:5] */
+#define WM8985_EQ1G_MASK                        0x001F  /* EQ1G - [4:0] */
+#define WM8985_EQ1G_SHIFT                            0  /* EQ1G - [4:0] */
+#define WM8985_EQ1G_WIDTH                            5  /* EQ1G - [4:0] */
+
+/*
+ * R19 (0x13) - EQ2 - peak 1
+ */
+#define WM8985_EQ2BW                            0x0100  /* EQ2BW */
+#define WM8985_EQ2BW_MASK                       0x0100  /* EQ2BW */
+#define WM8985_EQ2BW_SHIFT                           8  /* EQ2BW */
+#define WM8985_EQ2BW_WIDTH                           1  /* EQ2BW */
+#define WM8985_EQ2C_MASK                        0x0060  /* EQ2C - [6:5] */
+#define WM8985_EQ2C_SHIFT                            5  /* EQ2C - [6:5] */
+#define WM8985_EQ2C_WIDTH                            2  /* EQ2C - [6:5] */
+#define WM8985_EQ2G_MASK                        0x001F  /* EQ2G - [4:0] */
+#define WM8985_EQ2G_SHIFT                            0  /* EQ2G - [4:0] */
+#define WM8985_EQ2G_WIDTH                            5  /* EQ2G - [4:0] */
+
+/*
+ * R20 (0x14) - EQ3 - peak 2
+ */
+#define WM8985_EQ3BW                            0x0100  /* EQ3BW */
+#define WM8985_EQ3BW_MASK                       0x0100  /* EQ3BW */
+#define WM8985_EQ3BW_SHIFT                           8  /* EQ3BW */
+#define WM8985_EQ3BW_WIDTH                           1  /* EQ3BW */
+#define WM8985_EQ3C_MASK                        0x0060  /* EQ3C - [6:5] */
+#define WM8985_EQ3C_SHIFT                            5  /* EQ3C - [6:5] */
+#define WM8985_EQ3C_WIDTH                            2  /* EQ3C - [6:5] */
+#define WM8985_EQ3G_MASK                        0x001F  /* EQ3G - [4:0] */
+#define WM8985_EQ3G_SHIFT                            0  /* EQ3G - [4:0] */
+#define WM8985_EQ3G_WIDTH                            5  /* EQ3G - [4:0] */
+
+/*
+ * R21 (0x15) - EQ4 - peak 3
+ */
+#define WM8985_EQ4BW                            0x0100  /* EQ4BW */
+#define WM8985_EQ4BW_MASK                       0x0100  /* EQ4BW */
+#define WM8985_EQ4BW_SHIFT                           8  /* EQ4BW */
+#define WM8985_EQ4BW_WIDTH                           1  /* EQ4BW */
+#define WM8985_EQ4C_MASK                        0x0060  /* EQ4C - [6:5] */
+#define WM8985_EQ4C_SHIFT                            5  /* EQ4C - [6:5] */
+#define WM8985_EQ4C_WIDTH                            2  /* EQ4C - [6:5] */
+#define WM8985_EQ4G_MASK                        0x001F  /* EQ4G - [4:0] */
+#define WM8985_EQ4G_SHIFT                            0  /* EQ4G - [4:0] */
+#define WM8985_EQ4G_WIDTH                            5  /* EQ4G - [4:0] */
+
+/*
+ * R22 (0x16) - EQ5 - high shelf
+ */
+#define WM8985_EQ5C_MASK                        0x0060  /* EQ5C - [6:5] */
+#define WM8985_EQ5C_SHIFT                            5  /* EQ5C - [6:5] */
+#define WM8985_EQ5C_WIDTH                            2  /* EQ5C - [6:5] */
+#define WM8985_EQ5G_MASK                        0x001F  /* EQ5G - [4:0] */
+#define WM8985_EQ5G_SHIFT                            0  /* EQ5G - [4:0] */
+#define WM8985_EQ5G_WIDTH                            5  /* EQ5G - [4:0] */
+
+/*
+ * R24 (0x18) - DAC Limiter 1
+ */
+#define WM8985_LIMEN                            0x0100  /* LIMEN */
+#define WM8985_LIMEN_MASK                       0x0100  /* LIMEN */
+#define WM8985_LIMEN_SHIFT                           8  /* LIMEN */
+#define WM8985_LIMEN_WIDTH                           1  /* LIMEN */
+#define WM8985_LIMDCY_MASK                      0x00F0  /* LIMDCY - [7:4] */
+#define WM8985_LIMDCY_SHIFT                          4  /* LIMDCY - [7:4] */
+#define WM8985_LIMDCY_WIDTH                          4  /* LIMDCY - [7:4] */
+#define WM8985_LIMATK_MASK                      0x000F  /* LIMATK - [3:0] */
+#define WM8985_LIMATK_SHIFT                          0  /* LIMATK - [3:0] */
+#define WM8985_LIMATK_WIDTH                          4  /* LIMATK - [3:0] */
+
+/*
+ * R25 (0x19) - DAC Limiter 2
+ */
+#define WM8985_LIMLVL_MASK                      0x0070  /* LIMLVL - [6:4] */
+#define WM8985_LIMLVL_SHIFT                          4  /* LIMLVL - [6:4] */
+#define WM8985_LIMLVL_WIDTH                          3  /* LIMLVL - [6:4] */
+#define WM8985_LIMBOOST_MASK                    0x000F  /* LIMBOOST - [3:0] */
+#define WM8985_LIMBOOST_SHIFT                        0  /* LIMBOOST - [3:0] */
+#define WM8985_LIMBOOST_WIDTH                        4  /* LIMBOOST - [3:0] */
+
+/*
+ * R27 (0x1B) - Notch Filter 1
+ */
+#define WM8985_NFU                              0x0100  /* NFU */
+#define WM8985_NFU_MASK                         0x0100  /* NFU */
+#define WM8985_NFU_SHIFT                             8  /* NFU */
+#define WM8985_NFU_WIDTH                             1  /* NFU */
+#define WM8985_NFEN                             0x0080  /* NFEN */
+#define WM8985_NFEN_MASK                        0x0080  /* NFEN */
+#define WM8985_NFEN_SHIFT                            7  /* NFEN */
+#define WM8985_NFEN_WIDTH                            1  /* NFEN */
+#define WM8985_NFA0_13_7_MASK                   0x007F  /* NFA0(13:7) - [6:0] */
+#define WM8985_NFA0_13_7_SHIFT                       0  /* NFA0(13:7) - [6:0] */
+#define WM8985_NFA0_13_7_WIDTH                       7  /* NFA0(13:7) - [6:0] */
+
+/*
+ * R28 (0x1C) - Notch Filter 2
+ */
+#define WM8985_NFU                              0x0100  /* NFU */
+#define WM8985_NFU_MASK                         0x0100  /* NFU */
+#define WM8985_NFU_SHIFT                             8  /* NFU */
+#define WM8985_NFU_WIDTH                             1  /* NFU */
+#define WM8985_NFA0_6_0_MASK                    0x007F  /* NFA0(6:0) - [6:0] */
+#define WM8985_NFA0_6_0_SHIFT                        0  /* NFA0(6:0) - [6:0] */
+#define WM8985_NFA0_6_0_WIDTH                        7  /* NFA0(6:0) - [6:0] */
+
+/*
+ * R29 (0x1D) - Notch Filter 3
+ */
+#define WM8985_NFU                              0x0100  /* NFU */
+#define WM8985_NFU_MASK                         0x0100  /* NFU */
+#define WM8985_NFU_SHIFT                             8  /* NFU */
+#define WM8985_NFU_WIDTH                             1  /* NFU */
+#define WM8985_NFA1_13_7_MASK                   0x007F  /* NFA1(13:7) - [6:0] */
+#define WM8985_NFA1_13_7_SHIFT                       0  /* NFA1(13:7) - [6:0] */
+#define WM8985_NFA1_13_7_WIDTH                       7  /* NFA1(13:7) - [6:0] */
+
+/*
+ * R30 (0x1E) - Notch Filter 4
+ */
+#define WM8985_NFU                              0x0100  /* NFU */
+#define WM8985_NFU_MASK                         0x0100  /* NFU */
+#define WM8985_NFU_SHIFT                             8  /* NFU */
+#define WM8985_NFU_WIDTH                             1  /* NFU */
+#define WM8985_NFA1_6_0_MASK                    0x007F  /* NFA1(6:0) - [6:0] */
+#define WM8985_NFA1_6_0_SHIFT                        0  /* NFA1(6:0) - [6:0] */
+#define WM8985_NFA1_6_0_WIDTH                        7  /* NFA1(6:0) - [6:0] */
+
+/*
+ * R32 (0x20) - ALC control 1
+ */
+#define WM8985_ALCSEL_MASK                      0x0180  /* ALCSEL - [8:7] */
+#define WM8985_ALCSEL_SHIFT                          7  /* ALCSEL - [8:7] */
+#define WM8985_ALCSEL_WIDTH                          2  /* ALCSEL - [8:7] */
+#define WM8985_ALCMAX_MASK                      0x0038  /* ALCMAX - [5:3] */
+#define WM8985_ALCMAX_SHIFT                          3  /* ALCMAX - [5:3] */
+#define WM8985_ALCMAX_WIDTH                          3  /* ALCMAX - [5:3] */
+#define WM8985_ALCMIN_MASK                      0x0007  /* ALCMIN - [2:0] */
+#define WM8985_ALCMIN_SHIFT                          0  /* ALCMIN - [2:0] */
+#define WM8985_ALCMIN_WIDTH                          3  /* ALCMIN - [2:0] */
+
+/*
+ * R33 (0x21) - ALC control 2
+ */
+#define WM8985_ALCHLD_MASK                      0x00F0  /* ALCHLD - [7:4] */
+#define WM8985_ALCHLD_SHIFT                          4  /* ALCHLD - [7:4] */
+#define WM8985_ALCHLD_WIDTH                          4  /* ALCHLD - [7:4] */
+#define WM8985_ALCLVL_MASK                      0x000F  /* ALCLVL - [3:0] */
+#define WM8985_ALCLVL_SHIFT                          0  /* ALCLVL - [3:0] */
+#define WM8985_ALCLVL_WIDTH                          4  /* ALCLVL - [3:0] */
+
+/*
+ * R34 (0x22) - ALC control 3
+ */
+#define WM8985_ALCMODE                          0x0100  /* ALCMODE */
+#define WM8985_ALCMODE_MASK                     0x0100  /* ALCMODE */
+#define WM8985_ALCMODE_SHIFT                         8  /* ALCMODE */
+#define WM8985_ALCMODE_WIDTH                         1  /* ALCMODE */
+#define WM8985_ALCDCY_MASK                      0x00F0  /* ALCDCY - [7:4] */
+#define WM8985_ALCDCY_SHIFT                          4  /* ALCDCY - [7:4] */
+#define WM8985_ALCDCY_WIDTH                          4  /* ALCDCY - [7:4] */
+#define WM8985_ALCATK_MASK                      0x000F  /* ALCATK - [3:0] */
+#define WM8985_ALCATK_SHIFT                          0  /* ALCATK - [3:0] */
+#define WM8985_ALCATK_WIDTH                          4  /* ALCATK - [3:0] */
+
+/*
+ * R35 (0x23) - Noise Gate
+ */
+#define WM8985_NGEN                             0x0008  /* NGEN */
+#define WM8985_NGEN_MASK                        0x0008  /* NGEN */
+#define WM8985_NGEN_SHIFT                            3  /* NGEN */
+#define WM8985_NGEN_WIDTH                            1  /* NGEN */
+#define WM8985_NGTH_MASK                        0x0007  /* NGTH - [2:0] */
+#define WM8985_NGTH_SHIFT                            0  /* NGTH - [2:0] */
+#define WM8985_NGTH_WIDTH                            3  /* NGTH - [2:0] */
+
+/*
+ * R36 (0x24) - PLL N
+ */
+#define WM8985_PLL_PRESCALE                     0x0010  /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_MASK                0x0010  /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_SHIFT                    4  /* PLL_PRESCALE */
+#define WM8985_PLL_PRESCALE_WIDTH                    1  /* PLL_PRESCALE */
+#define WM8985_PLLN_MASK                        0x000F  /* PLLN - [3:0] */
+#define WM8985_PLLN_SHIFT                            0  /* PLLN - [3:0] */
+#define WM8985_PLLN_WIDTH                            4  /* PLLN - [3:0] */
+
+/*
+ * R37 (0x25) - PLL K 1
+ */
+#define WM8985_PLLK_23_18_MASK                  0x003F  /* PLLK(23:18) - [5:0] */
+#define WM8985_PLLK_23_18_SHIFT                      0  /* PLLK(23:18) - [5:0] */
+#define WM8985_PLLK_23_18_WIDTH                      6  /* PLLK(23:18) - [5:0] */
+
+/*
+ * R38 (0x26) - PLL K 2
+ */
+#define WM8985_PLLK_17_9_MASK                   0x01FF  /* PLLK(17:9) - [8:0] */
+#define WM8985_PLLK_17_9_SHIFT                       0  /* PLLK(17:9) - [8:0] */
+#define WM8985_PLLK_17_9_WIDTH                       9  /* PLLK(17:9) - [8:0] */
+
+/*
+ * R39 (0x27) - PLL K 3
+ */
+#define WM8985_PLLK_8_0_MASK                    0x01FF  /* PLLK(8:0) - [8:0] */
+#define WM8985_PLLK_8_0_SHIFT                        0  /* PLLK(8:0) - [8:0] */
+#define WM8985_PLLK_8_0_WIDTH                        9  /* PLLK(8:0) - [8:0] */
+
+/*
+ * R41 (0x29) - 3D control
+ */
+#define WM8985_DEPTH3D_MASK                     0x000F  /* DEPTH3D - [3:0] */
+#define WM8985_DEPTH3D_SHIFT                         0  /* DEPTH3D - [3:0] */
+#define WM8985_DEPTH3D_WIDTH                         4  /* DEPTH3D - [3:0] */
+
+/*
+ * R42 (0x2A) - OUT4 to ADC
+ */
+#define WM8985_OUT4_2ADCVOL_MASK                0x01C0  /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2ADCVOL_SHIFT                    6  /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2ADCVOL_WIDTH                    3  /* OUT4_2ADCVOL - [8:6] */
+#define WM8985_OUT4_2LNR                        0x0020  /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_MASK                   0x0020  /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_SHIFT                       5  /* OUT4_2LNR */
+#define WM8985_OUT4_2LNR_WIDTH                       1  /* OUT4_2LNR */
+#define WM8985_POBCTRL                          0x0004  /* POBCTRL */
+#define WM8985_POBCTRL_MASK                     0x0004  /* POBCTRL */
+#define WM8985_POBCTRL_SHIFT                         2  /* POBCTRL */
+#define WM8985_POBCTRL_WIDTH                         1  /* POBCTRL */
+#define WM8985_DELEN                            0x0002  /* DELEN */
+#define WM8985_DELEN_MASK                       0x0002  /* DELEN */
+#define WM8985_DELEN_SHIFT                           1  /* DELEN */
+#define WM8985_DELEN_WIDTH                           1  /* DELEN */
+#define WM8985_OUT1DEL                          0x0001  /* OUT1DEL */
+#define WM8985_OUT1DEL_MASK                     0x0001  /* OUT1DEL */
+#define WM8985_OUT1DEL_SHIFT                         0  /* OUT1DEL */
+#define WM8985_OUT1DEL_WIDTH                         1  /* OUT1DEL */
+
+/*
+ * R43 (0x2B) - Beep control
+ */
+#define WM8985_BYPL2RMIX                        0x0100  /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_MASK                   0x0100  /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_SHIFT                       8  /* BYPL2RMIX */
+#define WM8985_BYPL2RMIX_WIDTH                       1  /* BYPL2RMIX */
+#define WM8985_BYPR2LMIX                        0x0080  /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_MASK                   0x0080  /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_SHIFT                       7  /* BYPR2LMIX */
+#define WM8985_BYPR2LMIX_WIDTH                       1  /* BYPR2LMIX */
+#define WM8985_MUTERPGA2INV                     0x0020  /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_MASK                0x0020  /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_SHIFT                    5  /* MUTERPGA2INV */
+#define WM8985_MUTERPGA2INV_WIDTH                    1  /* MUTERPGA2INV */
+#define WM8985_INVROUT2                         0x0010  /* INVROUT2 */
+#define WM8985_INVROUT2_MASK                    0x0010  /* INVROUT2 */
+#define WM8985_INVROUT2_SHIFT                        4  /* INVROUT2 */
+#define WM8985_INVROUT2_WIDTH                        1  /* INVROUT2 */
+#define WM8985_BEEPVOL_MASK                     0x000E  /* BEEPVOL - [3:1] */
+#define WM8985_BEEPVOL_SHIFT                         1  /* BEEPVOL - [3:1] */
+#define WM8985_BEEPVOL_WIDTH                         3  /* BEEPVOL - [3:1] */
+#define WM8985_BEEPEN                           0x0001  /* BEEPEN */
+#define WM8985_BEEPEN_MASK                      0x0001  /* BEEPEN */
+#define WM8985_BEEPEN_SHIFT                          0  /* BEEPEN */
+#define WM8985_BEEPEN_WIDTH                          1  /* BEEPEN */
+
+/*
+ * R44 (0x2C) - Input ctrl
+ */
+#define WM8985_MBVSEL                           0x0100  /* MBVSEL */
+#define WM8985_MBVSEL_MASK                      0x0100  /* MBVSEL */
+#define WM8985_MBVSEL_SHIFT                          8  /* MBVSEL */
+#define WM8985_MBVSEL_WIDTH                          1  /* MBVSEL */
+#define WM8985_R2_2INPPGA                       0x0040  /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_MASK                  0x0040  /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_SHIFT                      6  /* R2_2INPPGA */
+#define WM8985_R2_2INPPGA_WIDTH                      1  /* R2_2INPPGA */
+#define WM8985_RIN2INPPGA                       0x0020  /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_MASK                  0x0020  /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_SHIFT                      5  /* RIN2INPPGA */
+#define WM8985_RIN2INPPGA_WIDTH                      1  /* RIN2INPPGA */
+#define WM8985_RIP2INPPGA                       0x0010  /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_MASK                  0x0010  /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_SHIFT                      4  /* RIP2INPPGA */
+#define WM8985_RIP2INPPGA_WIDTH                      1  /* RIP2INPPGA */
+#define WM8985_L2_2INPPGA                       0x0004  /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_MASK                  0x0004  /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_SHIFT                      2  /* L2_2INPPGA */
+#define WM8985_L2_2INPPGA_WIDTH                      1  /* L2_2INPPGA */
+#define WM8985_LIN2INPPGA                       0x0002  /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_MASK                  0x0002  /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_SHIFT                      1  /* LIN2INPPGA */
+#define WM8985_LIN2INPPGA_WIDTH                      1  /* LIN2INPPGA */
+#define WM8985_LIP2INPPGA                       0x0001  /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_MASK                  0x0001  /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_SHIFT                      0  /* LIP2INPPGA */
+#define WM8985_LIP2INPPGA_WIDTH                      1  /* LIP2INPPGA */
+
+/*
+ * R45 (0x2D) - Left INP PGA gain ctrl
+ */
+#define WM8985_INPGAVU                          0x0100  /* INPGAVU */
+#define WM8985_INPGAVU_MASK                     0x0100  /* INPGAVU */
+#define WM8985_INPGAVU_SHIFT                         8  /* INPGAVU */
+#define WM8985_INPGAVU_WIDTH                         1  /* INPGAVU */
+#define WM8985_INPPGAZCL                        0x0080  /* INPPGAZCL */
+#define WM8985_INPPGAZCL_MASK                   0x0080  /* INPPGAZCL */
+#define WM8985_INPPGAZCL_SHIFT                       7  /* INPPGAZCL */
+#define WM8985_INPPGAZCL_WIDTH                       1  /* INPPGAZCL */
+#define WM8985_INPPGAMUTEL                      0x0040  /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_MASK                 0x0040  /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_SHIFT                     6  /* INPPGAMUTEL */
+#define WM8985_INPPGAMUTEL_WIDTH                     1  /* INPPGAMUTEL */
+#define WM8985_INPPGAVOLL_MASK                  0x003F  /* INPPGAVOLL - [5:0] */
+#define WM8985_INPPGAVOLL_SHIFT                      0  /* INPPGAVOLL - [5:0] */
+#define WM8985_INPPGAVOLL_WIDTH                      6  /* INPPGAVOLL - [5:0] */
+
+/*
+ * R46 (0x2E) - Right INP PGA gain ctrl
+ */
+#define WM8985_INPGAVU                          0x0100  /* INPGAVU */
+#define WM8985_INPGAVU_MASK                     0x0100  /* INPGAVU */
+#define WM8985_INPGAVU_SHIFT                         8  /* INPGAVU */
+#define WM8985_INPGAVU_WIDTH                         1  /* INPGAVU */
+#define WM8985_INPPGAZCR                        0x0080  /* INPPGAZCR */
+#define WM8985_INPPGAZCR_MASK                   0x0080  /* INPPGAZCR */
+#define WM8985_INPPGAZCR_SHIFT                       7  /* INPPGAZCR */
+#define WM8985_INPPGAZCR_WIDTH                       1  /* INPPGAZCR */
+#define WM8985_INPPGAMUTER                      0x0040  /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_MASK                 0x0040  /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_SHIFT                     6  /* INPPGAMUTER */
+#define WM8985_INPPGAMUTER_WIDTH                     1  /* INPPGAMUTER */
+#define WM8985_INPPGAVOLR_MASK                  0x003F  /* INPPGAVOLR - [5:0] */
+#define WM8985_INPPGAVOLR_SHIFT                      0  /* INPPGAVOLR - [5:0] */
+#define WM8985_INPPGAVOLR_WIDTH                      6  /* INPPGAVOLR - [5:0] */
+
+/*
+ * R47 (0x2F) - Left ADC BOOST ctrl
+ */
+#define WM8985_PGABOOSTL                        0x0100  /* PGABOOSTL */
+#define WM8985_PGABOOSTL_MASK                   0x0100  /* PGABOOSTL */
+#define WM8985_PGABOOSTL_SHIFT                       8  /* PGABOOSTL */
+#define WM8985_PGABOOSTL_WIDTH                       1  /* PGABOOSTL */
+#define WM8985_L2_2BOOSTVOL_MASK                0x0070  /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_L2_2BOOSTVOL_SHIFT                    4  /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_L2_2BOOSTVOL_WIDTH                    3  /* L2_2BOOSTVOL - [6:4] */
+#define WM8985_AUXL2BOOSTVOL_MASK               0x0007  /* AUXL2BOOSTVOL - [2:0] */
+#define WM8985_AUXL2BOOSTVOL_SHIFT                   0  /* AUXL2BOOSTVOL - [2:0] */
+#define WM8985_AUXL2BOOSTVOL_WIDTH                   3  /* AUXL2BOOSTVOL - [2:0] */
+
+/*
+ * R48 (0x30) - Right ADC BOOST ctrl
+ */
+#define WM8985_PGABOOSTR                        0x0100  /* PGABOOSTR */
+#define WM8985_PGABOOSTR_MASK                   0x0100  /* PGABOOSTR */
+#define WM8985_PGABOOSTR_SHIFT                       8  /* PGABOOSTR */
+#define WM8985_PGABOOSTR_WIDTH                       1  /* PGABOOSTR */
+#define WM8985_R2_2BOOSTVOL_MASK                0x0070  /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_R2_2BOOSTVOL_SHIFT                    4  /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_R2_2BOOSTVOL_WIDTH                    3  /* R2_2BOOSTVOL - [6:4] */
+#define WM8985_AUXR2BOOSTVOL_MASK               0x0007  /* AUXR2BOOSTVOL - [2:0] */
+#define WM8985_AUXR2BOOSTVOL_SHIFT                   0  /* AUXR2BOOSTVOL - [2:0] */
+#define WM8985_AUXR2BOOSTVOL_WIDTH                   3  /* AUXR2BOOSTVOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output ctrl
+ */
+#define WM8985_DACL2RMIX                        0x0040  /* DACL2RMIX */
+#define WM8985_DACL2RMIX_MASK                   0x0040  /* DACL2RMIX */
+#define WM8985_DACL2RMIX_SHIFT                       6  /* DACL2RMIX */
+#define WM8985_DACL2RMIX_WIDTH                       1  /* DACL2RMIX */
+#define WM8985_DACR2LMIX                        0x0020  /* DACR2LMIX */
+#define WM8985_DACR2LMIX_MASK                   0x0020  /* DACR2LMIX */
+#define WM8985_DACR2LMIX_SHIFT                       5  /* DACR2LMIX */
+#define WM8985_DACR2LMIX_WIDTH                       1  /* DACR2LMIX */
+#define WM8985_OUT4BOOST                        0x0010  /* OUT4BOOST */
+#define WM8985_OUT4BOOST_MASK                   0x0010  /* OUT4BOOST */
+#define WM8985_OUT4BOOST_SHIFT                       4  /* OUT4BOOST */
+#define WM8985_OUT4BOOST_WIDTH                       1  /* OUT4BOOST */
+#define WM8985_OUT3BOOST                        0x0008  /* OUT3BOOST */
+#define WM8985_OUT3BOOST_MASK                   0x0008  /* OUT3BOOST */
+#define WM8985_OUT3BOOST_SHIFT                       3  /* OUT3BOOST */
+#define WM8985_OUT3BOOST_WIDTH                       1  /* OUT3BOOST */
+#define WM8985_TSOPCTRL                         0x0004  /* TSOPCTRL */
+#define WM8985_TSOPCTRL_MASK                    0x0004  /* TSOPCTRL */
+#define WM8985_TSOPCTRL_SHIFT                        2  /* TSOPCTRL */
+#define WM8985_TSOPCTRL_WIDTH                        1  /* TSOPCTRL */
+#define WM8985_TSDEN                            0x0002  /* TSDEN */
+#define WM8985_TSDEN_MASK                       0x0002  /* TSDEN */
+#define WM8985_TSDEN_SHIFT                           1  /* TSDEN */
+#define WM8985_TSDEN_WIDTH                           1  /* TSDEN */
+#define WM8985_VROI                             0x0001  /* VROI */
+#define WM8985_VROI_MASK                        0x0001  /* VROI */
+#define WM8985_VROI_SHIFT                            0  /* VROI */
+#define WM8985_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R50 (0x32) - Left mixer ctrl
+ */
+#define WM8985_AUXLMIXVOL_MASK                  0x01C0  /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXLMIXVOL_SHIFT                      6  /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXLMIXVOL_WIDTH                      3  /* AUXLMIXVOL - [8:6] */
+#define WM8985_AUXL2LMIX                        0x0020  /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_MASK                   0x0020  /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_SHIFT                       5  /* AUXL2LMIX */
+#define WM8985_AUXL2LMIX_WIDTH                       1  /* AUXL2LMIX */
+#define WM8985_BYPLMIXVOL_MASK                  0x001C  /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPLMIXVOL_SHIFT                      2  /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPLMIXVOL_WIDTH                      3  /* BYPLMIXVOL - [4:2] */
+#define WM8985_BYPL2LMIX                        0x0002  /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_MASK                   0x0002  /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_SHIFT                       1  /* BYPL2LMIX */
+#define WM8985_BYPL2LMIX_WIDTH                       1  /* BYPL2LMIX */
+#define WM8985_DACL2LMIX                        0x0001  /* DACL2LMIX */
+#define WM8985_DACL2LMIX_MASK                   0x0001  /* DACL2LMIX */
+#define WM8985_DACL2LMIX_SHIFT                       0  /* DACL2LMIX */
+#define WM8985_DACL2LMIX_WIDTH                       1  /* DACL2LMIX */
+
+/*
+ * R51 (0x33) - Right mixer ctrl
+ */
+#define WM8985_AUXRMIXVOL_MASK                  0x01C0  /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXRMIXVOL_SHIFT                      6  /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXRMIXVOL_WIDTH                      3  /* AUXRMIXVOL - [8:6] */
+#define WM8985_AUXR2RMIX                        0x0020  /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_MASK                   0x0020  /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_SHIFT                       5  /* AUXR2RMIX */
+#define WM8985_AUXR2RMIX_WIDTH                       1  /* AUXR2RMIX */
+#define WM8985_BYPRMIXVOL_MASK                  0x001C  /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPRMIXVOL_SHIFT                      2  /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPRMIXVOL_WIDTH                      3  /* BYPRMIXVOL - [4:2] */
+#define WM8985_BYPR2RMIX                        0x0002  /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_MASK                   0x0002  /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_SHIFT                       1  /* BYPR2RMIX */
+#define WM8985_BYPR2RMIX_WIDTH                       1  /* BYPR2RMIX */
+#define WM8985_DACR2RMIX                        0x0001  /* DACR2RMIX */
+#define WM8985_DACR2RMIX_MASK                   0x0001  /* DACR2RMIX */
+#define WM8985_DACR2RMIX_SHIFT                       0  /* DACR2RMIX */
+#define WM8985_DACR2RMIX_WIDTH                       1  /* DACR2RMIX */
+
+/*
+ * R52 (0x34) - LOUT1 (HP) volume ctrl
+ */
+#define WM8985_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8985_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8985_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8985_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8985_LOUT1ZC                          0x0080  /* LOUT1ZC */
+#define WM8985_LOUT1ZC_MASK                     0x0080  /* LOUT1ZC */
+#define WM8985_LOUT1ZC_SHIFT                         7  /* LOUT1ZC */
+#define WM8985_LOUT1ZC_WIDTH                         1  /* LOUT1ZC */
+#define WM8985_LOUT1MUTE                        0x0040  /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_MASK                   0x0040  /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_SHIFT                       6  /* LOUT1MUTE */
+#define WM8985_LOUT1MUTE_WIDTH                       1  /* LOUT1MUTE */
+#define WM8985_LOUT1VOL_MASK                    0x003F  /* LOUT1VOL - [5:0] */
+#define WM8985_LOUT1VOL_SHIFT                        0  /* LOUT1VOL - [5:0] */
+#define WM8985_LOUT1VOL_WIDTH                        6  /* LOUT1VOL - [5:0] */
+
+/*
+ * R53 (0x35) - ROUT1 (HP) volume ctrl
+ */
+#define WM8985_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8985_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8985_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8985_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8985_ROUT1ZC                          0x0080  /* ROUT1ZC */
+#define WM8985_ROUT1ZC_MASK                     0x0080  /* ROUT1ZC */
+#define WM8985_ROUT1ZC_SHIFT                         7  /* ROUT1ZC */
+#define WM8985_ROUT1ZC_WIDTH                         1  /* ROUT1ZC */
+#define WM8985_ROUT1MUTE                        0x0040  /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_MASK                   0x0040  /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_SHIFT                       6  /* ROUT1MUTE */
+#define WM8985_ROUT1MUTE_WIDTH                       1  /* ROUT1MUTE */
+#define WM8985_ROUT1VOL_MASK                    0x003F  /* ROUT1VOL - [5:0] */
+#define WM8985_ROUT1VOL_SHIFT                        0  /* ROUT1VOL - [5:0] */
+#define WM8985_ROUT1VOL_WIDTH                        6  /* ROUT1VOL - [5:0] */
+
+/*
+ * R54 (0x36) - LOUT2 (SPK) volume ctrl
+ */
+#define WM8985_OUT2VU                           0x0100  /* OUT2VU */
+#define WM8985_OUT2VU_MASK                      0x0100  /* OUT2VU */
+#define WM8985_OUT2VU_SHIFT                          8  /* OUT2VU */
+#define WM8985_OUT2VU_WIDTH                          1  /* OUT2VU */
+#define WM8985_LOUT2ZC                          0x0080  /* LOUT2ZC */
+#define WM8985_LOUT2ZC_MASK                     0x0080  /* LOUT2ZC */
+#define WM8985_LOUT2ZC_SHIFT                         7  /* LOUT2ZC */
+#define WM8985_LOUT2ZC_WIDTH                         1  /* LOUT2ZC */
+#define WM8985_LOUT2MUTE                        0x0040  /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_MASK                   0x0040  /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_SHIFT                       6  /* LOUT2MUTE */
+#define WM8985_LOUT2MUTE_WIDTH                       1  /* LOUT2MUTE */
+#define WM8985_LOUT2VOL_MASK                    0x003F  /* LOUT2VOL - [5:0] */
+#define WM8985_LOUT2VOL_SHIFT                        0  /* LOUT2VOL - [5:0] */
+#define WM8985_LOUT2VOL_WIDTH                        6  /* LOUT2VOL - [5:0] */
+
+/*
+ * R55 (0x37) - ROUT2 (SPK) volume ctrl
+ */
+#define WM8985_OUT2VU                           0x0100  /* OUT2VU */
+#define WM8985_OUT2VU_MASK                      0x0100  /* OUT2VU */
+#define WM8985_OUT2VU_SHIFT                          8  /* OUT2VU */
+#define WM8985_OUT2VU_WIDTH                          1  /* OUT2VU */
+#define WM8985_ROUT2ZC                          0x0080  /* ROUT2ZC */
+#define WM8985_ROUT2ZC_MASK                     0x0080  /* ROUT2ZC */
+#define WM8985_ROUT2ZC_SHIFT                         7  /* ROUT2ZC */
+#define WM8985_ROUT2ZC_WIDTH                         1  /* ROUT2ZC */
+#define WM8985_ROUT2MUTE                        0x0040  /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_MASK                   0x0040  /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_SHIFT                       6  /* ROUT2MUTE */
+#define WM8985_ROUT2MUTE_WIDTH                       1  /* ROUT2MUTE */
+#define WM8985_ROUT2VOL_MASK                    0x003F  /* ROUT2VOL - [5:0] */
+#define WM8985_ROUT2VOL_SHIFT                        0  /* ROUT2VOL - [5:0] */
+#define WM8985_ROUT2VOL_WIDTH                        6  /* ROUT2VOL - [5:0] */
+
+/*
+ * R56 (0x38) - OUT3 mixer ctrl
+ */
+#define WM8985_OUT3MUTE                         0x0040  /* OUT3MUTE */
+#define WM8985_OUT3MUTE_MASK                    0x0040  /* OUT3MUTE */
+#define WM8985_OUT3MUTE_SHIFT                        6  /* OUT3MUTE */
+#define WM8985_OUT3MUTE_WIDTH                        1  /* OUT3MUTE */
+#define WM8985_OUT4_2OUT3                       0x0008  /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_MASK                  0x0008  /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_SHIFT                      3  /* OUT4_2OUT3 */
+#define WM8985_OUT4_2OUT3_WIDTH                      1  /* OUT4_2OUT3 */
+#define WM8985_BYPL2OUT3                        0x0004  /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_MASK                   0x0004  /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_SHIFT                       2  /* BYPL2OUT3 */
+#define WM8985_BYPL2OUT3_WIDTH                       1  /* BYPL2OUT3 */
+#define WM8985_LMIX2OUT3                        0x0002  /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_MASK                   0x0002  /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_SHIFT                       1  /* LMIX2OUT3 */
+#define WM8985_LMIX2OUT3_WIDTH                       1  /* LMIX2OUT3 */
+#define WM8985_LDAC2OUT3                        0x0001  /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_MASK                   0x0001  /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_SHIFT                       0  /* LDAC2OUT3 */
+#define WM8985_LDAC2OUT3_WIDTH                       1  /* LDAC2OUT3 */
+
+/*
+ * R57 (0x39) - OUT4 (MONO) mix ctrl
+ */
+#define WM8985_OUT3_2OUT4                       0x0080  /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_MASK                  0x0080  /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_SHIFT                      7  /* OUT3_2OUT4 */
+#define WM8985_OUT3_2OUT4_WIDTH                      1  /* OUT3_2OUT4 */
+#define WM8985_OUT4MUTE                         0x0040  /* OUT4MUTE */
+#define WM8985_OUT4MUTE_MASK                    0x0040  /* OUT4MUTE */
+#define WM8985_OUT4MUTE_SHIFT                        6  /* OUT4MUTE */
+#define WM8985_OUT4MUTE_WIDTH                        1  /* OUT4MUTE */
+#define WM8985_OUT4ATTN                         0x0020  /* OUT4ATTN */
+#define WM8985_OUT4ATTN_MASK                    0x0020  /* OUT4ATTN */
+#define WM8985_OUT4ATTN_SHIFT                        5  /* OUT4ATTN */
+#define WM8985_OUT4ATTN_WIDTH                        1  /* OUT4ATTN */
+#define WM8985_LMIX2OUT4                        0x0010  /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_MASK                   0x0010  /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_SHIFT                       4  /* LMIX2OUT4 */
+#define WM8985_LMIX2OUT4_WIDTH                       1  /* LMIX2OUT4 */
+#define WM8985_LDAC2OUT4                        0x0008  /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_MASK                   0x0008  /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_SHIFT                       3  /* LDAC2OUT4 */
+#define WM8985_LDAC2OUT4_WIDTH                       1  /* LDAC2OUT4 */
+#define WM8985_BYPR2OUT4                        0x0004  /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_MASK                   0x0004  /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_SHIFT                       2  /* BYPR2OUT4 */
+#define WM8985_BYPR2OUT4_WIDTH                       1  /* BYPR2OUT4 */
+#define WM8985_RMIX2OUT4                        0x0002  /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_MASK                   0x0002  /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_SHIFT                       1  /* RMIX2OUT4 */
+#define WM8985_RMIX2OUT4_WIDTH                       1  /* RMIX2OUT4 */
+#define WM8985_RDAC2OUT4                        0x0001  /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_MASK                   0x0001  /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_SHIFT                       0  /* RDAC2OUT4 */
+#define WM8985_RDAC2OUT4_WIDTH                       1  /* RDAC2OUT4 */
+
+/*
+ * R60 (0x3C) - OUTPUT ctrl
+ */
+#define WM8985_VIDBUFFTST_MASK                  0x01E0  /* VIDBUFFTST - [8:5] */
+#define WM8985_VIDBUFFTST_SHIFT                      5  /* VIDBUFFTST - [8:5] */
+#define WM8985_VIDBUFFTST_WIDTH                      4  /* VIDBUFFTST - [8:5] */
+#define WM8985_HPTOG                            0x0008  /* HPTOG */
+#define WM8985_HPTOG_MASK                       0x0008  /* HPTOG */
+#define WM8985_HPTOG_SHIFT                           3  /* HPTOG */
+#define WM8985_HPTOG_WIDTH                           1  /* HPTOG */
+
+/*
+ * R61 (0x3D) - BIAS CTRL
+ */
+#define WM8985_BIASCUT                          0x0100  /* BIASCUT */
+#define WM8985_BIASCUT_MASK                     0x0100  /* BIASCUT */
+#define WM8985_BIASCUT_SHIFT                         8  /* BIASCUT */
+#define WM8985_BIASCUT_WIDTH                         1  /* BIASCUT */
+#define WM8985_HALFIPBIAS                       0x0080  /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_MASK                  0x0080  /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_SHIFT                      7  /* HALFIPBIAS */
+#define WM8985_HALFIPBIAS_WIDTH                      1  /* HALFIPBIAS */
+#define WM8985_VBBIASTST_MASK                   0x0060  /* VBBIASTST - [6:5] */
+#define WM8985_VBBIASTST_SHIFT                       5  /* VBBIASTST - [6:5] */
+#define WM8985_VBBIASTST_WIDTH                       2  /* VBBIASTST - [6:5] */
+#define WM8985_BUFBIAS_MASK                     0x0018  /* BUFBIAS - [4:3] */
+#define WM8985_BUFBIAS_SHIFT                         3  /* BUFBIAS - [4:3] */
+#define WM8985_BUFBIAS_WIDTH                         2  /* BUFBIAS - [4:3] */
+#define WM8985_ADCBIAS_MASK                     0x0006  /* ADCBIAS - [2:1] */
+#define WM8985_ADCBIAS_SHIFT                         1  /* ADCBIAS - [2:1] */
+#define WM8985_ADCBIAS_WIDTH                         2  /* ADCBIAS - [2:1] */
+#define WM8985_HALFOPBIAS                       0x0001  /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_MASK                  0x0001  /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_SHIFT                      0  /* HALFOPBIAS */
+#define WM8985_HALFOPBIAS_WIDTH                      1  /* HALFOPBIAS */
+
+enum clk_src {
+       WM8985_CLKSRC_MCLK,
+       WM8985_CLKSRC_PLL
+};
+
+#define WM8985_PLL 0
+
+#endif
index 19ad590..d7f2597 100644 (file)
@@ -52,7 +52,7 @@ static const u16 wm8988_reg[] = {
 /* codec private data */
 struct wm8988_priv {
        unsigned int sysclk;
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
        u16 reg_cache[WM8988_NUM_REG];
 };
@@ -608,8 +608,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
                                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 snd_soc_codec *codec = rtd->codec;
        struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
        u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
        u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
@@ -711,8 +710,8 @@ static struct snd_soc_dai_ops wm8988_ops = {
        .digital_mute = wm8988_mute,
 };
 
-struct snd_soc_dai wm8988_dai = {
-       .name = "WM8988",
+static struct snd_soc_dai_driver wm8988_dai = {
+       .name = "wm8988-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -730,21 +729,15 @@ struct snd_soc_dai wm8988_dai = {
        .ops = &wm8988_ops,
        .symmetric_rates = 1,
 };
-EXPORT_SYMBOL_GPL(wm8988_dai);
 
-static int wm8988_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8988_resume(struct platform_device *pdev)
+static int wm8988_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -763,99 +756,22 @@ static int wm8988_resume(struct platform_device *pdev)
        return 0;
 }
 
-static struct snd_soc_codec *wm8988_codec;
-
-static int wm8988_probe(struct platform_device *pdev)
+static int wm8988_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
+       struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
-
-       if (wm8988_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8988_codec;
-       codec = wm8988_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, wm8988_snd_controls,
-                               ARRAY_SIZE(wm8988_snd_controls));
-       snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
-                                 ARRAY_SIZE(wm8988_dapm_widgets));
-       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-
-       return ret;
-
-pcm_err:
-       return ret;
-}
-
-static int wm8988_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_wm8988 = {
-       .probe =        wm8988_probe,
-       .remove =       wm8988_remove,
-       .suspend =      wm8988_suspend,
-       .resume =       wm8988_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
-
-static int wm8988_register(struct wm8988_priv *wm8988,
-                          enum snd_soc_control_type control)
-{
-       struct snd_soc_codec *codec = &wm8988->codec;
-       int ret;
        u16 reg;
 
-       if (wm8988_codec) {
-               dev_err(codec->dev, "Another WM8988 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm8988);
-       codec->name = "WM8988";
-       codec->owner = THIS_MODULE;
-       codec->dai = &wm8988_dai;
-       codec->num_dai = 1;
-       codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
-       codec->reg_cache = &wm8988->reg_cache;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8988_set_bias_level;
-
-       memcpy(codec->reg_cache, wm8988_reg,
-              sizeof(wm8988_reg));
-
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
-               goto err;
+               return ret;
        }
 
        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) */
@@ -870,139 +786,132 @@ static int wm8988_register(struct wm8988_priv *wm8988,
        reg = snd_soc_read(codec, WM8988_RINVOL);
        snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
 
-       wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
-
-       wm8988_dai.dev = codec->dev;
-
-       wm8988_codec = codec;
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err;
-       }
+       wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       ret = snd_soc_register_dai(&wm8988_dai);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               goto err_codec;
-       }
+       snd_soc_add_controls(codec, wm8988_snd_controls,
+                               ARRAY_SIZE(wm8988_snd_controls));
+       snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
+                                 ARRAY_SIZE(wm8988_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
 
        return 0;
-
-err_codec:
-       snd_soc_unregister_codec(codec);
-err:
-       kfree(wm8988);
-       return ret;
 }
 
-static void wm8988_unregister(struct wm8988_priv *wm8988)
+static int wm8988_remove(struct snd_soc_codec *codec)
 {
-       wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm8988_dai);
-       snd_soc_unregister_codec(&wm8988->codec);
-       kfree(wm8988);
-       wm8988_codec = NULL;
+       wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-static int wm8988_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
+       .probe =        wm8988_probe,
+       .remove =       wm8988_remove,
+       .suspend =      wm8988_suspend,
+       .resume =       wm8988_resume,
+       .set_bias_level = wm8988_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8988_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8988_reg,
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8988_spi_probe(struct spi_device *spi)
 {
        struct wm8988_priv *wm8988;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
        if (wm8988 == NULL)
                return -ENOMEM;
 
-       codec = &wm8988->codec;
-
-       i2c_set_clientdata(i2c, wm8988);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
+       wm8988->control_type = SND_SOC_SPI;
+       spi_set_drvdata(spi, wm8988);
 
-       return wm8988_register(wm8988, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&spi->dev,
+                       &soc_codec_dev_wm8988, &wm8988_dai, 1);
+       if (ret < 0)
+               kfree(wm8988);
+       return ret;
 }
 
-static int wm8988_i2c_remove(struct i2c_client *client)
+static int __devexit wm8988_spi_remove(struct spi_device *spi)
 {
-       struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
-       wm8988_unregister(wm8988);
+       snd_soc_unregister_codec(&spi->dev);
+       kfree(spi_get_drvdata(spi));
        return 0;
 }
 
-static const struct i2c_device_id wm8988_i2c_id[] = {
-       { "wm8988", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
-
-static struct i2c_driver wm8988_i2c_driver = {
+static struct spi_driver wm8988_spi_driver = {
        .driver = {
-               .name = "WM8988",
-               .owner = THIS_MODULE,
+               .name   = "wm8988-codec",
+               .owner  = THIS_MODULE,
        },
-       .probe = wm8988_i2c_probe,
-       .remove = wm8988_i2c_remove,
-       .id_table = wm8988_i2c_id,
+       .probe          = wm8988_spi_probe,
+       .remove         = __devexit_p(wm8988_spi_remove),
 };
-#endif
+#endif /* CONFIG_SPI_MASTER */
 
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8988_spi_probe(struct spi_device *spi)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
        struct wm8988_priv *wm8988;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
        if (wm8988 == NULL)
                return -ENOMEM;
 
-       codec = &wm8988->codec;
-       codec->control_data = spi;
-       codec->dev = &spi->dev;
-
-       dev_set_drvdata(&spi->dev, wm8988);
+       i2c_set_clientdata(i2c, wm8988);
+       wm8988->control_type = SND_SOC_I2C;
 
-       return wm8988_register(wm8988, SND_SOC_SPI);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8988, &wm8988_dai, 1);
+       if (ret < 0)
+               kfree(wm8988);
+       return ret;
 }
 
-static int __devexit wm8988_spi_remove(struct spi_device *spi)
+static __devexit int wm8988_i2c_remove(struct i2c_client *client)
 {
-       struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev);
-
-       wm8988_unregister(wm8988);
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
-static struct spi_driver wm8988_spi_driver = {
+static const struct i2c_device_id wm8988_i2c_id[] = {
+       { "wm8988", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
+
+static struct i2c_driver wm8988_i2c_driver = {
        .driver = {
-               .name   = "wm8988",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
+               .name = "wm8988-codec",
+               .owner = THIS_MODULE,
        },
-       .probe          = wm8988_spi_probe,
-       .remove         = __devexit_p(wm8988_spi_remove),
+       .probe =    wm8988_i2c_probe,
+       .remove =   __devexit_p(wm8988_i2c_remove),
+       .id_table = wm8988_i2c_id,
 };
 #endif
 
 static int __init wm8988_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8988_i2c_driver);
-       if (ret != 0)
-               pr_err("WM8988: Unable to register I2C driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",
+                      ret);
+       }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        ret = spi_register_driver(&wm8988_spi_driver);
-       if (ret != 0)
-               pr_err("WM8988: Unable to register SPI driver: %d\n", ret);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n",
+                      ret);
+       }
 #endif
        return ret;
 }
index 4552d37..5c04024 100644 (file)
@@ -54,7 +54,4 @@
 
 #define WM8988_SYSCLK  0
 
-extern struct snd_soc_dai wm8988_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8988;
-
 #endif
index dd8d909..264828e 100644 (file)
@@ -32,6 +32,7 @@
 
 /* codec private data */
 struct wm8990_priv {
+       enum snd_soc_control_type control_type;
        unsigned int sysclk;
        unsigned int pcmclk;
 };
@@ -1114,8 +1115,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
                            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 snd_soc_codec *codec = rtd->codec;
        u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
 
        audio1 &= ~WM8990_AIF_WL_MASK;
@@ -1293,10 +1293,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = {
        .set_sysclk     = wm8990_set_dai_sysclk,
 };
 
-struct snd_soc_dai wm8990_dai = {
+static struct snd_soc_dai_driver wm8990_dai = {
 /* ADC/DAC on primary */
-       .name = "WM8990 ADC/DAC Primary",
-       .id = 1,
+       .name = "wm8990-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1311,21 +1310,15 @@ struct snd_soc_dai wm8990_dai = {
                .formats = WM8990_FORMATS,},
        .ops = &wm8990_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm8990_dai);
 
-static int wm8990_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm8990_resume(struct platform_device *pdev)
+static int wm8990_resume(struct snd_soc_codec *codec)
 {
-       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;
@@ -1347,40 +1340,20 @@ static int wm8990_resume(struct platform_device *pdev)
  * initialise the WM8990 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8990_init(struct snd_soc_device *socdev)
+static int wm8990_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
+       int ret;
        u16 reg;
-       int ret = 0;
-
-       codec->name = "WM8990";
-       codec->owner = THIS_MODULE;
-       codec->set_bias_level = wm8990_set_bias_level;
-       codec->dai = &wm8990_dai;
-       codec->num_dai = 2;
-       codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
-       codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
-
-       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;
+               return ret;
        }
 
        wm8990_reset(codec);
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "wm8990: failed to create pcms\n");
-               goto pcm_err;
-       }
-
        /* charge output caps */
-       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);
@@ -1400,47 +1373,51 @@ static int wm8990_init(struct snd_soc_device *socdev)
                                ARRAY_SIZE(wm8990_snd_controls));
        wm8990_add_widgets(codec);
 
-       return ret;
+       return 0;
+}
 
-pcm_err:
-       kfree(codec->reg_cache);
-       return ret;
+/* power down chip */
+static int wm8990_remove(struct snd_soc_codec *codec)
+{
+       wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
 }
 
-/* If the i2c layer weren't so broken, we could pass this kind of data
-   around */
-static struct snd_soc_device *wm8990_socdev;
+static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
+       .probe =        wm8990_probe,
+       .remove =       wm8990_remove,
+       .suspend =      wm8990_suspend,
+       .resume =       wm8990_resume,
+       .set_bias_level = wm8990_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8990_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8990_reg,
+};
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM891 2 wire address is determined by GPIO5
- * state during powerup.
- *    low  = 0x34
- *    high = 0x36
- */
-
-static int wm8990_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = wm8990_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8990_priv *wm8990;
        int ret;
 
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
+       wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
+       if (wm8990 == NULL)
+               return -ENOMEM;
 
-       ret = wm8990_init(socdev);
-       if (ret < 0)
-               pr_err("failed to initialise WM8990\n");
+       i2c_set_clientdata(i2c, wm8990);
 
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8990, &wm8990_dai, 1);
+       if (ret < 0)
+               kfree(wm8990);
        return ret;
 }
 
-static int wm8990_i2c_remove(struct i2c_client *client)
+static __devexit int wm8990_i2c_remove(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1452,134 +1429,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
 
 static struct i2c_driver wm8990_i2c_driver = {
        .driver = {
-               .name = "WM8990 I2C Codec",
+               .name = "wm8990-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm8990_i2c_probe,
-       .remove =   wm8990_i2c_remove,
+       .remove =   __devexit_p(wm8990_i2c_remove),
        .id_table = wm8990_i2c_id,
 };
-
-static int wm8990_add_i2c_device(struct platform_device *pdev,
-                                const struct wm8990_setup_data *setup)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
-
-       ret = i2c_add_driver(&wm8990_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "wm8990", 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(&wm8990_i2c_driver);
-       return -ENODEV;
-}
 #endif
 
-static int wm8990_probe(struct platform_device *pdev)
+static int __init wm8990_modinit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct wm8990_setup_data *setup;
-       struct snd_soc_codec *codec;
-       struct wm8990_priv *wm8990;
-       int ret;
-
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
-
-       wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
-       if (wm8990 == NULL) {
-               kfree(codec);
-               return -ENOMEM;
-       }
-
-       snd_soc_codec_set_drvdata(codec, wm8990);
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-       wm8990_socdev = socdev;
-
-       ret = -ENODEV;
-
+       int ret = 0;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
-               ret = wm8990_add_i2c_device(pdev, setup);
-       }
-#endif
-
+       ret = i2c_add_driver(&wm8990_i2c_driver);
        if (ret != 0) {
-               kfree(snd_soc_codec_get_drvdata(codec));
-               kfree(codec);
+               printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n",
+                      ret);
        }
+#endif
        return ret;
 }
+module_init(wm8990_modinit);
 
-/* power down chip */
-static int wm8990_remove(struct platform_device *pdev)
+static void __exit wm8990_exit(void)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               wm8990_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(&wm8990_i2c_driver);
 #endif
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec);
-
-       return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8990 = {
-       .probe =        wm8990_probe,
-       .remove =       wm8990_remove,
-       .suspend =      wm8990_suspend,
-       .resume =       wm8990_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
-
-static int __init wm8990_modinit(void)
-{
-       return snd_soc_register_dai(&wm8990_dai);
-}
-module_init(wm8990_modinit);
-
-static void __exit wm8990_exit(void)
-{
-       snd_soc_unregister_dai(&wm8990_dai);
 }
 module_exit(wm8990_exit);
 
index 7114ddc..77c98a4 100644 (file)
 #define WM8990_INMIXR_PWR_BIT                  2
 #define WM8990_AINRMUX_PWR_BIT                 3
 
-struct wm8990_setup_data {
-       unsigned i2c_bus;
-       unsigned short i2c_address;
-};
-
 #define WM8990_MCLK_DIV 0
 #define WM8990_DACCLK_DIV 1
 #define WM8990_ADCCLK_DIV 2
 #define WM8990_BCLK_DIV 3
 
-extern struct snd_soc_dai wm8990_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8990;
-
 #endif /* __WM8990REGISTERDEFS_H__ */
 /*------------------------------ END OF FILE ---------------------------------*/
index d8d300c..589e3fa 100644 (file)
@@ -229,7 +229,7 @@ struct wm8993_priv {
        u16 reg_cache[WM8993_REGISTER_COUNT];
        struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
        struct wm8993_platform_data pdata;
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
        int master;
        int sysclk_source;
        int tdm_slots;
@@ -367,10 +367,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
        return 0;
 }
 
-static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
                          unsigned int Fref, unsigned int Fout)
 {
-       struct snd_soc_codec *codec = dai->codec;
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        u16 reg1, reg4, reg5;
        struct _fll_div fll_div;
@@ -456,6 +455,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
        return 0;
 }
 
+static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
+                         unsigned int Fref, unsigned int Fout)
+{
+       return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout);
+}
+
 static int configure_clock(struct snd_soc_codec *codec)
 {
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
@@ -1394,8 +1399,8 @@ static struct snd_soc_dai_ops wm8993_ops = {
                        SNDRV_PCM_FMTBIT_S24_LE |\
                        SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_dai wm8993_dai = {
-       .name = "WM8993",
+static struct snd_soc_dai_driver wm8993_dai = {
+       .name = "wm8993-hifi",
        .playback = {
                .stream_name = "Playback",
                .channels_min = 1,
@@ -1413,32 +1418,81 @@ struct snd_soc_dai wm8993_dai = {
        .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)
+static int wm8993_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct wm8993_priv *wm8993;
-       int ret = 0;
+       struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+       int ret, i, val;
+
+       wm8993->hubs_data.hp_startup_mode = 1;
+       wm8993->hubs_data.dcs_codes = -2;
+
+       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);
+               return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+               wm8993->supplies[i].supply = wm8993_supply_names[i];
 
-       if (!wm8993_codec) {
-               dev_err(&pdev->dev, "I2C device not yet probed\n");
-               goto err;
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
+                                wm8993->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
        }
 
-       socdev->card->codec = wm8993_codec;
-       codec = wm8993_codec;
-       wm8993 = snd_soc_codec_get_drvdata(codec);
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
+                                   wm8993->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
 
-       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;
+       val = snd_soc_read(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_enable;
        }
 
+       ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
+       if (ret != 0)
+               goto err_enable;
+
+       codec->cache_only = 1;
+
+       /* 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);
+
+       wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
+                                     wm8993->pdata.lineout2_diff,
+                                     wm8993->pdata.lineout1fb,
+                                     wm8993->pdata.lineout2fb,
+                                     wm8993->pdata.jd_scthr,
+                                     wm8993->pdata.jd_thr,
+                                     wm8993->pdata.micbias1_lvl,
+                                     wm8993->pdata.micbias2_lvl);
+
+       ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       if (ret != 0)
+               goto err_enable;
+
        snd_soc_add_controls(codec, wm8993_snd_controls,
                             ARRAY_SIZE(wm8993_snd_controls));
        if (wm8993->pdata.num_retune_configs != 0) {
@@ -1457,36 +1511,36 @@ static int wm8993_probe(struct platform_device *pdev)
        wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
                                    wm8993->pdata.lineout2_diff);
 
-       return ret;
+       return 0;
 
-err:
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
        return ret;
 }
 
-static int wm8993_remove(struct platform_device *pdev)
+static int wm8993_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
 
+       wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        int fll_fout = wm8993->fll_fout;
        int fll_fref  = wm8993->fll_fref;
        int ret;
 
        /* Stop the FLL in an orderly fashion */
-       ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0);
+       ret = _wm8993_set_fll(codec, 0, 0, 0, 0);
        if (ret != 0) {
-               dev_err(&pdev->dev, "Failed to stop FLL\n");
+               dev_err(codec->dev, "Failed to stop FLL\n");
                return ret;
        }
 
@@ -1498,10 +1552,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int wm8993_resume(struct platform_device *pdev)
+static int wm8993_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
@@ -1515,7 +1567,7 @@ static int wm8993_resume(struct platform_device *pdev)
                wm8993->fll_fref = 0;
                wm8993->fll_fout = 0;
 
-               ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src,
+               ret = _wm8993_set_fll(codec, 0, wm8993->fll_src,
                                     fll_fref, fll_fout);
                if (ret != 0)
                        dev_err(codec->dev, "Failed to restart FLL\n");
@@ -1528,162 +1580,42 @@ static int wm8993_resume(struct platform_device *pdev)
 #define wm8993_resume NULL
 #endif
 
-struct snd_soc_codec_device soc_codec_dev_wm8993 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
        .probe =        wm8993_probe,
        .remove =       wm8993_remove,
        .suspend =      wm8993_suspend,
        .resume =       wm8993_resume,
+       .set_bias_level = wm8993_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm8993_reg_defaults,
+       .volatile_register = wm8993_volatile,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
 
-static int wm8993_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit 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;
-       int i;
-
-       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->volatile_register = wm8993_volatile;
-       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;
-       snd_soc_codec_set_drvdata(codec, wm8993);
-
-       wm8993->hubs_data.hp_startup_mode = 1;
-       wm8993->hubs_data.dcs_codes = -2;
-
-       memcpy(wm8993->reg_cache, wm8993_reg_defaults,
-              sizeof(wm8993->reg_cache));
-
-       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;
-       }
-
        i2c_set_clientdata(i2c, wm8993);
-       codec->control_data = i2c;
-       wm8993_codec = codec;
-
-       codec->dev = &i2c->dev;
-
-       for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
-               wm8993->supplies[i].supply = wm8993_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
-                                wm8993->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               goto err;
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
-                                   wm8993->supplies);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_get;
-       }
-
-       val = snd_soc_read(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_enable;
-       }
-
-       ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
-       if (ret != 0)
-               goto err_enable;
-
-       codec->cache_only = 1;
-
-       /* 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);
-
-       wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
-                                     wm8993->pdata.lineout2_diff,
-                                     wm8993->pdata.lineout1fb,
-                                     wm8993->pdata.lineout2fb,
-                                     wm8993->pdata.jd_scthr,
-                                     wm8993->pdata.jd_thr,
-                                     wm8993->pdata.micbias1_lvl,
-                                     wm8993->pdata.micbias2_lvl);
-                            
-       ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       if (ret != 0)
-               goto err_enable;
-
-       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_enable:
-       regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err:
-       wm8993_codec = NULL;
-       kfree(wm8993);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm8993, &wm8993_dai, 1);
+       if (ret < 0)
+               kfree(wm8993);
        return ret;
 }
 
-static int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit 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);
-       regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-       kfree(wm8993);
-
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1695,30 +1627,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
 
 static struct i2c_driver wm8993_i2c_driver = {
        .driver = {
-               .name = "WM8993",
+               .name = "wm8993-codec",
                .owner = THIS_MODULE,
        },
-       .probe = wm8993_i2c_probe,
-       .remove = wm8993_i2c_remove,
+       .probe =    wm8993_i2c_probe,
+       .remove =   __devexit_p(wm8993_i2c_remove),
        .id_table = wm8993_i2c_id,
 };
-
+#endif
 
 static int __init wm8993_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8993_i2c_driver);
-       if (ret != 0)
-               pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
-
+       if (ret != 0) {
+               pr_err("WM8993: Unable to register I2C driver: %d\n",
+                      ret);
+       }
+#endif
        return ret;
 }
 module_init(wm8993_modinit);
 
 static void __exit wm8993_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm8993_i2c_driver);
+#endif
 }
 module_exit(wm8993_exit);
 
index 30e71ca..2184617 100644 (file)
@@ -1,9 +1,6 @@
 #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
 
index 522249d..0db59c3 100644 (file)
@@ -36,9 +36,6 @@
 #include "wm8994.h"
 #include "wm_hubs.h"
 
-static struct snd_soc_codec *wm8994_codec;
-struct snd_soc_codec_device soc_codec_dev_wm8994;
-
 struct fll_config {
        int src;
        int in;
@@ -71,7 +68,9 @@ struct wm8994_micdet {
 /* codec private data */
 struct wm8994_priv {
        struct wm_hubs_data hubs;
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
+       struct snd_soc_codec *codec;
        u16 reg_cache[WM8994_REG_CACHE_SIZE + 1];
        int sysclk[2];
        int sysclk_rate[2];
@@ -99,1581 +98,1580 @@ struct wm8994_priv {
        struct wm8994_pdata *pdata;
 };
 
-static struct {
-       unsigned short  readable;   /* Mask of readable bits */
-       unsigned short  writable;   /* Mask of writable bits */
-       unsigned short  vol;        /* Mask of volatile bits */
+static const struct {
+       unsigned short readable;   /* Mask of readable bits */
+       unsigned short writable;   /* Mask of writable bits */
 } access_masks[] = {
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R0     - Software Reset */
-       { 0x3B37, 0x3B37, 0x0000 }, /* R1     - Power Management (1) */
-       { 0x6BF0, 0x6BF0, 0x0000 }, /* R2     - Power Management (2) */
-       { 0x3FF0, 0x3FF0, 0x0000 }, /* R3     - Power Management (3) */
-       { 0x3F3F, 0x3F3F, 0x0000 }, /* R4     - Power Management (4) */
-       { 0x3F0F, 0x3F0F, 0x0000 }, /* R5     - Power Management (5) */
-       { 0x003F, 0x003F, 0x0000 }, /* R6     - Power Management (6) */
-       { 0x0000, 0x0000, 0x0000 }, /* R7 */
-       { 0x0000, 0x0000, 0x0000 }, /* R8 */
-       { 0x0000, 0x0000, 0x0000 }, /* R9 */
-       { 0x0000, 0x0000, 0x0000 }, /* R10 */
-       { 0x0000, 0x0000, 0x0000 }, /* R11 */
-       { 0x0000, 0x0000, 0x0000 }, /* R12 */
-       { 0x0000, 0x0000, 0x0000 }, /* R13 */
-       { 0x0000, 0x0000, 0x0000 }, /* R14 */
-       { 0x0000, 0x0000, 0x0000 }, /* R15 */
-       { 0x0000, 0x0000, 0x0000 }, /* R16 */
-       { 0x0000, 0x0000, 0x0000 }, /* R17 */
-       { 0x0000, 0x0000, 0x0000 }, /* R18 */
-       { 0x0000, 0x0000, 0x0000 }, /* R19 */
-       { 0x0000, 0x0000, 0x0000 }, /* R20 */
-       { 0x01C0, 0x01C0, 0x0000 }, /* R21    - Input Mixer (1) */
-       { 0x0000, 0x0000, 0x0000 }, /* R22 */
-       { 0x0000, 0x0000, 0x0000 }, /* R23 */
-       { 0x00DF, 0x01DF, 0x0000 }, /* R24    - Left Line Input 1&2 Volume */
-       { 0x00DF, 0x01DF, 0x0000 }, /* R25    - Left Line Input 3&4 Volume */
-       { 0x00DF, 0x01DF, 0x0000 }, /* R26    - Right Line Input 1&2 Volume */
-       { 0x00DF, 0x01DF, 0x0000 }, /* R27    - Right Line Input 3&4 Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R28    - Left Output Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R29    - Right Output Volume */
-       { 0x0077, 0x0077, 0x0000 }, /* R30    - Line Outputs Volume */
-       { 0x0030, 0x0030, 0x0000 }, /* R31    - HPOUT2 Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R32    - Left OPGA Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R33    - Right OPGA Volume */
-       { 0x007F, 0x007F, 0x0000 }, /* R34    - SPKMIXL Attenuation */
-       { 0x017F, 0x017F, 0x0000 }, /* R35    - SPKMIXR Attenuation */
-       { 0x003F, 0x003F, 0x0000 }, /* R36    - SPKOUT Mixers */
-       { 0x003F, 0x003F, 0x0000 }, /* R37    - ClassD */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R38    - Speaker Volume Left */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R39    - Speaker Volume Right */
-       { 0x00FF, 0x00FF, 0x0000 }, /* R40    - Input Mixer (2) */
-       { 0x01B7, 0x01B7, 0x0000 }, /* R41    - Input Mixer (3) */
-       { 0x01B7, 0x01B7, 0x0000 }, /* R42    - Input Mixer (4) */
-       { 0x01C7, 0x01C7, 0x0000 }, /* R43    - Input Mixer (5) */
-       { 0x01C7, 0x01C7, 0x0000 }, /* R44    - Input Mixer (6) */
-       { 0x01FF, 0x01FF, 0x0000 }, /* R45    - Output Mixer (1) */
-       { 0x01FF, 0x01FF, 0x0000 }, /* R46    - Output Mixer (2) */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R47    - Output Mixer (3) */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R48    - Output Mixer (4) */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R49    - Output Mixer (5) */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R50    - Output Mixer (6) */
-       { 0x0038, 0x0038, 0x0000 }, /* R51    - HPOUT2 Mixer */
-       { 0x0077, 0x0077, 0x0000 }, /* R52    - Line Mixer (1) */
-       { 0x0077, 0x0077, 0x0000 }, /* R53    - Line Mixer (2) */
-       { 0x03FF, 0x03FF, 0x0000 }, /* R54    - Speaker Mixer */
-       { 0x00C1, 0x00C1, 0x0000 }, /* R55    - Additional Control */
-       { 0x00F0, 0x00F0, 0x0000 }, /* R56    - AntiPOP (1) */
-       { 0x01EF, 0x01EF, 0x0000 }, /* R57    - AntiPOP (2) */
-       { 0x00FF, 0x00FF, 0x0000 }, /* R58    - MICBIAS */
-       { 0x000F, 0x000F, 0x0000 }, /* R59    - LDO 1 */
-       { 0x0007, 0x0007, 0x0000 }, /* R60    - LDO 2 */
-       { 0x0000, 0x0000, 0x0000 }, /* R61 */
-       { 0x0000, 0x0000, 0x0000 }, /* R62 */
-       { 0x0000, 0x0000, 0x0000 }, /* R63 */
-       { 0x0000, 0x0000, 0x0000 }, /* R64 */
-       { 0x0000, 0x0000, 0x0000 }, /* R65 */
-       { 0x0000, 0x0000, 0x0000 }, /* R66 */
-       { 0x0000, 0x0000, 0x0000 }, /* R67 */
-       { 0x0000, 0x0000, 0x0000 }, /* R68 */
-       { 0x0000, 0x0000, 0x0000 }, /* R69 */
-       { 0x0000, 0x0000, 0x0000 }, /* R70 */
-       { 0x0000, 0x0000, 0x0000 }, /* R71 */
-       { 0x0000, 0x0000, 0x0000 }, /* R72 */
-       { 0x0000, 0x0000, 0x0000 }, /* R73 */
-       { 0x0000, 0x0000, 0x0000 }, /* R74 */
-       { 0x0000, 0x0000, 0x0000 }, /* R75 */
-       { 0x8000, 0x8000, 0x0000 }, /* R76    - Charge Pump (1) */
-       { 0x0000, 0x0000, 0x0000 }, /* R77 */
-       { 0x0000, 0x0000, 0x0000 }, /* R78 */
-       { 0x0000, 0x0000, 0x0000 }, /* R79 */
-       { 0x0000, 0x0000, 0x0000 }, /* R80 */
-       { 0x0301, 0x0301, 0x0000 }, /* R81    - Class W (1) */
-       { 0x0000, 0x0000, 0x0000 }, /* R82 */
-       { 0x0000, 0x0000, 0x0000 }, /* R83 */
-       { 0x333F, 0x333F, 0x0000 }, /* R84    - DC Servo (1) */
-       { 0x0FEF, 0x0FEF, 0x0000 }, /* R85    - DC Servo (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R86 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R87    - DC Servo (4) */
-       { 0x0333, 0x0000, 0x0000 }, /* R88    - DC Servo Readback */
-       { 0x0000, 0x0000, 0x0000 }, /* R89 */
-       { 0x0000, 0x0000, 0x0000 }, /* R90 */
-       { 0x0000, 0x0000, 0x0000 }, /* R91 */
-       { 0x0000, 0x0000, 0x0000 }, /* R92 */
-       { 0x0000, 0x0000, 0x0000 }, /* R93 */
-       { 0x0000, 0x0000, 0x0000 }, /* R94 */
-       { 0x0000, 0x0000, 0x0000 }, /* R95 */
-       { 0x00EE, 0x00EE, 0x0000 }, /* R96    - Analogue HP (1) */
-       { 0x0000, 0x0000, 0x0000 }, /* R97 */
-       { 0x0000, 0x0000, 0x0000 }, /* R98 */
-       { 0x0000, 0x0000, 0x0000 }, /* R99 */
-       { 0x0000, 0x0000, 0x0000 }, /* R100 */
-       { 0x0000, 0x0000, 0x0000 }, /* R101 */
-       { 0x0000, 0x0000, 0x0000 }, /* R102 */
-       { 0x0000, 0x0000, 0x0000 }, /* R103 */
-       { 0x0000, 0x0000, 0x0000 }, /* R104 */
-       { 0x0000, 0x0000, 0x0000 }, /* R105 */
-       { 0x0000, 0x0000, 0x0000 }, /* R106 */
-       { 0x0000, 0x0000, 0x0000 }, /* R107 */
-       { 0x0000, 0x0000, 0x0000 }, /* R108 */
-       { 0x0000, 0x0000, 0x0000 }, /* R109 */
-       { 0x0000, 0x0000, 0x0000 }, /* R110 */
-       { 0x0000, 0x0000, 0x0000 }, /* R111 */
-       { 0x0000, 0x0000, 0x0000 }, /* R112 */
-       { 0x0000, 0x0000, 0x0000 }, /* R113 */
-       { 0x0000, 0x0000, 0x0000 }, /* R114 */
-       { 0x0000, 0x0000, 0x0000 }, /* R115 */
-       { 0x0000, 0x0000, 0x0000 }, /* R116 */
-       { 0x0000, 0x0000, 0x0000 }, /* R117 */
-       { 0x0000, 0x0000, 0x0000 }, /* R118 */
-       { 0x0000, 0x0000, 0x0000 }, /* R119 */
-       { 0x0000, 0x0000, 0x0000 }, /* R120 */
-       { 0x0000, 0x0000, 0x0000 }, /* R121 */
-       { 0x0000, 0x0000, 0x0000 }, /* R122 */
-       { 0x0000, 0x0000, 0x0000 }, /* R123 */
-       { 0x0000, 0x0000, 0x0000 }, /* R124 */
-       { 0x0000, 0x0000, 0x0000 }, /* R125 */
-       { 0x0000, 0x0000, 0x0000 }, /* R126 */
-       { 0x0000, 0x0000, 0x0000 }, /* R127 */
-       { 0x0000, 0x0000, 0x0000 }, /* R128 */
-       { 0x0000, 0x0000, 0x0000 }, /* R129 */
-       { 0x0000, 0x0000, 0x0000 }, /* R130 */
-       { 0x0000, 0x0000, 0x0000 }, /* R131 */
-       { 0x0000, 0x0000, 0x0000 }, /* R132 */
-       { 0x0000, 0x0000, 0x0000 }, /* R133 */
-       { 0x0000, 0x0000, 0x0000 }, /* R134 */
-       { 0x0000, 0x0000, 0x0000 }, /* R135 */
-       { 0x0000, 0x0000, 0x0000 }, /* R136 */
-       { 0x0000, 0x0000, 0x0000 }, /* R137 */
-       { 0x0000, 0x0000, 0x0000 }, /* R138 */
-       { 0x0000, 0x0000, 0x0000 }, /* R139 */
-       { 0x0000, 0x0000, 0x0000 }, /* R140 */
-       { 0x0000, 0x0000, 0x0000 }, /* R141 */
-       { 0x0000, 0x0000, 0x0000 }, /* R142 */
-       { 0x0000, 0x0000, 0x0000 }, /* R143 */
-       { 0x0000, 0x0000, 0x0000 }, /* R144 */
-       { 0x0000, 0x0000, 0x0000 }, /* R145 */
-       { 0x0000, 0x0000, 0x0000 }, /* R146 */
-       { 0x0000, 0x0000, 0x0000 }, /* R147 */
-       { 0x0000, 0x0000, 0x0000 }, /* R148 */
-       { 0x0000, 0x0000, 0x0000 }, /* R149 */
-       { 0x0000, 0x0000, 0x0000 }, /* R150 */
-       { 0x0000, 0x0000, 0x0000 }, /* R151 */
-       { 0x0000, 0x0000, 0x0000 }, /* R152 */
-       { 0x0000, 0x0000, 0x0000 }, /* R153 */
-       { 0x0000, 0x0000, 0x0000 }, /* R154 */
-       { 0x0000, 0x0000, 0x0000 }, /* R155 */
-       { 0x0000, 0x0000, 0x0000 }, /* R156 */
-       { 0x0000, 0x0000, 0x0000 }, /* R157 */
-       { 0x0000, 0x0000, 0x0000 }, /* R158 */
-       { 0x0000, 0x0000, 0x0000 }, /* R159 */
-       { 0x0000, 0x0000, 0x0000 }, /* R160 */
-       { 0x0000, 0x0000, 0x0000 }, /* R161 */
-       { 0x0000, 0x0000, 0x0000 }, /* R162 */
-       { 0x0000, 0x0000, 0x0000 }, /* R163 */
-       { 0x0000, 0x0000, 0x0000 }, /* R164 */
-       { 0x0000, 0x0000, 0x0000 }, /* R165 */
-       { 0x0000, 0x0000, 0x0000 }, /* R166 */
-       { 0x0000, 0x0000, 0x0000 }, /* R167 */
-       { 0x0000, 0x0000, 0x0000 }, /* R168 */
-       { 0x0000, 0x0000, 0x0000 }, /* R169 */
-       { 0x0000, 0x0000, 0x0000 }, /* R170 */
-       { 0x0000, 0x0000, 0x0000 }, /* R171 */
-       { 0x0000, 0x0000, 0x0000 }, /* R172 */
-       { 0x0000, 0x0000, 0x0000 }, /* R173 */
-       { 0x0000, 0x0000, 0x0000 }, /* R174 */
-       { 0x0000, 0x0000, 0x0000 }, /* R175 */
-       { 0x0000, 0x0000, 0x0000 }, /* R176 */
-       { 0x0000, 0x0000, 0x0000 }, /* R177 */
-       { 0x0000, 0x0000, 0x0000 }, /* R178 */
-       { 0x0000, 0x0000, 0x0000 }, /* R179 */
-       { 0x0000, 0x0000, 0x0000 }, /* R180 */
-       { 0x0000, 0x0000, 0x0000 }, /* R181 */
-       { 0x0000, 0x0000, 0x0000 }, /* R182 */
-       { 0x0000, 0x0000, 0x0000 }, /* R183 */
-       { 0x0000, 0x0000, 0x0000 }, /* R184 */
-       { 0x0000, 0x0000, 0x0000 }, /* R185 */
-       { 0x0000, 0x0000, 0x0000 }, /* R186 */
-       { 0x0000, 0x0000, 0x0000 }, /* R187 */
-       { 0x0000, 0x0000, 0x0000 }, /* R188 */
-       { 0x0000, 0x0000, 0x0000 }, /* R189 */
-       { 0x0000, 0x0000, 0x0000 }, /* R190 */
-       { 0x0000, 0x0000, 0x0000 }, /* R191 */
-       { 0x0000, 0x0000, 0x0000 }, /* R192 */
-       { 0x0000, 0x0000, 0x0000 }, /* R193 */
-       { 0x0000, 0x0000, 0x0000 }, /* R194 */
-       { 0x0000, 0x0000, 0x0000 }, /* R195 */
-       { 0x0000, 0x0000, 0x0000 }, /* R196 */
-       { 0x0000, 0x0000, 0x0000 }, /* R197 */
-       { 0x0000, 0x0000, 0x0000 }, /* R198 */
-       { 0x0000, 0x0000, 0x0000 }, /* R199 */
-       { 0x0000, 0x0000, 0x0000 }, /* R200 */
-       { 0x0000, 0x0000, 0x0000 }, /* R201 */
-       { 0x0000, 0x0000, 0x0000 }, /* R202 */
-       { 0x0000, 0x0000, 0x0000 }, /* R203 */
-       { 0x0000, 0x0000, 0x0000 }, /* R204 */
-       { 0x0000, 0x0000, 0x0000 }, /* R205 */
-       { 0x0000, 0x0000, 0x0000 }, /* R206 */
-       { 0x0000, 0x0000, 0x0000 }, /* R207 */
-       { 0x0000, 0x0000, 0x0000 }, /* R208 */
-       { 0x0000, 0x0000, 0x0000 }, /* R209 */
-       { 0x0000, 0x0000, 0x0000 }, /* R210 */
-       { 0x0000, 0x0000, 0x0000 }, /* R211 */
-       { 0x0000, 0x0000, 0x0000 }, /* R212 */
-       { 0x0000, 0x0000, 0x0000 }, /* R213 */
-       { 0x0000, 0x0000, 0x0000 }, /* R214 */
-       { 0x0000, 0x0000, 0x0000 }, /* R215 */
-       { 0x0000, 0x0000, 0x0000 }, /* R216 */
-       { 0x0000, 0x0000, 0x0000 }, /* R217 */
-       { 0x0000, 0x0000, 0x0000 }, /* R218 */
-       { 0x0000, 0x0000, 0x0000 }, /* R219 */
-       { 0x0000, 0x0000, 0x0000 }, /* R220 */
-       { 0x0000, 0x0000, 0x0000 }, /* R221 */
-       { 0x0000, 0x0000, 0x0000 }, /* R222 */
-       { 0x0000, 0x0000, 0x0000 }, /* R223 */
-       { 0x0000, 0x0000, 0x0000 }, /* R224 */
-       { 0x0000, 0x0000, 0x0000 }, /* R225 */
-       { 0x0000, 0x0000, 0x0000 }, /* R226 */
-       { 0x0000, 0x0000, 0x0000 }, /* R227 */
-       { 0x0000, 0x0000, 0x0000 }, /* R228 */
-       { 0x0000, 0x0000, 0x0000 }, /* R229 */
-       { 0x0000, 0x0000, 0x0000 }, /* R230 */
-       { 0x0000, 0x0000, 0x0000 }, /* R231 */
-       { 0x0000, 0x0000, 0x0000 }, /* R232 */
-       { 0x0000, 0x0000, 0x0000 }, /* R233 */
-       { 0x0000, 0x0000, 0x0000 }, /* R234 */
-       { 0x0000, 0x0000, 0x0000 }, /* R235 */
-       { 0x0000, 0x0000, 0x0000 }, /* R236 */
-       { 0x0000, 0x0000, 0x0000 }, /* R237 */
-       { 0x0000, 0x0000, 0x0000 }, /* R238 */
-       { 0x0000, 0x0000, 0x0000 }, /* R239 */
-       { 0x0000, 0x0000, 0x0000 }, /* R240 */
-       { 0x0000, 0x0000, 0x0000 }, /* R241 */
-       { 0x0000, 0x0000, 0x0000 }, /* R242 */
-       { 0x0000, 0x0000, 0x0000 }, /* R243 */
-       { 0x0000, 0x0000, 0x0000 }, /* R244 */
-       { 0x0000, 0x0000, 0x0000 }, /* R245 */
-       { 0x0000, 0x0000, 0x0000 }, /* R246 */
-       { 0x0000, 0x0000, 0x0000 }, /* R247 */
-       { 0x0000, 0x0000, 0x0000 }, /* R248 */
-       { 0x0000, 0x0000, 0x0000 }, /* R249 */
-       { 0x0000, 0x0000, 0x0000 }, /* R250 */
-       { 0x0000, 0x0000, 0x0000 }, /* R251 */
-       { 0x0000, 0x0000, 0x0000 }, /* R252 */
-       { 0x0000, 0x0000, 0x0000 }, /* R253 */
-       { 0x0000, 0x0000, 0x0000 }, /* R254 */
-       { 0x0000, 0x0000, 0x0000 }, /* R255 */
-       { 0x000F, 0x0000, 0x0000 }, /* R256   - Chip Revision */
-       { 0x0074, 0x0074, 0x0000 }, /* R257   - Control Interface */
-       { 0x0000, 0x0000, 0x0000 }, /* R258 */
-       { 0x0000, 0x0000, 0x0000 }, /* R259 */
-       { 0x0000, 0x0000, 0x0000 }, /* R260 */
-       { 0x0000, 0x0000, 0x0000 }, /* R261 */
-       { 0x0000, 0x0000, 0x0000 }, /* R262 */
-       { 0x0000, 0x0000, 0x0000 }, /* R263 */
-       { 0x0000, 0x0000, 0x0000 }, /* R264 */
-       { 0x0000, 0x0000, 0x0000 }, /* R265 */
-       { 0x0000, 0x0000, 0x0000 }, /* R266 */
-       { 0x0000, 0x0000, 0x0000 }, /* R267 */
-       { 0x0000, 0x0000, 0x0000 }, /* R268 */
-       { 0x0000, 0x0000, 0x0000 }, /* R269 */
-       { 0x0000, 0x0000, 0x0000 }, /* R270 */
-       { 0x0000, 0x0000, 0x0000 }, /* R271 */
-       { 0x807F, 0x837F, 0x0000 }, /* R272   - Write Sequencer Ctrl (1) */
-       { 0x017F, 0x0000, 0x0000 }, /* R273   - Write Sequencer Ctrl (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R274 */
-       { 0x0000, 0x0000, 0x0000 }, /* R275 */
-       { 0x0000, 0x0000, 0x0000 }, /* R276 */
-       { 0x0000, 0x0000, 0x0000 }, /* R277 */
-       { 0x0000, 0x0000, 0x0000 }, /* R278 */
-       { 0x0000, 0x0000, 0x0000 }, /* R279 */
-       { 0x0000, 0x0000, 0x0000 }, /* R280 */
-       { 0x0000, 0x0000, 0x0000 }, /* R281 */
-       { 0x0000, 0x0000, 0x0000 }, /* R282 */
-       { 0x0000, 0x0000, 0x0000 }, /* R283 */
-       { 0x0000, 0x0000, 0x0000 }, /* R284 */
-       { 0x0000, 0x0000, 0x0000 }, /* R285 */
-       { 0x0000, 0x0000, 0x0000 }, /* R286 */
-       { 0x0000, 0x0000, 0x0000 }, /* R287 */
-       { 0x0000, 0x0000, 0x0000 }, /* R288 */
-       { 0x0000, 0x0000, 0x0000 }, /* R289 */
-       { 0x0000, 0x0000, 0x0000 }, /* R290 */
-       { 0x0000, 0x0000, 0x0000 }, /* R291 */
-       { 0x0000, 0x0000, 0x0000 }, /* R292 */
-       { 0x0000, 0x0000, 0x0000 }, /* R293 */
-       { 0x0000, 0x0000, 0x0000 }, /* R294 */
-       { 0x0000, 0x0000, 0x0000 }, /* R295 */
-       { 0x0000, 0x0000, 0x0000 }, /* R296 */
-       { 0x0000, 0x0000, 0x0000 }, /* R297 */
-       { 0x0000, 0x0000, 0x0000 }, /* R298 */
-       { 0x0000, 0x0000, 0x0000 }, /* R299 */
-       { 0x0000, 0x0000, 0x0000 }, /* R300 */
-       { 0x0000, 0x0000, 0x0000 }, /* R301 */
-       { 0x0000, 0x0000, 0x0000 }, /* R302 */
-       { 0x0000, 0x0000, 0x0000 }, /* R303 */
-       { 0x0000, 0x0000, 0x0000 }, /* R304 */
-       { 0x0000, 0x0000, 0x0000 }, /* R305 */
-       { 0x0000, 0x0000, 0x0000 }, /* R306 */
-       { 0x0000, 0x0000, 0x0000 }, /* R307 */
-       { 0x0000, 0x0000, 0x0000 }, /* R308 */
-       { 0x0000, 0x0000, 0x0000 }, /* R309 */
-       { 0x0000, 0x0000, 0x0000 }, /* R310 */
-       { 0x0000, 0x0000, 0x0000 }, /* R311 */
-       { 0x0000, 0x0000, 0x0000 }, /* R312 */
-       { 0x0000, 0x0000, 0x0000 }, /* R313 */
-       { 0x0000, 0x0000, 0x0000 }, /* R314 */
-       { 0x0000, 0x0000, 0x0000 }, /* R315 */
-       { 0x0000, 0x0000, 0x0000 }, /* R316 */
-       { 0x0000, 0x0000, 0x0000 }, /* R317 */
-       { 0x0000, 0x0000, 0x0000 }, /* R318 */
-       { 0x0000, 0x0000, 0x0000 }, /* R319 */
-       { 0x0000, 0x0000, 0x0000 }, /* R320 */
-       { 0x0000, 0x0000, 0x0000 }, /* R321 */
-       { 0x0000, 0x0000, 0x0000 }, /* R322 */
-       { 0x0000, 0x0000, 0x0000 }, /* R323 */
-       { 0x0000, 0x0000, 0x0000 }, /* R324 */
-       { 0x0000, 0x0000, 0x0000 }, /* R325 */
-       { 0x0000, 0x0000, 0x0000 }, /* R326 */
-       { 0x0000, 0x0000, 0x0000 }, /* R327 */
-       { 0x0000, 0x0000, 0x0000 }, /* R328 */
-       { 0x0000, 0x0000, 0x0000 }, /* R329 */
-       { 0x0000, 0x0000, 0x0000 }, /* R330 */
-       { 0x0000, 0x0000, 0x0000 }, /* R331 */
-       { 0x0000, 0x0000, 0x0000 }, /* R332 */
-       { 0x0000, 0x0000, 0x0000 }, /* R333 */
-       { 0x0000, 0x0000, 0x0000 }, /* R334 */
-       { 0x0000, 0x0000, 0x0000 }, /* R335 */
-       { 0x0000, 0x0000, 0x0000 }, /* R336 */
-       { 0x0000, 0x0000, 0x0000 }, /* R337 */
-       { 0x0000, 0x0000, 0x0000 }, /* R338 */
-       { 0x0000, 0x0000, 0x0000 }, /* R339 */
-       { 0x0000, 0x0000, 0x0000 }, /* R340 */
-       { 0x0000, 0x0000, 0x0000 }, /* R341 */
-       { 0x0000, 0x0000, 0x0000 }, /* R342 */
-       { 0x0000, 0x0000, 0x0000 }, /* R343 */
-       { 0x0000, 0x0000, 0x0000 }, /* R344 */
-       { 0x0000, 0x0000, 0x0000 }, /* R345 */
-       { 0x0000, 0x0000, 0x0000 }, /* R346 */
-       { 0x0000, 0x0000, 0x0000 }, /* R347 */
-       { 0x0000, 0x0000, 0x0000 }, /* R348 */
-       { 0x0000, 0x0000, 0x0000 }, /* R349 */
-       { 0x0000, 0x0000, 0x0000 }, /* R350 */
-       { 0x0000, 0x0000, 0x0000 }, /* R351 */
-       { 0x0000, 0x0000, 0x0000 }, /* R352 */
-       { 0x0000, 0x0000, 0x0000 }, /* R353 */
-       { 0x0000, 0x0000, 0x0000 }, /* R354 */
-       { 0x0000, 0x0000, 0x0000 }, /* R355 */
-       { 0x0000, 0x0000, 0x0000 }, /* R356 */
-       { 0x0000, 0x0000, 0x0000 }, /* R357 */
-       { 0x0000, 0x0000, 0x0000 }, /* R358 */
-       { 0x0000, 0x0000, 0x0000 }, /* R359 */
-       { 0x0000, 0x0000, 0x0000 }, /* R360 */
-       { 0x0000, 0x0000, 0x0000 }, /* R361 */
-       { 0x0000, 0x0000, 0x0000 }, /* R362 */
-       { 0x0000, 0x0000, 0x0000 }, /* R363 */
-       { 0x0000, 0x0000, 0x0000 }, /* R364 */
-       { 0x0000, 0x0000, 0x0000 }, /* R365 */
-       { 0x0000, 0x0000, 0x0000 }, /* R366 */
-       { 0x0000, 0x0000, 0x0000 }, /* R367 */
-       { 0x0000, 0x0000, 0x0000 }, /* R368 */
-       { 0x0000, 0x0000, 0x0000 }, /* R369 */
-       { 0x0000, 0x0000, 0x0000 }, /* R370 */
-       { 0x0000, 0x0000, 0x0000 }, /* R371 */
-       { 0x0000, 0x0000, 0x0000 }, /* R372 */
-       { 0x0000, 0x0000, 0x0000 }, /* R373 */
-       { 0x0000, 0x0000, 0x0000 }, /* R374 */
-       { 0x0000, 0x0000, 0x0000 }, /* R375 */
-       { 0x0000, 0x0000, 0x0000 }, /* R376 */
-       { 0x0000, 0x0000, 0x0000 }, /* R377 */
-       { 0x0000, 0x0000, 0x0000 }, /* R378 */
-       { 0x0000, 0x0000, 0x0000 }, /* R379 */
-       { 0x0000, 0x0000, 0x0000 }, /* R380 */
-       { 0x0000, 0x0000, 0x0000 }, /* R381 */
-       { 0x0000, 0x0000, 0x0000 }, /* R382 */
-       { 0x0000, 0x0000, 0x0000 }, /* R383 */
-       { 0x0000, 0x0000, 0x0000 }, /* R384 */
-       { 0x0000, 0x0000, 0x0000 }, /* R385 */
-       { 0x0000, 0x0000, 0x0000 }, /* R386 */
-       { 0x0000, 0x0000, 0x0000 }, /* R387 */
-       { 0x0000, 0x0000, 0x0000 }, /* R388 */
-       { 0x0000, 0x0000, 0x0000 }, /* R389 */
-       { 0x0000, 0x0000, 0x0000 }, /* R390 */
-       { 0x0000, 0x0000, 0x0000 }, /* R391 */
-       { 0x0000, 0x0000, 0x0000 }, /* R392 */
-       { 0x0000, 0x0000, 0x0000 }, /* R393 */
-       { 0x0000, 0x0000, 0x0000 }, /* R394 */
-       { 0x0000, 0x0000, 0x0000 }, /* R395 */
-       { 0x0000, 0x0000, 0x0000 }, /* R396 */
-       { 0x0000, 0x0000, 0x0000 }, /* R397 */
-       { 0x0000, 0x0000, 0x0000 }, /* R398 */
-       { 0x0000, 0x0000, 0x0000 }, /* R399 */
-       { 0x0000, 0x0000, 0x0000 }, /* R400 */
-       { 0x0000, 0x0000, 0x0000 }, /* R401 */
-       { 0x0000, 0x0000, 0x0000 }, /* R402 */
-       { 0x0000, 0x0000, 0x0000 }, /* R403 */
-       { 0x0000, 0x0000, 0x0000 }, /* R404 */
-       { 0x0000, 0x0000, 0x0000 }, /* R405 */
-       { 0x0000, 0x0000, 0x0000 }, /* R406 */
-       { 0x0000, 0x0000, 0x0000 }, /* R407 */
-       { 0x0000, 0x0000, 0x0000 }, /* R408 */
-       { 0x0000, 0x0000, 0x0000 }, /* R409 */
-       { 0x0000, 0x0000, 0x0000 }, /* R410 */
-       { 0x0000, 0x0000, 0x0000 }, /* R411 */
-       { 0x0000, 0x0000, 0x0000 }, /* R412 */
-       { 0x0000, 0x0000, 0x0000 }, /* R413 */
-       { 0x0000, 0x0000, 0x0000 }, /* R414 */
-       { 0x0000, 0x0000, 0x0000 }, /* R415 */
-       { 0x0000, 0x0000, 0x0000 }, /* R416 */
-       { 0x0000, 0x0000, 0x0000 }, /* R417 */
-       { 0x0000, 0x0000, 0x0000 }, /* R418 */
-       { 0x0000, 0x0000, 0x0000 }, /* R419 */
-       { 0x0000, 0x0000, 0x0000 }, /* R420 */
-       { 0x0000, 0x0000, 0x0000 }, /* R421 */
-       { 0x0000, 0x0000, 0x0000 }, /* R422 */
-       { 0x0000, 0x0000, 0x0000 }, /* R423 */
-       { 0x0000, 0x0000, 0x0000 }, /* R424 */
-       { 0x0000, 0x0000, 0x0000 }, /* R425 */
-       { 0x0000, 0x0000, 0x0000 }, /* R426 */
-       { 0x0000, 0x0000, 0x0000 }, /* R427 */
-       { 0x0000, 0x0000, 0x0000 }, /* R428 */
-       { 0x0000, 0x0000, 0x0000 }, /* R429 */
-       { 0x0000, 0x0000, 0x0000 }, /* R430 */
-       { 0x0000, 0x0000, 0x0000 }, /* R431 */
-       { 0x0000, 0x0000, 0x0000 }, /* R432 */
-       { 0x0000, 0x0000, 0x0000 }, /* R433 */
-       { 0x0000, 0x0000, 0x0000 }, /* R434 */
-       { 0x0000, 0x0000, 0x0000 }, /* R435 */
-       { 0x0000, 0x0000, 0x0000 }, /* R436 */
-       { 0x0000, 0x0000, 0x0000 }, /* R437 */
-       { 0x0000, 0x0000, 0x0000 }, /* R438 */
-       { 0x0000, 0x0000, 0x0000 }, /* R439 */
-       { 0x0000, 0x0000, 0x0000 }, /* R440 */
-       { 0x0000, 0x0000, 0x0000 }, /* R441 */
-       { 0x0000, 0x0000, 0x0000 }, /* R442 */
-       { 0x0000, 0x0000, 0x0000 }, /* R443 */
-       { 0x0000, 0x0000, 0x0000 }, /* R444 */
-       { 0x0000, 0x0000, 0x0000 }, /* R445 */
-       { 0x0000, 0x0000, 0x0000 }, /* R446 */
-       { 0x0000, 0x0000, 0x0000 }, /* R447 */
-       { 0x0000, 0x0000, 0x0000 }, /* R448 */
-       { 0x0000, 0x0000, 0x0000 }, /* R449 */
-       { 0x0000, 0x0000, 0x0000 }, /* R450 */
-       { 0x0000, 0x0000, 0x0000 }, /* R451 */
-       { 0x0000, 0x0000, 0x0000 }, /* R452 */
-       { 0x0000, 0x0000, 0x0000 }, /* R453 */
-       { 0x0000, 0x0000, 0x0000 }, /* R454 */
-       { 0x0000, 0x0000, 0x0000 }, /* R455 */
-       { 0x0000, 0x0000, 0x0000 }, /* R456 */
-       { 0x0000, 0x0000, 0x0000 }, /* R457 */
-       { 0x0000, 0x0000, 0x0000 }, /* R458 */
-       { 0x0000, 0x0000, 0x0000 }, /* R459 */
-       { 0x0000, 0x0000, 0x0000 }, /* R460 */
-       { 0x0000, 0x0000, 0x0000 }, /* R461 */
-       { 0x0000, 0x0000, 0x0000 }, /* R462 */
-       { 0x0000, 0x0000, 0x0000 }, /* R463 */
-       { 0x0000, 0x0000, 0x0000 }, /* R464 */
-       { 0x0000, 0x0000, 0x0000 }, /* R465 */
-       { 0x0000, 0x0000, 0x0000 }, /* R466 */
-       { 0x0000, 0x0000, 0x0000 }, /* R467 */
-       { 0x0000, 0x0000, 0x0000 }, /* R468 */
-       { 0x0000, 0x0000, 0x0000 }, /* R469 */
-       { 0x0000, 0x0000, 0x0000 }, /* R470 */
-       { 0x0000, 0x0000, 0x0000 }, /* R471 */
-       { 0x0000, 0x0000, 0x0000 }, /* R472 */
-       { 0x0000, 0x0000, 0x0000 }, /* R473 */
-       { 0x0000, 0x0000, 0x0000 }, /* R474 */
-       { 0x0000, 0x0000, 0x0000 }, /* R475 */
-       { 0x0000, 0x0000, 0x0000 }, /* R476 */
-       { 0x0000, 0x0000, 0x0000 }, /* R477 */
-       { 0x0000, 0x0000, 0x0000 }, /* R478 */
-       { 0x0000, 0x0000, 0x0000 }, /* R479 */
-       { 0x0000, 0x0000, 0x0000 }, /* R480 */
-       { 0x0000, 0x0000, 0x0000 }, /* R481 */
-       { 0x0000, 0x0000, 0x0000 }, /* R482 */
-       { 0x0000, 0x0000, 0x0000 }, /* R483 */
-       { 0x0000, 0x0000, 0x0000 }, /* R484 */
-       { 0x0000, 0x0000, 0x0000 }, /* R485 */
-       { 0x0000, 0x0000, 0x0000 }, /* R486 */
-       { 0x0000, 0x0000, 0x0000 }, /* R487 */
-       { 0x0000, 0x0000, 0x0000 }, /* R488 */
-       { 0x0000, 0x0000, 0x0000 }, /* R489 */
-       { 0x0000, 0x0000, 0x0000 }, /* R490 */
-       { 0x0000, 0x0000, 0x0000 }, /* R491 */
-       { 0x0000, 0x0000, 0x0000 }, /* R492 */
-       { 0x0000, 0x0000, 0x0000 }, /* R493 */
-       { 0x0000, 0x0000, 0x0000 }, /* R494 */
-       { 0x0000, 0x0000, 0x0000 }, /* R495 */
-       { 0x0000, 0x0000, 0x0000 }, /* R496 */
-       { 0x0000, 0x0000, 0x0000 }, /* R497 */
-       { 0x0000, 0x0000, 0x0000 }, /* R498 */
-       { 0x0000, 0x0000, 0x0000 }, /* R499 */
-       { 0x0000, 0x0000, 0x0000 }, /* R500 */
-       { 0x0000, 0x0000, 0x0000 }, /* R501 */
-       { 0x0000, 0x0000, 0x0000 }, /* R502 */
-       { 0x0000, 0x0000, 0x0000 }, /* R503 */
-       { 0x0000, 0x0000, 0x0000 }, /* R504 */
-       { 0x0000, 0x0000, 0x0000 }, /* R505 */
-       { 0x0000, 0x0000, 0x0000 }, /* R506 */
-       { 0x0000, 0x0000, 0x0000 }, /* R507 */
-       { 0x0000, 0x0000, 0x0000 }, /* R508 */
-       { 0x0000, 0x0000, 0x0000 }, /* R509 */
-       { 0x0000, 0x0000, 0x0000 }, /* R510 */
-       { 0x0000, 0x0000, 0x0000 }, /* R511 */
-       { 0x001F, 0x001F, 0x0000 }, /* R512   - AIF1 Clocking (1) */
-       { 0x003F, 0x003F, 0x0000 }, /* R513   - AIF1 Clocking (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R514 */
-       { 0x0000, 0x0000, 0x0000 }, /* R515 */
-       { 0x001F, 0x001F, 0x0000 }, /* R516   - AIF2 Clocking (1) */
-       { 0x003F, 0x003F, 0x0000 }, /* R517   - AIF2 Clocking (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R518 */
-       { 0x0000, 0x0000, 0x0000 }, /* R519 */
-       { 0x001F, 0x001F, 0x0000 }, /* R520   - Clocking (1) */
-       { 0x0777, 0x0777, 0x0000 }, /* R521   - Clocking (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R522 */
-       { 0x0000, 0x0000, 0x0000 }, /* R523 */
-       { 0x0000, 0x0000, 0x0000 }, /* R524 */
-       { 0x0000, 0x0000, 0x0000 }, /* R525 */
-       { 0x0000, 0x0000, 0x0000 }, /* R526 */
-       { 0x0000, 0x0000, 0x0000 }, /* R527 */
-       { 0x00FF, 0x00FF, 0x0000 }, /* R528   - AIF1 Rate */
-       { 0x00FF, 0x00FF, 0x0000 }, /* R529   - AIF2 Rate */
-       { 0x000F, 0x0000, 0x0000 }, /* R530   - Rate Status */
-       { 0x0000, 0x0000, 0x0000 }, /* R531 */
-       { 0x0000, 0x0000, 0x0000 }, /* R532 */
-       { 0x0000, 0x0000, 0x0000 }, /* R533 */
-       { 0x0000, 0x0000, 0x0000 }, /* R534 */
-       { 0x0000, 0x0000, 0x0000 }, /* R535 */
-       { 0x0000, 0x0000, 0x0000 }, /* R536 */
-       { 0x0000, 0x0000, 0x0000 }, /* R537 */
-       { 0x0000, 0x0000, 0x0000 }, /* R538 */
-       { 0x0000, 0x0000, 0x0000 }, /* R539 */
-       { 0x0000, 0x0000, 0x0000 }, /* R540 */
-       { 0x0000, 0x0000, 0x0000 }, /* R541 */
-       { 0x0000, 0x0000, 0x0000 }, /* R542 */
-       { 0x0000, 0x0000, 0x0000 }, /* R543 */
-       { 0x0007, 0x0007, 0x0000 }, /* R544   - FLL1 Control (1) */
-       { 0x3F77, 0x3F77, 0x0000 }, /* R545   - FLL1 Control (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R546   - FLL1 Control (3) */
-       { 0x7FEF, 0x7FEF, 0x0000 }, /* R547   - FLL1 Control (4) */
-       { 0x1FDB, 0x1FDB, 0x0000 }, /* R548   - FLL1 Control (5) */
-       { 0x0000, 0x0000, 0x0000 }, /* R549 */
-       { 0x0000, 0x0000, 0x0000 }, /* R550 */
-       { 0x0000, 0x0000, 0x0000 }, /* R551 */
-       { 0x0000, 0x0000, 0x0000 }, /* R552 */
-       { 0x0000, 0x0000, 0x0000 }, /* R553 */
-       { 0x0000, 0x0000, 0x0000 }, /* R554 */
-       { 0x0000, 0x0000, 0x0000 }, /* R555 */
-       { 0x0000, 0x0000, 0x0000 }, /* R556 */
-       { 0x0000, 0x0000, 0x0000 }, /* R557 */
-       { 0x0000, 0x0000, 0x0000 }, /* R558 */
-       { 0x0000, 0x0000, 0x0000 }, /* R559 */
-       { 0x0000, 0x0000, 0x0000 }, /* R560 */
-       { 0x0000, 0x0000, 0x0000 }, /* R561 */
-       { 0x0000, 0x0000, 0x0000 }, /* R562 */
-       { 0x0000, 0x0000, 0x0000 }, /* R563 */
-       { 0x0000, 0x0000, 0x0000 }, /* R564 */
-       { 0x0000, 0x0000, 0x0000 }, /* R565 */
-       { 0x0000, 0x0000, 0x0000 }, /* R566 */
-       { 0x0000, 0x0000, 0x0000 }, /* R567 */
-       { 0x0000, 0x0000, 0x0000 }, /* R568 */
-       { 0x0000, 0x0000, 0x0000 }, /* R569 */
-       { 0x0000, 0x0000, 0x0000 }, /* R570 */
-       { 0x0000, 0x0000, 0x0000 }, /* R571 */
-       { 0x0000, 0x0000, 0x0000 }, /* R572 */
-       { 0x0000, 0x0000, 0x0000 }, /* R573 */
-       { 0x0000, 0x0000, 0x0000 }, /* R574 */
-       { 0x0000, 0x0000, 0x0000 }, /* R575 */
-       { 0x0007, 0x0007, 0x0000 }, /* R576   - FLL2 Control (1) */
-       { 0x3F77, 0x3F77, 0x0000 }, /* R577   - FLL2 Control (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R578   - FLL2 Control (3) */
-       { 0x7FEF, 0x7FEF, 0x0000 }, /* R579   - FLL2 Control (4) */
-       { 0x1FDB, 0x1FDB, 0x0000 }, /* R580   - FLL2 Control (5) */
-       { 0x0000, 0x0000, 0x0000 }, /* R581 */
-       { 0x0000, 0x0000, 0x0000 }, /* R582 */
-       { 0x0000, 0x0000, 0x0000 }, /* R583 */
-       { 0x0000, 0x0000, 0x0000 }, /* R584 */
-       { 0x0000, 0x0000, 0x0000 }, /* R585 */
-       { 0x0000, 0x0000, 0x0000 }, /* R586 */
-       { 0x0000, 0x0000, 0x0000 }, /* R587 */
-       { 0x0000, 0x0000, 0x0000 }, /* R588 */
-       { 0x0000, 0x0000, 0x0000 }, /* R589 */
-       { 0x0000, 0x0000, 0x0000 }, /* R590 */
-       { 0x0000, 0x0000, 0x0000 }, /* R591 */
-       { 0x0000, 0x0000, 0x0000 }, /* R592 */
-       { 0x0000, 0x0000, 0x0000 }, /* R593 */
-       { 0x0000, 0x0000, 0x0000 }, /* R594 */
-       { 0x0000, 0x0000, 0x0000 }, /* R595 */
-       { 0x0000, 0x0000, 0x0000 }, /* R596 */
-       { 0x0000, 0x0000, 0x0000 }, /* R597 */
-       { 0x0000, 0x0000, 0x0000 }, /* R598 */
-       { 0x0000, 0x0000, 0x0000 }, /* R599 */
-       { 0x0000, 0x0000, 0x0000 }, /* R600 */
-       { 0x0000, 0x0000, 0x0000 }, /* R601 */
-       { 0x0000, 0x0000, 0x0000 }, /* R602 */
-       { 0x0000, 0x0000, 0x0000 }, /* R603 */
-       { 0x0000, 0x0000, 0x0000 }, /* R604 */
-       { 0x0000, 0x0000, 0x0000 }, /* R605 */
-       { 0x0000, 0x0000, 0x0000 }, /* R606 */
-       { 0x0000, 0x0000, 0x0000 }, /* R607 */
-       { 0x0000, 0x0000, 0x0000 }, /* R608 */
-       { 0x0000, 0x0000, 0x0000 }, /* R609 */
-       { 0x0000, 0x0000, 0x0000 }, /* R610 */
-       { 0x0000, 0x0000, 0x0000 }, /* R611 */
-       { 0x0000, 0x0000, 0x0000 }, /* R612 */
-       { 0x0000, 0x0000, 0x0000 }, /* R613 */
-       { 0x0000, 0x0000, 0x0000 }, /* R614 */
-       { 0x0000, 0x0000, 0x0000 }, /* R615 */
-       { 0x0000, 0x0000, 0x0000 }, /* R616 */
-       { 0x0000, 0x0000, 0x0000 }, /* R617 */
-       { 0x0000, 0x0000, 0x0000 }, /* R618 */
-       { 0x0000, 0x0000, 0x0000 }, /* R619 */
-       { 0x0000, 0x0000, 0x0000 }, /* R620 */
-       { 0x0000, 0x0000, 0x0000 }, /* R621 */
-       { 0x0000, 0x0000, 0x0000 }, /* R622 */
-       { 0x0000, 0x0000, 0x0000 }, /* R623 */
-       { 0x0000, 0x0000, 0x0000 }, /* R624 */
-       { 0x0000, 0x0000, 0x0000 }, /* R625 */
-       { 0x0000, 0x0000, 0x0000 }, /* R626 */
-       { 0x0000, 0x0000, 0x0000 }, /* R627 */
-       { 0x0000, 0x0000, 0x0000 }, /* R628 */
-       { 0x0000, 0x0000, 0x0000 }, /* R629 */
-       { 0x0000, 0x0000, 0x0000 }, /* R630 */
-       { 0x0000, 0x0000, 0x0000 }, /* R631 */
-       { 0x0000, 0x0000, 0x0000 }, /* R632 */
-       { 0x0000, 0x0000, 0x0000 }, /* R633 */
-       { 0x0000, 0x0000, 0x0000 }, /* R634 */
-       { 0x0000, 0x0000, 0x0000 }, /* R635 */
-       { 0x0000, 0x0000, 0x0000 }, /* R636 */
-       { 0x0000, 0x0000, 0x0000 }, /* R637 */
-       { 0x0000, 0x0000, 0x0000 }, /* R638 */
-       { 0x0000, 0x0000, 0x0000 }, /* R639 */
-       { 0x0000, 0x0000, 0x0000 }, /* R640 */
-       { 0x0000, 0x0000, 0x0000 }, /* R641 */
-       { 0x0000, 0x0000, 0x0000 }, /* R642 */
-       { 0x0000, 0x0000, 0x0000 }, /* R643 */
-       { 0x0000, 0x0000, 0x0000 }, /* R644 */
-       { 0x0000, 0x0000, 0x0000 }, /* R645 */
-       { 0x0000, 0x0000, 0x0000 }, /* R646 */
-       { 0x0000, 0x0000, 0x0000 }, /* R647 */
-       { 0x0000, 0x0000, 0x0000 }, /* R648 */
-       { 0x0000, 0x0000, 0x0000 }, /* R649 */
-       { 0x0000, 0x0000, 0x0000 }, /* R650 */
-       { 0x0000, 0x0000, 0x0000 }, /* R651 */
-       { 0x0000, 0x0000, 0x0000 }, /* R652 */
-       { 0x0000, 0x0000, 0x0000 }, /* R653 */
-       { 0x0000, 0x0000, 0x0000 }, /* R654 */
-       { 0x0000, 0x0000, 0x0000 }, /* R655 */
-       { 0x0000, 0x0000, 0x0000 }, /* R656 */
-       { 0x0000, 0x0000, 0x0000 }, /* R657 */
-       { 0x0000, 0x0000, 0x0000 }, /* R658 */
-       { 0x0000, 0x0000, 0x0000 }, /* R659 */
-       { 0x0000, 0x0000, 0x0000 }, /* R660 */
-       { 0x0000, 0x0000, 0x0000 }, /* R661 */
-       { 0x0000, 0x0000, 0x0000 }, /* R662 */
-       { 0x0000, 0x0000, 0x0000 }, /* R663 */
-       { 0x0000, 0x0000, 0x0000 }, /* R664 */
-       { 0x0000, 0x0000, 0x0000 }, /* R665 */
-       { 0x0000, 0x0000, 0x0000 }, /* R666 */
-       { 0x0000, 0x0000, 0x0000 }, /* R667 */
-       { 0x0000, 0x0000, 0x0000 }, /* R668 */
-       { 0x0000, 0x0000, 0x0000 }, /* R669 */
-       { 0x0000, 0x0000, 0x0000 }, /* R670 */
-       { 0x0000, 0x0000, 0x0000 }, /* R671 */
-       { 0x0000, 0x0000, 0x0000 }, /* R672 */
-       { 0x0000, 0x0000, 0x0000 }, /* R673 */
-       { 0x0000, 0x0000, 0x0000 }, /* R674 */
-       { 0x0000, 0x0000, 0x0000 }, /* R675 */
-       { 0x0000, 0x0000, 0x0000 }, /* R676 */
-       { 0x0000, 0x0000, 0x0000 }, /* R677 */
-       { 0x0000, 0x0000, 0x0000 }, /* R678 */
-       { 0x0000, 0x0000, 0x0000 }, /* R679 */
-       { 0x0000, 0x0000, 0x0000 }, /* R680 */
-       { 0x0000, 0x0000, 0x0000 }, /* R681 */
-       { 0x0000, 0x0000, 0x0000 }, /* R682 */
-       { 0x0000, 0x0000, 0x0000 }, /* R683 */
-       { 0x0000, 0x0000, 0x0000 }, /* R684 */
-       { 0x0000, 0x0000, 0x0000 }, /* R685 */
-       { 0x0000, 0x0000, 0x0000 }, /* R686 */
-       { 0x0000, 0x0000, 0x0000 }, /* R687 */
-       { 0x0000, 0x0000, 0x0000 }, /* R688 */
-       { 0x0000, 0x0000, 0x0000 }, /* R689 */
-       { 0x0000, 0x0000, 0x0000 }, /* R690 */
-       { 0x0000, 0x0000, 0x0000 }, /* R691 */
-       { 0x0000, 0x0000, 0x0000 }, /* R692 */
-       { 0x0000, 0x0000, 0x0000 }, /* R693 */
-       { 0x0000, 0x0000, 0x0000 }, /* R694 */
-       { 0x0000, 0x0000, 0x0000 }, /* R695 */
-       { 0x0000, 0x0000, 0x0000 }, /* R696 */
-       { 0x0000, 0x0000, 0x0000 }, /* R697 */
-       { 0x0000, 0x0000, 0x0000 }, /* R698 */
-       { 0x0000, 0x0000, 0x0000 }, /* R699 */
-       { 0x0000, 0x0000, 0x0000 }, /* R700 */
-       { 0x0000, 0x0000, 0x0000 }, /* R701 */
-       { 0x0000, 0x0000, 0x0000 }, /* R702 */
-       { 0x0000, 0x0000, 0x0000 }, /* R703 */
-       { 0x0000, 0x0000, 0x0000 }, /* R704 */
-       { 0x0000, 0x0000, 0x0000 }, /* R705 */
-       { 0x0000, 0x0000, 0x0000 }, /* R706 */
-       { 0x0000, 0x0000, 0x0000 }, /* R707 */
-       { 0x0000, 0x0000, 0x0000 }, /* R708 */
-       { 0x0000, 0x0000, 0x0000 }, /* R709 */
-       { 0x0000, 0x0000, 0x0000 }, /* R710 */
-       { 0x0000, 0x0000, 0x0000 }, /* R711 */
-       { 0x0000, 0x0000, 0x0000 }, /* R712 */
-       { 0x0000, 0x0000, 0x0000 }, /* R713 */
-       { 0x0000, 0x0000, 0x0000 }, /* R714 */
-       { 0x0000, 0x0000, 0x0000 }, /* R715 */
-       { 0x0000, 0x0000, 0x0000 }, /* R716 */
-       { 0x0000, 0x0000, 0x0000 }, /* R717 */
-       { 0x0000, 0x0000, 0x0000 }, /* R718 */
-       { 0x0000, 0x0000, 0x0000 }, /* R719 */
-       { 0x0000, 0x0000, 0x0000 }, /* R720 */
-       { 0x0000, 0x0000, 0x0000 }, /* R721 */
-       { 0x0000, 0x0000, 0x0000 }, /* R722 */
-       { 0x0000, 0x0000, 0x0000 }, /* R723 */
-       { 0x0000, 0x0000, 0x0000 }, /* R724 */
-       { 0x0000, 0x0000, 0x0000 }, /* R725 */
-       { 0x0000, 0x0000, 0x0000 }, /* R726 */
-       { 0x0000, 0x0000, 0x0000 }, /* R727 */
-       { 0x0000, 0x0000, 0x0000 }, /* R728 */
-       { 0x0000, 0x0000, 0x0000 }, /* R729 */
-       { 0x0000, 0x0000, 0x0000 }, /* R730 */
-       { 0x0000, 0x0000, 0x0000 }, /* R731 */
-       { 0x0000, 0x0000, 0x0000 }, /* R732 */
-       { 0x0000, 0x0000, 0x0000 }, /* R733 */
-       { 0x0000, 0x0000, 0x0000 }, /* R734 */
-       { 0x0000, 0x0000, 0x0000 }, /* R735 */
-       { 0x0000, 0x0000, 0x0000 }, /* R736 */
-       { 0x0000, 0x0000, 0x0000 }, /* R737 */
-       { 0x0000, 0x0000, 0x0000 }, /* R738 */
-       { 0x0000, 0x0000, 0x0000 }, /* R739 */
-       { 0x0000, 0x0000, 0x0000 }, /* R740 */
-       { 0x0000, 0x0000, 0x0000 }, /* R741 */
-       { 0x0000, 0x0000, 0x0000 }, /* R742 */
-       { 0x0000, 0x0000, 0x0000 }, /* R743 */
-       { 0x0000, 0x0000, 0x0000 }, /* R744 */
-       { 0x0000, 0x0000, 0x0000 }, /* R745 */
-       { 0x0000, 0x0000, 0x0000 }, /* R746 */
-       { 0x0000, 0x0000, 0x0000 }, /* R747 */
-       { 0x0000, 0x0000, 0x0000 }, /* R748 */
-       { 0x0000, 0x0000, 0x0000 }, /* R749 */
-       { 0x0000, 0x0000, 0x0000 }, /* R750 */
-       { 0x0000, 0x0000, 0x0000 }, /* R751 */
-       { 0x0000, 0x0000, 0x0000 }, /* R752 */
-       { 0x0000, 0x0000, 0x0000 }, /* R753 */
-       { 0x0000, 0x0000, 0x0000 }, /* R754 */
-       { 0x0000, 0x0000, 0x0000 }, /* R755 */
-       { 0x0000, 0x0000, 0x0000 }, /* R756 */
-       { 0x0000, 0x0000, 0x0000 }, /* R757 */
-       { 0x0000, 0x0000, 0x0000 }, /* R758 */
-       { 0x0000, 0x0000, 0x0000 }, /* R759 */
-       { 0x0000, 0x0000, 0x0000 }, /* R760 */
-       { 0x0000, 0x0000, 0x0000 }, /* R761 */
-       { 0x0000, 0x0000, 0x0000 }, /* R762 */
-       { 0x0000, 0x0000, 0x0000 }, /* R763 */
-       { 0x0000, 0x0000, 0x0000 }, /* R764 */
-       { 0x0000, 0x0000, 0x0000 }, /* R765 */
-       { 0x0000, 0x0000, 0x0000 }, /* R766 */
-       { 0x0000, 0x0000, 0x0000 }, /* R767 */
-       { 0xE1F8, 0xE1F8, 0x0000 }, /* R768   - AIF1 Control (1) */
-       { 0xCD1F, 0xCD1F, 0x0000 }, /* R769   - AIF1 Control (2) */
-       { 0xF000, 0xF000, 0x0000 }, /* R770   - AIF1 Master/Slave */
-       { 0x01F0, 0x01F0, 0x0000 }, /* R771   - AIF1 BCLK */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R772   - AIF1ADC LRCLK */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R773   - AIF1DAC LRCLK */
-       { 0x0003, 0x0003, 0x0000 }, /* R774   - AIF1DAC Data */
-       { 0x0003, 0x0003, 0x0000 }, /* R775   - AIF1ADC Data */
-       { 0x0000, 0x0000, 0x0000 }, /* R776 */
-       { 0x0000, 0x0000, 0x0000 }, /* R777 */
-       { 0x0000, 0x0000, 0x0000 }, /* R778 */
-       { 0x0000, 0x0000, 0x0000 }, /* R779 */
-       { 0x0000, 0x0000, 0x0000 }, /* R780 */
-       { 0x0000, 0x0000, 0x0000 }, /* R781 */
-       { 0x0000, 0x0000, 0x0000 }, /* R782 */
-       { 0x0000, 0x0000, 0x0000 }, /* R783 */
-       { 0xF1F8, 0xF1F8, 0x0000 }, /* R784   - AIF2 Control (1) */
-       { 0xFD1F, 0xFD1F, 0x0000 }, /* R785   - AIF2 Control (2) */
-       { 0xF000, 0xF000, 0x0000 }, /* R786   - AIF2 Master/Slave */
-       { 0x01F0, 0x01F0, 0x0000 }, /* R787   - AIF2 BCLK */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R788   - AIF2ADC LRCLK */
-       { 0x0FFF, 0x0FFF, 0x0000 }, /* R789   - AIF2DAC LRCLK */
-       { 0x0003, 0x0003, 0x0000 }, /* R790   - AIF2DAC Data */
-       { 0x0003, 0x0003, 0x0000 }, /* R791   - AIF2ADC Data */
-       { 0x0000, 0x0000, 0x0000 }, /* R792 */
-       { 0x0000, 0x0000, 0x0000 }, /* R793 */
-       { 0x0000, 0x0000, 0x0000 }, /* R794 */
-       { 0x0000, 0x0000, 0x0000 }, /* R795 */
-       { 0x0000, 0x0000, 0x0000 }, /* R796 */
-       { 0x0000, 0x0000, 0x0000 }, /* R797 */
-       { 0x0000, 0x0000, 0x0000 }, /* R798 */
-       { 0x0000, 0x0000, 0x0000 }, /* R799 */
-       { 0x0000, 0x0000, 0x0000 }, /* R800 */
-       { 0x0000, 0x0000, 0x0000 }, /* R801 */
-       { 0x0000, 0x0000, 0x0000 }, /* R802 */
-       { 0x0000, 0x0000, 0x0000 }, /* R803 */
-       { 0x0000, 0x0000, 0x0000 }, /* R804 */
-       { 0x0000, 0x0000, 0x0000 }, /* R805 */
-       { 0x0000, 0x0000, 0x0000 }, /* R806 */
-       { 0x0000, 0x0000, 0x0000 }, /* R807 */
-       { 0x0000, 0x0000, 0x0000 }, /* R808 */
-       { 0x0000, 0x0000, 0x0000 }, /* R809 */
-       { 0x0000, 0x0000, 0x0000 }, /* R810 */
-       { 0x0000, 0x0000, 0x0000 }, /* R811 */
-       { 0x0000, 0x0000, 0x0000 }, /* R812 */
-       { 0x0000, 0x0000, 0x0000 }, /* R813 */
-       { 0x0000, 0x0000, 0x0000 }, /* R814 */
-       { 0x0000, 0x0000, 0x0000 }, /* R815 */
-       { 0x0000, 0x0000, 0x0000 }, /* R816 */
-       { 0x0000, 0x0000, 0x0000 }, /* R817 */
-       { 0x0000, 0x0000, 0x0000 }, /* R818 */
-       { 0x0000, 0x0000, 0x0000 }, /* R819 */
-       { 0x0000, 0x0000, 0x0000 }, /* R820 */
-       { 0x0000, 0x0000, 0x0000 }, /* R821 */
-       { 0x0000, 0x0000, 0x0000 }, /* R822 */
-       { 0x0000, 0x0000, 0x0000 }, /* R823 */
-       { 0x0000, 0x0000, 0x0000 }, /* R824 */
-       { 0x0000, 0x0000, 0x0000 }, /* R825 */
-       { 0x0000, 0x0000, 0x0000 }, /* R826 */
-       { 0x0000, 0x0000, 0x0000 }, /* R827 */
-       { 0x0000, 0x0000, 0x0000 }, /* R828 */
-       { 0x0000, 0x0000, 0x0000 }, /* R829 */
-       { 0x0000, 0x0000, 0x0000 }, /* R830 */
-       { 0x0000, 0x0000, 0x0000 }, /* R831 */
-       { 0x0000, 0x0000, 0x0000 }, /* R832 */
-       { 0x0000, 0x0000, 0x0000 }, /* R833 */
-       { 0x0000, 0x0000, 0x0000 }, /* R834 */
-       { 0x0000, 0x0000, 0x0000 }, /* R835 */
-       { 0x0000, 0x0000, 0x0000 }, /* R836 */
-       { 0x0000, 0x0000, 0x0000 }, /* R837 */
-       { 0x0000, 0x0000, 0x0000 }, /* R838 */
-       { 0x0000, 0x0000, 0x0000 }, /* R839 */
-       { 0x0000, 0x0000, 0x0000 }, /* R840 */
-       { 0x0000, 0x0000, 0x0000 }, /* R841 */
-       { 0x0000, 0x0000, 0x0000 }, /* R842 */
-       { 0x0000, 0x0000, 0x0000 }, /* R843 */
-       { 0x0000, 0x0000, 0x0000 }, /* R844 */
-       { 0x0000, 0x0000, 0x0000 }, /* R845 */
-       { 0x0000, 0x0000, 0x0000 }, /* R846 */
-       { 0x0000, 0x0000, 0x0000 }, /* R847 */
-       { 0x0000, 0x0000, 0x0000 }, /* R848 */
-       { 0x0000, 0x0000, 0x0000 }, /* R849 */
-       { 0x0000, 0x0000, 0x0000 }, /* R850 */
-       { 0x0000, 0x0000, 0x0000 }, /* R851 */
-       { 0x0000, 0x0000, 0x0000 }, /* R852 */
-       { 0x0000, 0x0000, 0x0000 }, /* R853 */
-       { 0x0000, 0x0000, 0x0000 }, /* R854 */
-       { 0x0000, 0x0000, 0x0000 }, /* R855 */
-       { 0x0000, 0x0000, 0x0000 }, /* R856 */
-       { 0x0000, 0x0000, 0x0000 }, /* R857 */
-       { 0x0000, 0x0000, 0x0000 }, /* R858 */
-       { 0x0000, 0x0000, 0x0000 }, /* R859 */
-       { 0x0000, 0x0000, 0x0000 }, /* R860 */
-       { 0x0000, 0x0000, 0x0000 }, /* R861 */
-       { 0x0000, 0x0000, 0x0000 }, /* R862 */
-       { 0x0000, 0x0000, 0x0000 }, /* R863 */
-       { 0x0000, 0x0000, 0x0000 }, /* R864 */
-       { 0x0000, 0x0000, 0x0000 }, /* R865 */
-       { 0x0000, 0x0000, 0x0000 }, /* R866 */
-       { 0x0000, 0x0000, 0x0000 }, /* R867 */
-       { 0x0000, 0x0000, 0x0000 }, /* R868 */
-       { 0x0000, 0x0000, 0x0000 }, /* R869 */
-       { 0x0000, 0x0000, 0x0000 }, /* R870 */
-       { 0x0000, 0x0000, 0x0000 }, /* R871 */
-       { 0x0000, 0x0000, 0x0000 }, /* R872 */
-       { 0x0000, 0x0000, 0x0000 }, /* R873 */
-       { 0x0000, 0x0000, 0x0000 }, /* R874 */
-       { 0x0000, 0x0000, 0x0000 }, /* R875 */
-       { 0x0000, 0x0000, 0x0000 }, /* R876 */
-       { 0x0000, 0x0000, 0x0000 }, /* R877 */
-       { 0x0000, 0x0000, 0x0000 }, /* R878 */
-       { 0x0000, 0x0000, 0x0000 }, /* R879 */
-       { 0x0000, 0x0000, 0x0000 }, /* R880 */
-       { 0x0000, 0x0000, 0x0000 }, /* R881 */
-       { 0x0000, 0x0000, 0x0000 }, /* R882 */
-       { 0x0000, 0x0000, 0x0000 }, /* R883 */
-       { 0x0000, 0x0000, 0x0000 }, /* R884 */
-       { 0x0000, 0x0000, 0x0000 }, /* R885 */
-       { 0x0000, 0x0000, 0x0000 }, /* R886 */
-       { 0x0000, 0x0000, 0x0000 }, /* R887 */
-       { 0x0000, 0x0000, 0x0000 }, /* R888 */
-       { 0x0000, 0x0000, 0x0000 }, /* R889 */
-       { 0x0000, 0x0000, 0x0000 }, /* R890 */
-       { 0x0000, 0x0000, 0x0000 }, /* R891 */
-       { 0x0000, 0x0000, 0x0000 }, /* R892 */
-       { 0x0000, 0x0000, 0x0000 }, /* R893 */
-       { 0x0000, 0x0000, 0x0000 }, /* R894 */
-       { 0x0000, 0x0000, 0x0000 }, /* R895 */
-       { 0x0000, 0x0000, 0x0000 }, /* R896 */
-       { 0x0000, 0x0000, 0x0000 }, /* R897 */
-       { 0x0000, 0x0000, 0x0000 }, /* R898 */
-       { 0x0000, 0x0000, 0x0000 }, /* R899 */
-       { 0x0000, 0x0000, 0x0000 }, /* R900 */
-       { 0x0000, 0x0000, 0x0000 }, /* R901 */
-       { 0x0000, 0x0000, 0x0000 }, /* R902 */
-       { 0x0000, 0x0000, 0x0000 }, /* R903 */
-       { 0x0000, 0x0000, 0x0000 }, /* R904 */
-       { 0x0000, 0x0000, 0x0000 }, /* R905 */
-       { 0x0000, 0x0000, 0x0000 }, /* R906 */
-       { 0x0000, 0x0000, 0x0000 }, /* R907 */
-       { 0x0000, 0x0000, 0x0000 }, /* R908 */
-       { 0x0000, 0x0000, 0x0000 }, /* R909 */
-       { 0x0000, 0x0000, 0x0000 }, /* R910 */
-       { 0x0000, 0x0000, 0x0000 }, /* R911 */
-       { 0x0000, 0x0000, 0x0000 }, /* R912 */
-       { 0x0000, 0x0000, 0x0000 }, /* R913 */
-       { 0x0000, 0x0000, 0x0000 }, /* R914 */
-       { 0x0000, 0x0000, 0x0000 }, /* R915 */
-       { 0x0000, 0x0000, 0x0000 }, /* R916 */
-       { 0x0000, 0x0000, 0x0000 }, /* R917 */
-       { 0x0000, 0x0000, 0x0000 }, /* R918 */
-       { 0x0000, 0x0000, 0x0000 }, /* R919 */
-       { 0x0000, 0x0000, 0x0000 }, /* R920 */
-       { 0x0000, 0x0000, 0x0000 }, /* R921 */
-       { 0x0000, 0x0000, 0x0000 }, /* R922 */
-       { 0x0000, 0x0000, 0x0000 }, /* R923 */
-       { 0x0000, 0x0000, 0x0000 }, /* R924 */
-       { 0x0000, 0x0000, 0x0000 }, /* R925 */
-       { 0x0000, 0x0000, 0x0000 }, /* R926 */
-       { 0x0000, 0x0000, 0x0000 }, /* R927 */
-       { 0x0000, 0x0000, 0x0000 }, /* R928 */
-       { 0x0000, 0x0000, 0x0000 }, /* R929 */
-       { 0x0000, 0x0000, 0x0000 }, /* R930 */
-       { 0x0000, 0x0000, 0x0000 }, /* R931 */
-       { 0x0000, 0x0000, 0x0000 }, /* R932 */
-       { 0x0000, 0x0000, 0x0000 }, /* R933 */
-       { 0x0000, 0x0000, 0x0000 }, /* R934 */
-       { 0x0000, 0x0000, 0x0000 }, /* R935 */
-       { 0x0000, 0x0000, 0x0000 }, /* R936 */
-       { 0x0000, 0x0000, 0x0000 }, /* R937 */
-       { 0x0000, 0x0000, 0x0000 }, /* R938 */
-       { 0x0000, 0x0000, 0x0000 }, /* R939 */
-       { 0x0000, 0x0000, 0x0000 }, /* R940 */
-       { 0x0000, 0x0000, 0x0000 }, /* R941 */
-       { 0x0000, 0x0000, 0x0000 }, /* R942 */
-       { 0x0000, 0x0000, 0x0000 }, /* R943 */
-       { 0x0000, 0x0000, 0x0000 }, /* R944 */
-       { 0x0000, 0x0000, 0x0000 }, /* R945 */
-       { 0x0000, 0x0000, 0x0000 }, /* R946 */
-       { 0x0000, 0x0000, 0x0000 }, /* R947 */
-       { 0x0000, 0x0000, 0x0000 }, /* R948 */
-       { 0x0000, 0x0000, 0x0000 }, /* R949 */
-       { 0x0000, 0x0000, 0x0000 }, /* R950 */
-       { 0x0000, 0x0000, 0x0000 }, /* R951 */
-       { 0x0000, 0x0000, 0x0000 }, /* R952 */
-       { 0x0000, 0x0000, 0x0000 }, /* R953 */
-       { 0x0000, 0x0000, 0x0000 }, /* R954 */
-       { 0x0000, 0x0000, 0x0000 }, /* R955 */
-       { 0x0000, 0x0000, 0x0000 }, /* R956 */
-       { 0x0000, 0x0000, 0x0000 }, /* R957 */
-       { 0x0000, 0x0000, 0x0000 }, /* R958 */
-       { 0x0000, 0x0000, 0x0000 }, /* R959 */
-       { 0x0000, 0x0000, 0x0000 }, /* R960 */
-       { 0x0000, 0x0000, 0x0000 }, /* R961 */
-       { 0x0000, 0x0000, 0x0000 }, /* R962 */
-       { 0x0000, 0x0000, 0x0000 }, /* R963 */
-       { 0x0000, 0x0000, 0x0000 }, /* R964 */
-       { 0x0000, 0x0000, 0x0000 }, /* R965 */
-       { 0x0000, 0x0000, 0x0000 }, /* R966 */
-       { 0x0000, 0x0000, 0x0000 }, /* R967 */
-       { 0x0000, 0x0000, 0x0000 }, /* R968 */
-       { 0x0000, 0x0000, 0x0000 }, /* R969 */
-       { 0x0000, 0x0000, 0x0000 }, /* R970 */
-       { 0x0000, 0x0000, 0x0000 }, /* R971 */
-       { 0x0000, 0x0000, 0x0000 }, /* R972 */
-       { 0x0000, 0x0000, 0x0000 }, /* R973 */
-       { 0x0000, 0x0000, 0x0000 }, /* R974 */
-       { 0x0000, 0x0000, 0x0000 }, /* R975 */
-       { 0x0000, 0x0000, 0x0000 }, /* R976 */
-       { 0x0000, 0x0000, 0x0000 }, /* R977 */
-       { 0x0000, 0x0000, 0x0000 }, /* R978 */
-       { 0x0000, 0x0000, 0x0000 }, /* R979 */
-       { 0x0000, 0x0000, 0x0000 }, /* R980 */
-       { 0x0000, 0x0000, 0x0000 }, /* R981 */
-       { 0x0000, 0x0000, 0x0000 }, /* R982 */
-       { 0x0000, 0x0000, 0x0000 }, /* R983 */
-       { 0x0000, 0x0000, 0x0000 }, /* R984 */
-       { 0x0000, 0x0000, 0x0000 }, /* R985 */
-       { 0x0000, 0x0000, 0x0000 }, /* R986 */
-       { 0x0000, 0x0000, 0x0000 }, /* R987 */
-       { 0x0000, 0x0000, 0x0000 }, /* R988 */
-       { 0x0000, 0x0000, 0x0000 }, /* R989 */
-       { 0x0000, 0x0000, 0x0000 }, /* R990 */
-       { 0x0000, 0x0000, 0x0000 }, /* R991 */
-       { 0x0000, 0x0000, 0x0000 }, /* R992 */
-       { 0x0000, 0x0000, 0x0000 }, /* R993 */
-       { 0x0000, 0x0000, 0x0000 }, /* R994 */
-       { 0x0000, 0x0000, 0x0000 }, /* R995 */
-       { 0x0000, 0x0000, 0x0000 }, /* R996 */
-       { 0x0000, 0x0000, 0x0000 }, /* R997 */
-       { 0x0000, 0x0000, 0x0000 }, /* R998 */
-       { 0x0000, 0x0000, 0x0000 }, /* R999 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1000 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1001 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1002 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1003 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1004 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1005 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1006 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1007 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1008 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1009 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1010 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1011 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1012 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1013 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1014 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1015 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1016 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1017 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1018 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1019 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1020 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1021 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1022 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1023 */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1024  - AIF1 ADC1 Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1025  - AIF1 ADC1 Right Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1026  - AIF1 DAC1 Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1027  - AIF1 DAC1 Right Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1028  - AIF1 ADC2 Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1029  - AIF1 ADC2 Right Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1030  - AIF1 DAC2 Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1031  - AIF1 DAC2 Right Volume */
-       { 0x0000, 0x0000, 0x0000 }, /* R1032 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1033 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1034 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1035 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1036 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1037 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1038 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1039 */
-       { 0xF800, 0xF800, 0x0000 }, /* R1040  - AIF1 ADC1 Filters */
-       { 0x7800, 0x7800, 0x0000 }, /* R1041  - AIF1 ADC2 Filters */
-       { 0x0000, 0x0000, 0x0000 }, /* R1042 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1043 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1044 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1045 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1046 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1047 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1048 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1049 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1050 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1051 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1052 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1053 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1054 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1055 */
-       { 0x02B6, 0x02B6, 0x0000 }, /* R1056  - AIF1 DAC1 Filters (1) */
-       { 0x3F00, 0x3F00, 0x0000 }, /* R1057  - AIF1 DAC1 Filters (2) */
-       { 0x02B6, 0x02B6, 0x0000 }, /* R1058  - AIF1 DAC2 Filters (1) */
-       { 0x3F00, 0x3F00, 0x0000 }, /* R1059  - AIF1 DAC2 Filters (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R1060 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1061 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1062 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1063 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1064 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1065 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1066 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1067 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1068 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1069 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1070 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1071 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1072 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1073 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1074 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1075 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1076 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1077 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1078 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1079 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1080 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1081 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1082 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1083 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1084 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1085 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1086 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1087 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1088  - AIF1 DRC1 (1) */
-       { 0x1FFF, 0x1FFF, 0x0000 }, /* R1089  - AIF1 DRC1 (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1090  - AIF1 DRC1 (3) */
-       { 0x07FF, 0x07FF, 0x0000 }, /* R1091  - AIF1 DRC1 (4) */
-       { 0x03FF, 0x03FF, 0x0000 }, /* R1092  - AIF1 DRC1 (5) */
-       { 0x0000, 0x0000, 0x0000 }, /* R1093 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1094 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1095 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1096 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1097 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1098 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1099 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1100 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1101 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1102 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1103 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1104  - AIF1 DRC2 (1) */
-       { 0x1FFF, 0x1FFF, 0x0000 }, /* R1105  - AIF1 DRC2 (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1106  - AIF1 DRC2 (3) */
-       { 0x07FF, 0x07FF, 0x0000 }, /* R1107  - AIF1 DRC2 (4) */
-       { 0x03FF, 0x03FF, 0x0000 }, /* R1108  - AIF1 DRC2 (5) */
-       { 0x0000, 0x0000, 0x0000 }, /* R1109 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1110 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1111 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1112 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1113 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1114 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1115 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1116 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1117 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1118 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1119 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1120 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1121 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1122 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1123 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1124 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1125 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1126 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1127 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1128 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1129 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1130 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1131 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1132 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1133 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1134 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1135 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1136 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1137 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1138 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1139 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1140 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1141 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1142 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1143 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1144 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1145 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1146 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1147 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1148 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1149 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1150 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1151 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1152  - AIF1 DAC1 EQ Gains (1) */
-       { 0xFFC0, 0xFFC0, 0x0000 }, /* R1153  - AIF1 DAC1 EQ Gains (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1154  - AIF1 DAC1 EQ Band 1 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1155  - AIF1 DAC1 EQ Band 1 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1156  - AIF1 DAC1 EQ Band 1 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1157  - AIF1 DAC1 EQ Band 2 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1158  - AIF1 DAC1 EQ Band 2 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1159  - AIF1 DAC1 EQ Band 2 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1160  - AIF1 DAC1 EQ Band 2 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1161  - AIF1 DAC1 EQ Band 3 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1162  - AIF1 DAC1 EQ Band 3 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1163  - AIF1 DAC1 EQ Band 3 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1164  - AIF1 DAC1 EQ Band 3 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1165  - AIF1 DAC1 EQ Band 4 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1166  - AIF1 DAC1 EQ Band 4 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1167  - AIF1 DAC1 EQ Band 4 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1168  - AIF1 DAC1 EQ Band 4 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1169  - AIF1 DAC1 EQ Band 5 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1170  - AIF1 DAC1 EQ Band 5 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1171  - AIF1 DAC1 EQ Band 5 PG */
-       { 0x0000, 0x0000, 0x0000 }, /* R1172 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1173 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1174 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1175 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1176 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1177 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1178 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1179 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1180 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1181 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1182 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1183 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1184  - AIF1 DAC2 EQ Gains (1) */
-       { 0xFFC0, 0xFFC0, 0x0000 }, /* R1185  - AIF1 DAC2 EQ Gains (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1186  - AIF1 DAC2 EQ Band 1 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1187  - AIF1 DAC2 EQ Band 1 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1188  - AIF1 DAC2 EQ Band 1 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1189  - AIF1 DAC2 EQ Band 2 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1190  - AIF1 DAC2 EQ Band 2 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1191  - AIF1 DAC2 EQ Band 2 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1192  - AIF1 DAC2 EQ Band 2 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1193  - AIF1 DAC2 EQ Band 3 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1194  - AIF1 DAC2 EQ Band 3 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1195  - AIF1 DAC2 EQ Band 3 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1196  - AIF1 DAC2 EQ Band 3 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1197  - AIF1 DAC2 EQ Band 4 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1198  - AIF1 DAC2 EQ Band 4 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1199  - AIF1 DAC2 EQ Band 4 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1200  - AIF1 DAC2 EQ Band 4 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1201  - AIF1 DAC2 EQ Band 5 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1202  - AIF1 DAC2 EQ Band 5 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1203  - AIF1 DAC2 EQ Band 5 PG */
-       { 0x0000, 0x0000, 0x0000 }, /* R1204 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1205 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1206 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1207 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1208 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1209 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1210 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1211 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1212 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1213 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1214 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1215 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1216 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1217 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1218 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1219 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1220 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1221 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1222 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1223 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1224 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1225 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1226 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1227 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1228 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1229 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1230 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1231 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1232 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1233 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1234 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1235 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1236 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1237 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1238 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1239 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1240 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1241 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1242 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1243 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1244 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1245 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1246 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1247 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1248 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1249 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1250 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1251 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1252 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1253 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1254 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1255 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1256 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1257 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1258 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1259 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1260 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1261 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1262 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1263 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1264 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1265 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1266 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1267 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1268 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1269 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1270 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1271 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1272 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1273 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1274 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1275 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1276 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1277 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1278 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1279 */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1280  - AIF2 ADC Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1281  - AIF2 ADC Right Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1282  - AIF2 DAC Left Volume */
-       { 0x00FF, 0x01FF, 0x0000 }, /* R1283  - AIF2 DAC Right Volume */
-       { 0x0000, 0x0000, 0x0000 }, /* R1284 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1285 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1286 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1287 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1288 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1289 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1290 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1291 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1292 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1293 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1294 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1295 */
-       { 0xF800, 0xF800, 0x0000 }, /* R1296  - AIF2 ADC Filters */
-       { 0x0000, 0x0000, 0x0000 }, /* R1297 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1298 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1299 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1300 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1301 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1302 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1303 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1304 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1305 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1306 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1307 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1308 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1309 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1310 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1311 */
-       { 0x02B6, 0x02B6, 0x0000 }, /* R1312  - AIF2 DAC Filters (1) */
-       { 0x3F00, 0x3F00, 0x0000 }, /* R1313  - AIF2 DAC Filters (2) */
-       { 0x0000, 0x0000, 0x0000 }, /* R1314 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1315 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1316 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1317 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1318 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1319 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1320 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1321 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1322 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1323 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1324 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1325 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1326 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1327 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1328 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1329 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1330 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1331 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1332 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1333 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1334 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1335 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1336 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1337 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1338 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1339 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1340 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1341 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1342 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1343 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1344  - AIF2 DRC (1) */
-       { 0x1FFF, 0x1FFF, 0x0000 }, /* R1345  - AIF2 DRC (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1346  - AIF2 DRC (3) */
-       { 0x07FF, 0x07FF, 0x0000 }, /* R1347  - AIF2 DRC (4) */
-       { 0x03FF, 0x03FF, 0x0000 }, /* R1348  - AIF2 DRC (5) */
-       { 0x0000, 0x0000, 0x0000 }, /* R1349 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1350 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1351 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1352 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1353 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1354 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1355 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1356 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1357 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1358 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1359 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1360 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1361 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1362 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1363 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1364 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1365 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1366 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1367 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1368 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1369 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1370 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1371 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1372 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1373 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1374 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1375 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1376 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1377 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1378 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1379 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1380 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1381 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1382 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1383 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1384 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1385 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1386 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1387 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1388 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1389 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1390 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1391 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1392 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1393 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1394 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1395 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1396 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1397 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1398 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1399 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1400 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1401 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1402 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1403 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1404 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1405 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1406 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1407 */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1408  - AIF2 EQ Gains (1) */
-       { 0xFFC0, 0xFFC0, 0x0000 }, /* R1409  - AIF2 EQ Gains (2) */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1410  - AIF2 EQ Band 1 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1411  - AIF2 EQ Band 1 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1412  - AIF2 EQ Band 1 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1413  - AIF2 EQ Band 2 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1414  - AIF2 EQ Band 2 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1415  - AIF2 EQ Band 2 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1416  - AIF2 EQ Band 2 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1417  - AIF2 EQ Band 3 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1418  - AIF2 EQ Band 3 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1419  - AIF2 EQ Band 3 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1420  - AIF2 EQ Band 3 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1421  - AIF2 EQ Band 4 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1422  - AIF2 EQ Band 4 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1423  - AIF2 EQ Band 4 C */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1424  - AIF2 EQ Band 4 PG */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1425  - AIF2 EQ Band 5 A */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1426  - AIF2 EQ Band 5 B */
-       { 0xFFFF, 0xFFFF, 0x0000 }, /* R1427  - AIF2 EQ Band 5 PG */
-       { 0x0000, 0x0000, 0x0000 }, /* R1428 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1429 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1430 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1431 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1432 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1433 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1434 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1435 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1436 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1437 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1438 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1439 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1440 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1441 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1442 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1443 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1444 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1445 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1446 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1447 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1448 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1449 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1450 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1451 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1452 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1453 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1454 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1455 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1456 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1457 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1458 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1459 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1460 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1461 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1462 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1463 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1464 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1465 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1466 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1467 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1468 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1469 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1470 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1471 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1472 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1473 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1474 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1475 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1476 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1477 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1478 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1479 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1480 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1481 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1482 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1483 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1484 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1485 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1486 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1487 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1488 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1489 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1490 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1491 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1492 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1493 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1494 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1495 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1496 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1497 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1498 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1499 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1500 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1501 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1502 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1503 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1504 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1505 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1506 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1507 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1508 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1509 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1510 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1511 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1512 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1513 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1514 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1515 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1516 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1517 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1518 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1519 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1520 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1521 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1522 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1523 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1524 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1525 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1526 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1527 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1528 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1529 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1530 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1531 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1532 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1533 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1534 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1535 */
-       { 0x01EF, 0x01EF, 0x0000 }, /* R1536  - DAC1 Mixer Volumes */
-       { 0x0037, 0x0037, 0x0000 }, /* R1537  - DAC1 Left Mixer Routing */
-       { 0x0037, 0x0037, 0x0000 }, /* R1538  - DAC1 Right Mixer Routing */
-       { 0x01EF, 0x01EF, 0x0000 }, /* R1539  - DAC2 Mixer Volumes */
-       { 0x0037, 0x0037, 0x0000 }, /* R1540  - DAC2 Left Mixer Routing */
-       { 0x0037, 0x0037, 0x0000 }, /* R1541  - DAC2 Right Mixer Routing */
-       { 0x0003, 0x0003, 0x0000 }, /* R1542  - AIF1 ADC1 Left Mixer Routing */
-       { 0x0003, 0x0003, 0x0000 }, /* R1543  - AIF1 ADC1 Right Mixer Routing */
-       { 0x0003, 0x0003, 0x0000 }, /* R1544  - AIF1 ADC2 Left Mixer Routing */
-       { 0x0003, 0x0003, 0x0000 }, /* R1545  - AIF1 ADC2 Right mixer Routing */
-       { 0x0000, 0x0000, 0x0000 }, /* R1546 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1547 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1548 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1549 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1550 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1551 */
-       { 0x02FF, 0x03FF, 0x0000 }, /* R1552  - DAC1 Left Volume */
-       { 0x02FF, 0x03FF, 0x0000 }, /* R1553  - DAC1 Right Volume */
-       { 0x02FF, 0x03FF, 0x0000 }, /* R1554  - DAC2 Left Volume */
-       { 0x02FF, 0x03FF, 0x0000 }, /* R1555  - DAC2 Right Volume */
-       { 0x0003, 0x0003, 0x0000 }, /* R1556  - DAC Softmute */
-       { 0x0000, 0x0000, 0x0000 }, /* R1557 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1558 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1559 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1560 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1561 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1562 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1563 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1564 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1565 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1566 */
-       { 0x0000, 0x0000, 0x0000 }, /* R1567 */
-       { 0x0003, 0x0003, 0x0000 }, /* R1568  - Oversampling */
-       { 0x03C3, 0x03C3, 0x0000 }, /* R1569  - Sidetone */
+       { 0xFFFF, 0xFFFF }, /* R0     - Software Reset */
+       { 0x3B37, 0x3B37 }, /* R1     - Power Management (1) */
+       { 0x6BF0, 0x6BF0 }, /* R2     - Power Management (2) */
+       { 0x3FF0, 0x3FF0 }, /* R3     - Power Management (3) */
+       { 0x3F3F, 0x3F3F }, /* R4     - Power Management (4) */
+       { 0x3F0F, 0x3F0F }, /* R5     - Power Management (5) */
+       { 0x003F, 0x003F }, /* R6     - Power Management (6) */
+       { 0x0000, 0x0000 }, /* R7 */
+       { 0x0000, 0x0000 }, /* R8 */
+       { 0x0000, 0x0000 }, /* R9 */
+       { 0x0000, 0x0000 }, /* R10 */
+       { 0x0000, 0x0000 }, /* R11 */
+       { 0x0000, 0x0000 }, /* R12 */
+       { 0x0000, 0x0000 }, /* R13 */
+       { 0x0000, 0x0000 }, /* R14 */
+       { 0x0000, 0x0000 }, /* R15 */
+       { 0x0000, 0x0000 }, /* R16 */
+       { 0x0000, 0x0000 }, /* R17 */
+       { 0x0000, 0x0000 }, /* R18 */
+       { 0x0000, 0x0000 }, /* R19 */
+       { 0x0000, 0x0000 }, /* R20 */
+       { 0x01C0, 0x01C0 }, /* R21    - Input Mixer (1) */
+       { 0x0000, 0x0000 }, /* R22 */
+       { 0x0000, 0x0000 }, /* R23 */
+       { 0x00DF, 0x01DF }, /* R24    - Left Line Input 1&2 Volume */
+       { 0x00DF, 0x01DF }, /* R25    - Left Line Input 3&4 Volume */
+       { 0x00DF, 0x01DF }, /* R26    - Right Line Input 1&2 Volume */
+       { 0x00DF, 0x01DF }, /* R27    - Right Line Input 3&4 Volume */
+       { 0x00FF, 0x01FF }, /* R28    - Left Output Volume */
+       { 0x00FF, 0x01FF }, /* R29    - Right Output Volume */
+       { 0x0077, 0x0077 }, /* R30    - Line Outputs Volume */
+       { 0x0030, 0x0030 }, /* R31    - HPOUT2 Volume */
+       { 0x00FF, 0x01FF }, /* R32    - Left OPGA Volume */
+       { 0x00FF, 0x01FF }, /* R33    - Right OPGA Volume */
+       { 0x007F, 0x007F }, /* R34    - SPKMIXL Attenuation */
+       { 0x017F, 0x017F }, /* R35    - SPKMIXR Attenuation */
+       { 0x003F, 0x003F }, /* R36    - SPKOUT Mixers */
+       { 0x003F, 0x003F }, /* R37    - ClassD */
+       { 0x00FF, 0x01FF }, /* R38    - Speaker Volume Left */
+       { 0x00FF, 0x01FF }, /* R39    - Speaker Volume Right */
+       { 0x00FF, 0x00FF }, /* R40    - Input Mixer (2) */
+       { 0x01B7, 0x01B7 }, /* R41    - Input Mixer (3) */
+       { 0x01B7, 0x01B7 }, /* R42    - Input Mixer (4) */
+       { 0x01C7, 0x01C7 }, /* R43    - Input Mixer (5) */
+       { 0x01C7, 0x01C7 }, /* R44    - Input Mixer (6) */
+       { 0x01FF, 0x01FF }, /* R45    - Output Mixer (1) */
+       { 0x01FF, 0x01FF }, /* R46    - Output Mixer (2) */
+       { 0x0FFF, 0x0FFF }, /* R47    - Output Mixer (3) */
+       { 0x0FFF, 0x0FFF }, /* R48    - Output Mixer (4) */
+       { 0x0FFF, 0x0FFF }, /* R49    - Output Mixer (5) */
+       { 0x0FFF, 0x0FFF }, /* R50    - Output Mixer (6) */
+       { 0x0038, 0x0038 }, /* R51    - HPOUT2 Mixer */
+       { 0x0077, 0x0077 }, /* R52    - Line Mixer (1) */
+       { 0x0077, 0x0077 }, /* R53    - Line Mixer (2) */
+       { 0x03FF, 0x03FF }, /* R54    - Speaker Mixer */
+       { 0x00C1, 0x00C1 }, /* R55    - Additional Control */
+       { 0x00F0, 0x00F0 }, /* R56    - AntiPOP (1) */
+       { 0x01EF, 0x01EF }, /* R57    - AntiPOP (2) */
+       { 0x00FF, 0x00FF }, /* R58    - MICBIAS */
+       { 0x000F, 0x000F }, /* R59    - LDO 1 */
+       { 0x0007, 0x0007 }, /* R60    - LDO 2 */
+       { 0x0000, 0x0000 }, /* R61 */
+       { 0x0000, 0x0000 }, /* R62 */
+       { 0x0000, 0x0000 }, /* R63 */
+       { 0x0000, 0x0000 }, /* R64 */
+       { 0x0000, 0x0000 }, /* R65 */
+       { 0x0000, 0x0000 }, /* R66 */
+       { 0x0000, 0x0000 }, /* R67 */
+       { 0x0000, 0x0000 }, /* R68 */
+       { 0x0000, 0x0000 }, /* R69 */
+       { 0x0000, 0x0000 }, /* R70 */
+       { 0x0000, 0x0000 }, /* R71 */
+       { 0x0000, 0x0000 }, /* R72 */
+       { 0x0000, 0x0000 }, /* R73 */
+       { 0x0000, 0x0000 }, /* R74 */
+       { 0x0000, 0x0000 }, /* R75 */
+       { 0x8000, 0x8000 }, /* R76    - Charge Pump (1) */
+       { 0x0000, 0x0000 }, /* R77 */
+       { 0x0000, 0x0000 }, /* R78 */
+       { 0x0000, 0x0000 }, /* R79 */
+       { 0x0000, 0x0000 }, /* R80 */
+       { 0x0301, 0x0301 }, /* R81    - Class W (1) */
+       { 0x0000, 0x0000 }, /* R82 */
+       { 0x0000, 0x0000 }, /* R83 */
+       { 0x333F, 0x333F }, /* R84    - DC Servo (1) */
+       { 0x0FEF, 0x0FEF }, /* R85    - DC Servo (2) */
+       { 0x0000, 0x0000 }, /* R86 */
+       { 0xFFFF, 0xFFFF }, /* R87    - DC Servo (4) */
+       { 0x0333, 0x0000 }, /* R88    - DC Servo Readback */
+       { 0x0000, 0x0000 }, /* R89 */
+       { 0x0000, 0x0000 }, /* R90 */
+       { 0x0000, 0x0000 }, /* R91 */
+       { 0x0000, 0x0000 }, /* R92 */
+       { 0x0000, 0x0000 }, /* R93 */
+       { 0x0000, 0x0000 }, /* R94 */
+       { 0x0000, 0x0000 }, /* R95 */
+       { 0x00EE, 0x00EE }, /* R96    - Analogue HP (1) */
+       { 0x0000, 0x0000 }, /* R97 */
+       { 0x0000, 0x0000 }, /* R98 */
+       { 0x0000, 0x0000 }, /* R99 */
+       { 0x0000, 0x0000 }, /* R100 */
+       { 0x0000, 0x0000 }, /* R101 */
+       { 0x0000, 0x0000 }, /* R102 */
+       { 0x0000, 0x0000 }, /* R103 */
+       { 0x0000, 0x0000 }, /* R104 */
+       { 0x0000, 0x0000 }, /* R105 */
+       { 0x0000, 0x0000 }, /* R106 */
+       { 0x0000, 0x0000 }, /* R107 */
+       { 0x0000, 0x0000 }, /* R108 */
+       { 0x0000, 0x0000 }, /* R109 */
+       { 0x0000, 0x0000 }, /* R110 */
+       { 0x0000, 0x0000 }, /* R111 */
+       { 0x0000, 0x0000 }, /* R112 */
+       { 0x0000, 0x0000 }, /* R113 */
+       { 0x0000, 0x0000 }, /* R114 */
+       { 0x0000, 0x0000 }, /* R115 */
+       { 0x0000, 0x0000 }, /* R116 */
+       { 0x0000, 0x0000 }, /* R117 */
+       { 0x0000, 0x0000 }, /* R118 */
+       { 0x0000, 0x0000 }, /* R119 */
+       { 0x0000, 0x0000 }, /* R120 */
+       { 0x0000, 0x0000 }, /* R121 */
+       { 0x0000, 0x0000 }, /* R122 */
+       { 0x0000, 0x0000 }, /* R123 */
+       { 0x0000, 0x0000 }, /* R124 */
+       { 0x0000, 0x0000 }, /* R125 */
+       { 0x0000, 0x0000 }, /* R126 */
+       { 0x0000, 0x0000 }, /* R127 */
+       { 0x0000, 0x0000 }, /* R128 */
+       { 0x0000, 0x0000 }, /* R129 */
+       { 0x0000, 0x0000 }, /* R130 */
+       { 0x0000, 0x0000 }, /* R131 */
+       { 0x0000, 0x0000 }, /* R132 */
+       { 0x0000, 0x0000 }, /* R133 */
+       { 0x0000, 0x0000 }, /* R134 */
+       { 0x0000, 0x0000 }, /* R135 */
+       { 0x0000, 0x0000 }, /* R136 */
+       { 0x0000, 0x0000 }, /* R137 */
+       { 0x0000, 0x0000 }, /* R138 */
+       { 0x0000, 0x0000 }, /* R139 */
+       { 0x0000, 0x0000 }, /* R140 */
+       { 0x0000, 0x0000 }, /* R141 */
+       { 0x0000, 0x0000 }, /* R142 */
+       { 0x0000, 0x0000 }, /* R143 */
+       { 0x0000, 0x0000 }, /* R144 */
+       { 0x0000, 0x0000 }, /* R145 */
+       { 0x0000, 0x0000 }, /* R146 */
+       { 0x0000, 0x0000 }, /* R147 */
+       { 0x0000, 0x0000 }, /* R148 */
+       { 0x0000, 0x0000 }, /* R149 */
+       { 0x0000, 0x0000 }, /* R150 */
+       { 0x0000, 0x0000 }, /* R151 */
+       { 0x0000, 0x0000 }, /* R152 */
+       { 0x0000, 0x0000 }, /* R153 */
+       { 0x0000, 0x0000 }, /* R154 */
+       { 0x0000, 0x0000 }, /* R155 */
+       { 0x0000, 0x0000 }, /* R156 */
+       { 0x0000, 0x0000 }, /* R157 */
+       { 0x0000, 0x0000 }, /* R158 */
+       { 0x0000, 0x0000 }, /* R159 */
+       { 0x0000, 0x0000 }, /* R160 */
+       { 0x0000, 0x0000 }, /* R161 */
+       { 0x0000, 0x0000 }, /* R162 */
+       { 0x0000, 0x0000 }, /* R163 */
+       { 0x0000, 0x0000 }, /* R164 */
+       { 0x0000, 0x0000 }, /* R165 */
+       { 0x0000, 0x0000 }, /* R166 */
+       { 0x0000, 0x0000 }, /* R167 */
+       { 0x0000, 0x0000 }, /* R168 */
+       { 0x0000, 0x0000 }, /* R169 */
+       { 0x0000, 0x0000 }, /* R170 */
+       { 0x0000, 0x0000 }, /* R171 */
+       { 0x0000, 0x0000 }, /* R172 */
+       { 0x0000, 0x0000 }, /* R173 */
+       { 0x0000, 0x0000 }, /* R174 */
+       { 0x0000, 0x0000 }, /* R175 */
+       { 0x0000, 0x0000 }, /* R176 */
+       { 0x0000, 0x0000 }, /* R177 */
+       { 0x0000, 0x0000 }, /* R178 */
+       { 0x0000, 0x0000 }, /* R179 */
+       { 0x0000, 0x0000 }, /* R180 */
+       { 0x0000, 0x0000 }, /* R181 */
+       { 0x0000, 0x0000 }, /* R182 */
+       { 0x0000, 0x0000 }, /* R183 */
+       { 0x0000, 0x0000 }, /* R184 */
+       { 0x0000, 0x0000 }, /* R185 */
+       { 0x0000, 0x0000 }, /* R186 */
+       { 0x0000, 0x0000 }, /* R187 */
+       { 0x0000, 0x0000 }, /* R188 */
+       { 0x0000, 0x0000 }, /* R189 */
+       { 0x0000, 0x0000 }, /* R190 */
+       { 0x0000, 0x0000 }, /* R191 */
+       { 0x0000, 0x0000 }, /* R192 */
+       { 0x0000, 0x0000 }, /* R193 */
+       { 0x0000, 0x0000 }, /* R194 */
+       { 0x0000, 0x0000 }, /* R195 */
+       { 0x0000, 0x0000 }, /* R196 */
+       { 0x0000, 0x0000 }, /* R197 */
+       { 0x0000, 0x0000 }, /* R198 */
+       { 0x0000, 0x0000 }, /* R199 */
+       { 0x0000, 0x0000 }, /* R200 */
+       { 0x0000, 0x0000 }, /* R201 */
+       { 0x0000, 0x0000 }, /* R202 */
+       { 0x0000, 0x0000 }, /* R203 */
+       { 0x0000, 0x0000 }, /* R204 */
+       { 0x0000, 0x0000 }, /* R205 */
+       { 0x0000, 0x0000 }, /* R206 */
+       { 0x0000, 0x0000 }, /* R207 */
+       { 0x0000, 0x0000 }, /* R208 */
+       { 0x0000, 0x0000 }, /* R209 */
+       { 0x0000, 0x0000 }, /* R210 */
+       { 0x0000, 0x0000 }, /* R211 */
+       { 0x0000, 0x0000 }, /* R212 */
+       { 0x0000, 0x0000 }, /* R213 */
+       { 0x0000, 0x0000 }, /* R214 */
+       { 0x0000, 0x0000 }, /* R215 */
+       { 0x0000, 0x0000 }, /* R216 */
+       { 0x0000, 0x0000 }, /* R217 */
+       { 0x0000, 0x0000 }, /* R218 */
+       { 0x0000, 0x0000 }, /* R219 */
+       { 0x0000, 0x0000 }, /* R220 */
+       { 0x0000, 0x0000 }, /* R221 */
+       { 0x0000, 0x0000 }, /* R222 */
+       { 0x0000, 0x0000 }, /* R223 */
+       { 0x0000, 0x0000 }, /* R224 */
+       { 0x0000, 0x0000 }, /* R225 */
+       { 0x0000, 0x0000 }, /* R226 */
+       { 0x0000, 0x0000 }, /* R227 */
+       { 0x0000, 0x0000 }, /* R228 */
+       { 0x0000, 0x0000 }, /* R229 */
+       { 0x0000, 0x0000 }, /* R230 */
+       { 0x0000, 0x0000 }, /* R231 */
+       { 0x0000, 0x0000 }, /* R232 */
+       { 0x0000, 0x0000 }, /* R233 */
+       { 0x0000, 0x0000 }, /* R234 */
+       { 0x0000, 0x0000 }, /* R235 */
+       { 0x0000, 0x0000 }, /* R236 */
+       { 0x0000, 0x0000 }, /* R237 */
+       { 0x0000, 0x0000 }, /* R238 */
+       { 0x0000, 0x0000 }, /* R239 */
+       { 0x0000, 0x0000 }, /* R240 */
+       { 0x0000, 0x0000 }, /* R241 */
+       { 0x0000, 0x0000 }, /* R242 */
+       { 0x0000, 0x0000 }, /* R243 */
+       { 0x0000, 0x0000 }, /* R244 */
+       { 0x0000, 0x0000 }, /* R245 */
+       { 0x0000, 0x0000 }, /* R246 */
+       { 0x0000, 0x0000 }, /* R247 */
+       { 0x0000, 0x0000 }, /* R248 */
+       { 0x0000, 0x0000 }, /* R249 */
+       { 0x0000, 0x0000 }, /* R250 */
+       { 0x0000, 0x0000 }, /* R251 */
+       { 0x0000, 0x0000 }, /* R252 */
+       { 0x0000, 0x0000 }, /* R253 */
+       { 0x0000, 0x0000 }, /* R254 */
+       { 0x0000, 0x0000 }, /* R255 */
+       { 0x000F, 0x0000 }, /* R256   - Chip Revision */
+       { 0x0074, 0x0074 }, /* R257   - Control Interface */
+       { 0x0000, 0x0000 }, /* R258 */
+       { 0x0000, 0x0000 }, /* R259 */
+       { 0x0000, 0x0000 }, /* R260 */
+       { 0x0000, 0x0000 }, /* R261 */
+       { 0x0000, 0x0000 }, /* R262 */
+       { 0x0000, 0x0000 }, /* R263 */
+       { 0x0000, 0x0000 }, /* R264 */
+       { 0x0000, 0x0000 }, /* R265 */
+       { 0x0000, 0x0000 }, /* R266 */
+       { 0x0000, 0x0000 }, /* R267 */
+       { 0x0000, 0x0000 }, /* R268 */
+       { 0x0000, 0x0000 }, /* R269 */
+       { 0x0000, 0x0000 }, /* R270 */
+       { 0x0000, 0x0000 }, /* R271 */
+       { 0x807F, 0x837F }, /* R272   - Write Sequencer Ctrl (1) */
+       { 0x017F, 0x0000 }, /* R273   - Write Sequencer Ctrl (2) */
+       { 0x0000, 0x0000 }, /* R274 */
+       { 0x0000, 0x0000 }, /* R275 */
+       { 0x0000, 0x0000 }, /* R276 */
+       { 0x0000, 0x0000 }, /* R277 */
+       { 0x0000, 0x0000 }, /* R278 */
+       { 0x0000, 0x0000 }, /* R279 */
+       { 0x0000, 0x0000 }, /* R280 */
+       { 0x0000, 0x0000 }, /* R281 */
+       { 0x0000, 0x0000 }, /* R282 */
+       { 0x0000, 0x0000 }, /* R283 */
+       { 0x0000, 0x0000 }, /* R284 */
+       { 0x0000, 0x0000 }, /* R285 */
+       { 0x0000, 0x0000 }, /* R286 */
+       { 0x0000, 0x0000 }, /* R287 */
+       { 0x0000, 0x0000 }, /* R288 */
+       { 0x0000, 0x0000 }, /* R289 */
+       { 0x0000, 0x0000 }, /* R290 */
+       { 0x0000, 0x0000 }, /* R291 */
+       { 0x0000, 0x0000 }, /* R292 */
+       { 0x0000, 0x0000 }, /* R293 */
+       { 0x0000, 0x0000 }, /* R294 */
+       { 0x0000, 0x0000 }, /* R295 */
+       { 0x0000, 0x0000 }, /* R296 */
+       { 0x0000, 0x0000 }, /* R297 */
+       { 0x0000, 0x0000 }, /* R298 */
+       { 0x0000, 0x0000 }, /* R299 */
+       { 0x0000, 0x0000 }, /* R300 */
+       { 0x0000, 0x0000 }, /* R301 */
+       { 0x0000, 0x0000 }, /* R302 */
+       { 0x0000, 0x0000 }, /* R303 */
+       { 0x0000, 0x0000 }, /* R304 */
+       { 0x0000, 0x0000 }, /* R305 */
+       { 0x0000, 0x0000 }, /* R306 */
+       { 0x0000, 0x0000 }, /* R307 */
+       { 0x0000, 0x0000 }, /* R308 */
+       { 0x0000, 0x0000 }, /* R309 */
+       { 0x0000, 0x0000 }, /* R310 */
+       { 0x0000, 0x0000 }, /* R311 */
+       { 0x0000, 0x0000 }, /* R312 */
+       { 0x0000, 0x0000 }, /* R313 */
+       { 0x0000, 0x0000 }, /* R314 */
+       { 0x0000, 0x0000 }, /* R315 */
+       { 0x0000, 0x0000 }, /* R316 */
+       { 0x0000, 0x0000 }, /* R317 */
+       { 0x0000, 0x0000 }, /* R318 */
+       { 0x0000, 0x0000 }, /* R319 */
+       { 0x0000, 0x0000 }, /* R320 */
+       { 0x0000, 0x0000 }, /* R321 */
+       { 0x0000, 0x0000 }, /* R322 */
+       { 0x0000, 0x0000 }, /* R323 */
+       { 0x0000, 0x0000 }, /* R324 */
+       { 0x0000, 0x0000 }, /* R325 */
+       { 0x0000, 0x0000 }, /* R326 */
+       { 0x0000, 0x0000 }, /* R327 */
+       { 0x0000, 0x0000 }, /* R328 */
+       { 0x0000, 0x0000 }, /* R329 */
+       { 0x0000, 0x0000 }, /* R330 */
+       { 0x0000, 0x0000 }, /* R331 */
+       { 0x0000, 0x0000 }, /* R332 */
+       { 0x0000, 0x0000 }, /* R333 */
+       { 0x0000, 0x0000 }, /* R334 */
+       { 0x0000, 0x0000 }, /* R335 */
+       { 0x0000, 0x0000 }, /* R336 */
+       { 0x0000, 0x0000 }, /* R337 */
+       { 0x0000, 0x0000 }, /* R338 */
+       { 0x0000, 0x0000 }, /* R339 */
+       { 0x0000, 0x0000 }, /* R340 */
+       { 0x0000, 0x0000 }, /* R341 */
+       { 0x0000, 0x0000 }, /* R342 */
+       { 0x0000, 0x0000 }, /* R343 */
+       { 0x0000, 0x0000 }, /* R344 */
+       { 0x0000, 0x0000 }, /* R345 */
+       { 0x0000, 0x0000 }, /* R346 */
+       { 0x0000, 0x0000 }, /* R347 */
+       { 0x0000, 0x0000 }, /* R348 */
+       { 0x0000, 0x0000 }, /* R349 */
+       { 0x0000, 0x0000 }, /* R350 */
+       { 0x0000, 0x0000 }, /* R351 */
+       { 0x0000, 0x0000 }, /* R352 */
+       { 0x0000, 0x0000 }, /* R353 */
+       { 0x0000, 0x0000 }, /* R354 */
+       { 0x0000, 0x0000 }, /* R355 */
+       { 0x0000, 0x0000 }, /* R356 */
+       { 0x0000, 0x0000 }, /* R357 */
+       { 0x0000, 0x0000 }, /* R358 */
+       { 0x0000, 0x0000 }, /* R359 */
+       { 0x0000, 0x0000 }, /* R360 */
+       { 0x0000, 0x0000 }, /* R361 */
+       { 0x0000, 0x0000 }, /* R362 */
+       { 0x0000, 0x0000 }, /* R363 */
+       { 0x0000, 0x0000 }, /* R364 */
+       { 0x0000, 0x0000 }, /* R365 */
+       { 0x0000, 0x0000 }, /* R366 */
+       { 0x0000, 0x0000 }, /* R367 */
+       { 0x0000, 0x0000 }, /* R368 */
+       { 0x0000, 0x0000 }, /* R369 */
+       { 0x0000, 0x0000 }, /* R370 */
+       { 0x0000, 0x0000 }, /* R371 */
+       { 0x0000, 0x0000 }, /* R372 */
+       { 0x0000, 0x0000 }, /* R373 */
+       { 0x0000, 0x0000 }, /* R374 */
+       { 0x0000, 0x0000 }, /* R375 */
+       { 0x0000, 0x0000 }, /* R376 */
+       { 0x0000, 0x0000 }, /* R377 */
+       { 0x0000, 0x0000 }, /* R378 */
+       { 0x0000, 0x0000 }, /* R379 */
+       { 0x0000, 0x0000 }, /* R380 */
+       { 0x0000, 0x0000 }, /* R381 */
+       { 0x0000, 0x0000 }, /* R382 */
+       { 0x0000, 0x0000 }, /* R383 */
+       { 0x0000, 0x0000 }, /* R384 */
+       { 0x0000, 0x0000 }, /* R385 */
+       { 0x0000, 0x0000 }, /* R386 */
+       { 0x0000, 0x0000 }, /* R387 */
+       { 0x0000, 0x0000 }, /* R388 */
+       { 0x0000, 0x0000 }, /* R389 */
+       { 0x0000, 0x0000 }, /* R390 */
+       { 0x0000, 0x0000 }, /* R391 */
+       { 0x0000, 0x0000 }, /* R392 */
+       { 0x0000, 0x0000 }, /* R393 */
+       { 0x0000, 0x0000 }, /* R394 */
+       { 0x0000, 0x0000 }, /* R395 */
+       { 0x0000, 0x0000 }, /* R396 */
+       { 0x0000, 0x0000 }, /* R397 */
+       { 0x0000, 0x0000 }, /* R398 */
+       { 0x0000, 0x0000 }, /* R399 */
+       { 0x0000, 0x0000 }, /* R400 */
+       { 0x0000, 0x0000 }, /* R401 */
+       { 0x0000, 0x0000 }, /* R402 */
+       { 0x0000, 0x0000 }, /* R403 */
+       { 0x0000, 0x0000 }, /* R404 */
+       { 0x0000, 0x0000 }, /* R405 */
+       { 0x0000, 0x0000 }, /* R406 */
+       { 0x0000, 0x0000 }, /* R407 */
+       { 0x0000, 0x0000 }, /* R408 */
+       { 0x0000, 0x0000 }, /* R409 */
+       { 0x0000, 0x0000 }, /* R410 */
+       { 0x0000, 0x0000 }, /* R411 */
+       { 0x0000, 0x0000 }, /* R412 */
+       { 0x0000, 0x0000 }, /* R413 */
+       { 0x0000, 0x0000 }, /* R414 */
+       { 0x0000, 0x0000 }, /* R415 */
+       { 0x0000, 0x0000 }, /* R416 */
+       { 0x0000, 0x0000 }, /* R417 */
+       { 0x0000, 0x0000 }, /* R418 */
+       { 0x0000, 0x0000 }, /* R419 */
+       { 0x0000, 0x0000 }, /* R420 */
+       { 0x0000, 0x0000 }, /* R421 */
+       { 0x0000, 0x0000 }, /* R422 */
+       { 0x0000, 0x0000 }, /* R423 */
+       { 0x0000, 0x0000 }, /* R424 */
+       { 0x0000, 0x0000 }, /* R425 */
+       { 0x0000, 0x0000 }, /* R426 */
+       { 0x0000, 0x0000 }, /* R427 */
+       { 0x0000, 0x0000 }, /* R428 */
+       { 0x0000, 0x0000 }, /* R429 */
+       { 0x0000, 0x0000 }, /* R430 */
+       { 0x0000, 0x0000 }, /* R431 */
+       { 0x0000, 0x0000 }, /* R432 */
+       { 0x0000, 0x0000 }, /* R433 */
+       { 0x0000, 0x0000 }, /* R434 */
+       { 0x0000, 0x0000 }, /* R435 */
+       { 0x0000, 0x0000 }, /* R436 */
+       { 0x0000, 0x0000 }, /* R437 */
+       { 0x0000, 0x0000 }, /* R438 */
+       { 0x0000, 0x0000 }, /* R439 */
+       { 0x0000, 0x0000 }, /* R440 */
+       { 0x0000, 0x0000 }, /* R441 */
+       { 0x0000, 0x0000 }, /* R442 */
+       { 0x0000, 0x0000 }, /* R443 */
+       { 0x0000, 0x0000 }, /* R444 */
+       { 0x0000, 0x0000 }, /* R445 */
+       { 0x0000, 0x0000 }, /* R446 */
+       { 0x0000, 0x0000 }, /* R447 */
+       { 0x0000, 0x0000 }, /* R448 */
+       { 0x0000, 0x0000 }, /* R449 */
+       { 0x0000, 0x0000 }, /* R450 */
+       { 0x0000, 0x0000 }, /* R451 */
+       { 0x0000, 0x0000 }, /* R452 */
+       { 0x0000, 0x0000 }, /* R453 */
+       { 0x0000, 0x0000 }, /* R454 */
+       { 0x0000, 0x0000 }, /* R455 */
+       { 0x0000, 0x0000 }, /* R456 */
+       { 0x0000, 0x0000 }, /* R457 */
+       { 0x0000, 0x0000 }, /* R458 */
+       { 0x0000, 0x0000 }, /* R459 */
+       { 0x0000, 0x0000 }, /* R460 */
+       { 0x0000, 0x0000 }, /* R461 */
+       { 0x0000, 0x0000 }, /* R462 */
+       { 0x0000, 0x0000 }, /* R463 */
+       { 0x0000, 0x0000 }, /* R464 */
+       { 0x0000, 0x0000 }, /* R465 */
+       { 0x0000, 0x0000 }, /* R466 */
+       { 0x0000, 0x0000 }, /* R467 */
+       { 0x0000, 0x0000 }, /* R468 */
+       { 0x0000, 0x0000 }, /* R469 */
+       { 0x0000, 0x0000 }, /* R470 */
+       { 0x0000, 0x0000 }, /* R471 */
+       { 0x0000, 0x0000 }, /* R472 */
+       { 0x0000, 0x0000 }, /* R473 */
+       { 0x0000, 0x0000 }, /* R474 */
+       { 0x0000, 0x0000 }, /* R475 */
+       { 0x0000, 0x0000 }, /* R476 */
+       { 0x0000, 0x0000 }, /* R477 */
+       { 0x0000, 0x0000 }, /* R478 */
+       { 0x0000, 0x0000 }, /* R479 */
+       { 0x0000, 0x0000 }, /* R480 */
+       { 0x0000, 0x0000 }, /* R481 */
+       { 0x0000, 0x0000 }, /* R482 */
+       { 0x0000, 0x0000 }, /* R483 */
+       { 0x0000, 0x0000 }, /* R484 */
+       { 0x0000, 0x0000 }, /* R485 */
+       { 0x0000, 0x0000 }, /* R486 */
+       { 0x0000, 0x0000 }, /* R487 */
+       { 0x0000, 0x0000 }, /* R488 */
+       { 0x0000, 0x0000 }, /* R489 */
+       { 0x0000, 0x0000 }, /* R490 */
+       { 0x0000, 0x0000 }, /* R491 */
+       { 0x0000, 0x0000 }, /* R492 */
+       { 0x0000, 0x0000 }, /* R493 */
+       { 0x0000, 0x0000 }, /* R494 */
+       { 0x0000, 0x0000 }, /* R495 */
+       { 0x0000, 0x0000 }, /* R496 */
+       { 0x0000, 0x0000 }, /* R497 */
+       { 0x0000, 0x0000 }, /* R498 */
+       { 0x0000, 0x0000 }, /* R499 */
+       { 0x0000, 0x0000 }, /* R500 */
+       { 0x0000, 0x0000 }, /* R501 */
+       { 0x0000, 0x0000 }, /* R502 */
+       { 0x0000, 0x0000 }, /* R503 */
+       { 0x0000, 0x0000 }, /* R504 */
+       { 0x0000, 0x0000 }, /* R505 */
+       { 0x0000, 0x0000 }, /* R506 */
+       { 0x0000, 0x0000 }, /* R507 */
+       { 0x0000, 0x0000 }, /* R508 */
+       { 0x0000, 0x0000 }, /* R509 */
+       { 0x0000, 0x0000 }, /* R510 */
+       { 0x0000, 0x0000 }, /* R511 */
+       { 0x001F, 0x001F }, /* R512   - AIF1 Clocking (1) */
+       { 0x003F, 0x003F }, /* R513   - AIF1 Clocking (2) */
+       { 0x0000, 0x0000 }, /* R514 */
+       { 0x0000, 0x0000 }, /* R515 */
+       { 0x001F, 0x001F }, /* R516   - AIF2 Clocking (1) */
+       { 0x003F, 0x003F }, /* R517   - AIF2 Clocking (2) */
+       { 0x0000, 0x0000 }, /* R518 */
+       { 0x0000, 0x0000 }, /* R519 */
+       { 0x001F, 0x001F }, /* R520   - Clocking (1) */
+       { 0x0777, 0x0777 }, /* R521   - Clocking (2) */
+       { 0x0000, 0x0000 }, /* R522 */
+       { 0x0000, 0x0000 }, /* R523 */
+       { 0x0000, 0x0000 }, /* R524 */
+       { 0x0000, 0x0000 }, /* R525 */
+       { 0x0000, 0x0000 }, /* R526 */
+       { 0x0000, 0x0000 }, /* R527 */
+       { 0x00FF, 0x00FF }, /* R528   - AIF1 Rate */
+       { 0x00FF, 0x00FF }, /* R529   - AIF2 Rate */
+       { 0x000F, 0x0000 }, /* R530   - Rate Status */
+       { 0x0000, 0x0000 }, /* R531 */
+       { 0x0000, 0x0000 }, /* R532 */
+       { 0x0000, 0x0000 }, /* R533 */
+       { 0x0000, 0x0000 }, /* R534 */
+       { 0x0000, 0x0000 }, /* R535 */
+       { 0x0000, 0x0000 }, /* R536 */
+       { 0x0000, 0x0000 }, /* R537 */
+       { 0x0000, 0x0000 }, /* R538 */
+       { 0x0000, 0x0000 }, /* R539 */
+       { 0x0000, 0x0000 }, /* R540 */
+       { 0x0000, 0x0000 }, /* R541 */
+       { 0x0000, 0x0000 }, /* R542 */
+       { 0x0000, 0x0000 }, /* R543 */
+       { 0x0007, 0x0007 }, /* R544   - FLL1 Control (1) */
+       { 0x3F77, 0x3F77 }, /* R545   - FLL1 Control (2) */
+       { 0xFFFF, 0xFFFF }, /* R546   - FLL1 Control (3) */
+       { 0x7FEF, 0x7FEF }, /* R547   - FLL1 Control (4) */
+       { 0x1FDB, 0x1FDB }, /* R548   - FLL1 Control (5) */
+       { 0x0000, 0x0000 }, /* R549 */
+       { 0x0000, 0x0000 }, /* R550 */
+       { 0x0000, 0x0000 }, /* R551 */
+       { 0x0000, 0x0000 }, /* R552 */
+       { 0x0000, 0x0000 }, /* R553 */
+       { 0x0000, 0x0000 }, /* R554 */
+       { 0x0000, 0x0000 }, /* R555 */
+       { 0x0000, 0x0000 }, /* R556 */
+       { 0x0000, 0x0000 }, /* R557 */
+       { 0x0000, 0x0000 }, /* R558 */
+       { 0x0000, 0x0000 }, /* R559 */
+       { 0x0000, 0x0000 }, /* R560 */
+       { 0x0000, 0x0000 }, /* R561 */
+       { 0x0000, 0x0000 }, /* R562 */
+       { 0x0000, 0x0000 }, /* R563 */
+       { 0x0000, 0x0000 }, /* R564 */
+       { 0x0000, 0x0000 }, /* R565 */
+       { 0x0000, 0x0000 }, /* R566 */
+       { 0x0000, 0x0000 }, /* R567 */
+       { 0x0000, 0x0000 }, /* R568 */
+       { 0x0000, 0x0000 }, /* R569 */
+       { 0x0000, 0x0000 }, /* R570 */
+       { 0x0000, 0x0000 }, /* R571 */
+       { 0x0000, 0x0000 }, /* R572 */
+       { 0x0000, 0x0000 }, /* R573 */
+       { 0x0000, 0x0000 }, /* R574 */
+       { 0x0000, 0x0000 }, /* R575 */
+       { 0x0007, 0x0007 }, /* R576   - FLL2 Control (1) */
+       { 0x3F77, 0x3F77 }, /* R577   - FLL2 Control (2) */
+       { 0xFFFF, 0xFFFF }, /* R578   - FLL2 Control (3) */
+       { 0x7FEF, 0x7FEF }, /* R579   - FLL2 Control (4) */
+       { 0x1FDB, 0x1FDB }, /* R580   - FLL2 Control (5) */
+       { 0x0000, 0x0000 }, /* R581 */
+       { 0x0000, 0x0000 }, /* R582 */
+       { 0x0000, 0x0000 }, /* R583 */
+       { 0x0000, 0x0000 }, /* R584 */
+       { 0x0000, 0x0000 }, /* R585 */
+       { 0x0000, 0x0000 }, /* R586 */
+       { 0x0000, 0x0000 }, /* R587 */
+       { 0x0000, 0x0000 }, /* R588 */
+       { 0x0000, 0x0000 }, /* R589 */
+       { 0x0000, 0x0000 }, /* R590 */
+       { 0x0000, 0x0000 }, /* R591 */
+       { 0x0000, 0x0000 }, /* R592 */
+       { 0x0000, 0x0000 }, /* R593 */
+       { 0x0000, 0x0000 }, /* R594 */
+       { 0x0000, 0x0000 }, /* R595 */
+       { 0x0000, 0x0000 }, /* R596 */
+       { 0x0000, 0x0000 }, /* R597 */
+       { 0x0000, 0x0000 }, /* R598 */
+       { 0x0000, 0x0000 }, /* R599 */
+       { 0x0000, 0x0000 }, /* R600 */
+       { 0x0000, 0x0000 }, /* R601 */
+       { 0x0000, 0x0000 }, /* R602 */
+       { 0x0000, 0x0000 }, /* R603 */
+       { 0x0000, 0x0000 }, /* R604 */
+       { 0x0000, 0x0000 }, /* R605 */
+       { 0x0000, 0x0000 }, /* R606 */
+       { 0x0000, 0x0000 }, /* R607 */
+       { 0x0000, 0x0000 }, /* R608 */
+       { 0x0000, 0x0000 }, /* R609 */
+       { 0x0000, 0x0000 }, /* R610 */
+       { 0x0000, 0x0000 }, /* R611 */
+       { 0x0000, 0x0000 }, /* R612 */
+       { 0x0000, 0x0000 }, /* R613 */
+       { 0x0000, 0x0000 }, /* R614 */
+       { 0x0000, 0x0000 }, /* R615 */
+       { 0x0000, 0x0000 }, /* R616 */
+       { 0x0000, 0x0000 }, /* R617 */
+       { 0x0000, 0x0000 }, /* R618 */
+       { 0x0000, 0x0000 }, /* R619 */
+       { 0x0000, 0x0000 }, /* R620 */
+       { 0x0000, 0x0000 }, /* R621 */
+       { 0x0000, 0x0000 }, /* R622 */
+       { 0x0000, 0x0000 }, /* R623 */
+       { 0x0000, 0x0000 }, /* R624 */
+       { 0x0000, 0x0000 }, /* R625 */
+       { 0x0000, 0x0000 }, /* R626 */
+       { 0x0000, 0x0000 }, /* R627 */
+       { 0x0000, 0x0000 }, /* R628 */
+       { 0x0000, 0x0000 }, /* R629 */
+       { 0x0000, 0x0000 }, /* R630 */
+       { 0x0000, 0x0000 }, /* R631 */
+       { 0x0000, 0x0000 }, /* R632 */
+       { 0x0000, 0x0000 }, /* R633 */
+       { 0x0000, 0x0000 }, /* R634 */
+       { 0x0000, 0x0000 }, /* R635 */
+       { 0x0000, 0x0000 }, /* R636 */
+       { 0x0000, 0x0000 }, /* R637 */
+       { 0x0000, 0x0000 }, /* R638 */
+       { 0x0000, 0x0000 }, /* R639 */
+       { 0x0000, 0x0000 }, /* R640 */
+       { 0x0000, 0x0000 }, /* R641 */
+       { 0x0000, 0x0000 }, /* R642 */
+       { 0x0000, 0x0000 }, /* R643 */
+       { 0x0000, 0x0000 }, /* R644 */
+       { 0x0000, 0x0000 }, /* R645 */
+       { 0x0000, 0x0000 }, /* R646 */
+       { 0x0000, 0x0000 }, /* R647 */
+       { 0x0000, 0x0000 }, /* R648 */
+       { 0x0000, 0x0000 }, /* R649 */
+       { 0x0000, 0x0000 }, /* R650 */
+       { 0x0000, 0x0000 }, /* R651 */
+       { 0x0000, 0x0000 }, /* R652 */
+       { 0x0000, 0x0000 }, /* R653 */
+       { 0x0000, 0x0000 }, /* R654 */
+       { 0x0000, 0x0000 }, /* R655 */
+       { 0x0000, 0x0000 }, /* R656 */
+       { 0x0000, 0x0000 }, /* R657 */
+       { 0x0000, 0x0000 }, /* R658 */
+       { 0x0000, 0x0000 }, /* R659 */
+       { 0x0000, 0x0000 }, /* R660 */
+       { 0x0000, 0x0000 }, /* R661 */
+       { 0x0000, 0x0000 }, /* R662 */
+       { 0x0000, 0x0000 }, /* R663 */
+       { 0x0000, 0x0000 }, /* R664 */
+       { 0x0000, 0x0000 }, /* R665 */
+       { 0x0000, 0x0000 }, /* R666 */
+       { 0x0000, 0x0000 }, /* R667 */
+       { 0x0000, 0x0000 }, /* R668 */
+       { 0x0000, 0x0000 }, /* R669 */
+       { 0x0000, 0x0000 }, /* R670 */
+       { 0x0000, 0x0000 }, /* R671 */
+       { 0x0000, 0x0000 }, /* R672 */
+       { 0x0000, 0x0000 }, /* R673 */
+       { 0x0000, 0x0000 }, /* R674 */
+       { 0x0000, 0x0000 }, /* R675 */
+       { 0x0000, 0x0000 }, /* R676 */
+       { 0x0000, 0x0000 }, /* R677 */
+       { 0x0000, 0x0000 }, /* R678 */
+       { 0x0000, 0x0000 }, /* R679 */
+       { 0x0000, 0x0000 }, /* R680 */
+       { 0x0000, 0x0000 }, /* R681 */
+       { 0x0000, 0x0000 }, /* R682 */
+       { 0x0000, 0x0000 }, /* R683 */
+       { 0x0000, 0x0000 }, /* R684 */
+       { 0x0000, 0x0000 }, /* R685 */
+       { 0x0000, 0x0000 }, /* R686 */
+       { 0x0000, 0x0000 }, /* R687 */
+       { 0x0000, 0x0000 }, /* R688 */
+       { 0x0000, 0x0000 }, /* R689 */
+       { 0x0000, 0x0000 }, /* R690 */
+       { 0x0000, 0x0000 }, /* R691 */
+       { 0x0000, 0x0000 }, /* R692 */
+       { 0x0000, 0x0000 }, /* R693 */
+       { 0x0000, 0x0000 }, /* R694 */
+       { 0x0000, 0x0000 }, /* R695 */
+       { 0x0000, 0x0000 }, /* R696 */
+       { 0x0000, 0x0000 }, /* R697 */
+       { 0x0000, 0x0000 }, /* R698 */
+       { 0x0000, 0x0000 }, /* R699 */
+       { 0x0000, 0x0000 }, /* R700 */
+       { 0x0000, 0x0000 }, /* R701 */
+       { 0x0000, 0x0000 }, /* R702 */
+       { 0x0000, 0x0000 }, /* R703 */
+       { 0x0000, 0x0000 }, /* R704 */
+       { 0x0000, 0x0000 }, /* R705 */
+       { 0x0000, 0x0000 }, /* R706 */
+       { 0x0000, 0x0000 }, /* R707 */
+       { 0x0000, 0x0000 }, /* R708 */
+       { 0x0000, 0x0000 }, /* R709 */
+       { 0x0000, 0x0000 }, /* R710 */
+       { 0x0000, 0x0000 }, /* R711 */
+       { 0x0000, 0x0000 }, /* R712 */
+       { 0x0000, 0x0000 }, /* R713 */
+       { 0x0000, 0x0000 }, /* R714 */
+       { 0x0000, 0x0000 }, /* R715 */
+       { 0x0000, 0x0000 }, /* R716 */
+       { 0x0000, 0x0000 }, /* R717 */
+       { 0x0000, 0x0000 }, /* R718 */
+       { 0x0000, 0x0000 }, /* R719 */
+       { 0x0000, 0x0000 }, /* R720 */
+       { 0x0000, 0x0000 }, /* R721 */
+       { 0x0000, 0x0000 }, /* R722 */
+       { 0x0000, 0x0000 }, /* R723 */
+       { 0x0000, 0x0000 }, /* R724 */
+       { 0x0000, 0x0000 }, /* R725 */
+       { 0x0000, 0x0000 }, /* R726 */
+       { 0x0000, 0x0000 }, /* R727 */
+       { 0x0000, 0x0000 }, /* R728 */
+       { 0x0000, 0x0000 }, /* R729 */
+       { 0x0000, 0x0000 }, /* R730 */
+       { 0x0000, 0x0000 }, /* R731 */
+       { 0x0000, 0x0000 }, /* R732 */
+       { 0x0000, 0x0000 }, /* R733 */
+       { 0x0000, 0x0000 }, /* R734 */
+       { 0x0000, 0x0000 }, /* R735 */
+       { 0x0000, 0x0000 }, /* R736 */
+       { 0x0000, 0x0000 }, /* R737 */
+       { 0x0000, 0x0000 }, /* R738 */
+       { 0x0000, 0x0000 }, /* R739 */
+       { 0x0000, 0x0000 }, /* R740 */
+       { 0x0000, 0x0000 }, /* R741 */
+       { 0x0000, 0x0000 }, /* R742 */
+       { 0x0000, 0x0000 }, /* R743 */
+       { 0x0000, 0x0000 }, /* R744 */
+       { 0x0000, 0x0000 }, /* R745 */
+       { 0x0000, 0x0000 }, /* R746 */
+       { 0x0000, 0x0000 }, /* R747 */
+       { 0x0000, 0x0000 }, /* R748 */
+       { 0x0000, 0x0000 }, /* R749 */
+       { 0x0000, 0x0000 }, /* R750 */
+       { 0x0000, 0x0000 }, /* R751 */
+       { 0x0000, 0x0000 }, /* R752 */
+       { 0x0000, 0x0000 }, /* R753 */
+       { 0x0000, 0x0000 }, /* R754 */
+       { 0x0000, 0x0000 }, /* R755 */
+       { 0x0000, 0x0000 }, /* R756 */
+       { 0x0000, 0x0000 }, /* R757 */
+       { 0x0000, 0x0000 }, /* R758 */
+       { 0x0000, 0x0000 }, /* R759 */
+       { 0x0000, 0x0000 }, /* R760 */
+       { 0x0000, 0x0000 }, /* R761 */
+       { 0x0000, 0x0000 }, /* R762 */
+       { 0x0000, 0x0000 }, /* R763 */
+       { 0x0000, 0x0000 }, /* R764 */
+       { 0x0000, 0x0000 }, /* R765 */
+       { 0x0000, 0x0000 }, /* R766 */
+       { 0x0000, 0x0000 }, /* R767 */
+       { 0xE1F8, 0xE1F8 }, /* R768   - AIF1 Control (1) */
+       { 0xCD1F, 0xCD1F }, /* R769   - AIF1 Control (2) */
+       { 0xF000, 0xF000 }, /* R770   - AIF1 Master/Slave */
+       { 0x01F0, 0x01F0 }, /* R771   - AIF1 BCLK */
+       { 0x0FFF, 0x0FFF }, /* R772   - AIF1ADC LRCLK */
+       { 0x0FFF, 0x0FFF }, /* R773   - AIF1DAC LRCLK */
+       { 0x0003, 0x0003 }, /* R774   - AIF1DAC Data */
+       { 0x0003, 0x0003 }, /* R775   - AIF1ADC Data */
+       { 0x0000, 0x0000 }, /* R776 */
+       { 0x0000, 0x0000 }, /* R777 */
+       { 0x0000, 0x0000 }, /* R778 */
+       { 0x0000, 0x0000 }, /* R779 */
+       { 0x0000, 0x0000 }, /* R780 */
+       { 0x0000, 0x0000 }, /* R781 */
+       { 0x0000, 0x0000 }, /* R782 */
+       { 0x0000, 0x0000 }, /* R783 */
+       { 0xF1F8, 0xF1F8 }, /* R784   - AIF2 Control (1) */
+       { 0xFD1F, 0xFD1F }, /* R785   - AIF2 Control (2) */
+       { 0xF000, 0xF000 }, /* R786   - AIF2 Master/Slave */
+       { 0x01F0, 0x01F0 }, /* R787   - AIF2 BCLK */
+       { 0x0FFF, 0x0FFF }, /* R788   - AIF2ADC LRCLK */
+       { 0x0FFF, 0x0FFF }, /* R789   - AIF2DAC LRCLK */
+       { 0x0003, 0x0003 }, /* R790   - AIF2DAC Data */
+       { 0x0003, 0x0003 }, /* R791   - AIF2ADC Data */
+       { 0x0000, 0x0000 }, /* R792 */
+       { 0x0000, 0x0000 }, /* R793 */
+       { 0x0000, 0x0000 }, /* R794 */
+       { 0x0000, 0x0000 }, /* R795 */
+       { 0x0000, 0x0000 }, /* R796 */
+       { 0x0000, 0x0000 }, /* R797 */
+       { 0x0000, 0x0000 }, /* R798 */
+       { 0x0000, 0x0000 }, /* R799 */
+       { 0x0000, 0x0000 }, /* R800 */
+       { 0x0000, 0x0000 }, /* R801 */
+       { 0x0000, 0x0000 }, /* R802 */
+       { 0x0000, 0x0000 }, /* R803 */
+       { 0x0000, 0x0000 }, /* R804 */
+       { 0x0000, 0x0000 }, /* R805 */
+       { 0x0000, 0x0000 }, /* R806 */
+       { 0x0000, 0x0000 }, /* R807 */
+       { 0x0000, 0x0000 }, /* R808 */
+       { 0x0000, 0x0000 }, /* R809 */
+       { 0x0000, 0x0000 }, /* R810 */
+       { 0x0000, 0x0000 }, /* R811 */
+       { 0x0000, 0x0000 }, /* R812 */
+       { 0x0000, 0x0000 }, /* R813 */
+       { 0x0000, 0x0000 }, /* R814 */
+       { 0x0000, 0x0000 }, /* R815 */
+       { 0x0000, 0x0000 }, /* R816 */
+       { 0x0000, 0x0000 }, /* R817 */
+       { 0x0000, 0x0000 }, /* R818 */
+       { 0x0000, 0x0000 }, /* R819 */
+       { 0x0000, 0x0000 }, /* R820 */
+       { 0x0000, 0x0000 }, /* R821 */
+       { 0x0000, 0x0000 }, /* R822 */
+       { 0x0000, 0x0000 }, /* R823 */
+       { 0x0000, 0x0000 }, /* R824 */
+       { 0x0000, 0x0000 }, /* R825 */
+       { 0x0000, 0x0000 }, /* R826 */
+       { 0x0000, 0x0000 }, /* R827 */
+       { 0x0000, 0x0000 }, /* R828 */
+       { 0x0000, 0x0000 }, /* R829 */
+       { 0x0000, 0x0000 }, /* R830 */
+       { 0x0000, 0x0000 }, /* R831 */
+       { 0x0000, 0x0000 }, /* R832 */
+       { 0x0000, 0x0000 }, /* R833 */
+       { 0x0000, 0x0000 }, /* R834 */
+       { 0x0000, 0x0000 }, /* R835 */
+       { 0x0000, 0x0000 }, /* R836 */
+       { 0x0000, 0x0000 }, /* R837 */
+       { 0x0000, 0x0000 }, /* R838 */
+       { 0x0000, 0x0000 }, /* R839 */
+       { 0x0000, 0x0000 }, /* R840 */
+       { 0x0000, 0x0000 }, /* R841 */
+       { 0x0000, 0x0000 }, /* R842 */
+       { 0x0000, 0x0000 }, /* R843 */
+       { 0x0000, 0x0000 }, /* R844 */
+       { 0x0000, 0x0000 }, /* R845 */
+       { 0x0000, 0x0000 }, /* R846 */
+       { 0x0000, 0x0000 }, /* R847 */
+       { 0x0000, 0x0000 }, /* R848 */
+       { 0x0000, 0x0000 }, /* R849 */
+       { 0x0000, 0x0000 }, /* R850 */
+       { 0x0000, 0x0000 }, /* R851 */
+       { 0x0000, 0x0000 }, /* R852 */
+       { 0x0000, 0x0000 }, /* R853 */
+       { 0x0000, 0x0000 }, /* R854 */
+       { 0x0000, 0x0000 }, /* R855 */
+       { 0x0000, 0x0000 }, /* R856 */
+       { 0x0000, 0x0000 }, /* R857 */
+       { 0x0000, 0x0000 }, /* R858 */
+       { 0x0000, 0x0000 }, /* R859 */
+       { 0x0000, 0x0000 }, /* R860 */
+       { 0x0000, 0x0000 }, /* R861 */
+       { 0x0000, 0x0000 }, /* R862 */
+       { 0x0000, 0x0000 }, /* R863 */
+       { 0x0000, 0x0000 }, /* R864 */
+       { 0x0000, 0x0000 }, /* R865 */
+       { 0x0000, 0x0000 }, /* R866 */
+       { 0x0000, 0x0000 }, /* R867 */
+       { 0x0000, 0x0000 }, /* R868 */
+       { 0x0000, 0x0000 }, /* R869 */
+       { 0x0000, 0x0000 }, /* R870 */
+       { 0x0000, 0x0000 }, /* R871 */
+       { 0x0000, 0x0000 }, /* R872 */
+       { 0x0000, 0x0000 }, /* R873 */
+       { 0x0000, 0x0000 }, /* R874 */
+       { 0x0000, 0x0000 }, /* R875 */
+       { 0x0000, 0x0000 }, /* R876 */
+       { 0x0000, 0x0000 }, /* R877 */
+       { 0x0000, 0x0000 }, /* R878 */
+       { 0x0000, 0x0000 }, /* R879 */
+       { 0x0000, 0x0000 }, /* R880 */
+       { 0x0000, 0x0000 }, /* R881 */
+       { 0x0000, 0x0000 }, /* R882 */
+       { 0x0000, 0x0000 }, /* R883 */
+       { 0x0000, 0x0000 }, /* R884 */
+       { 0x0000, 0x0000 }, /* R885 */
+       { 0x0000, 0x0000 }, /* R886 */
+       { 0x0000, 0x0000 }, /* R887 */
+       { 0x0000, 0x0000 }, /* R888 */
+       { 0x0000, 0x0000 }, /* R889 */
+       { 0x0000, 0x0000 }, /* R890 */
+       { 0x0000, 0x0000 }, /* R891 */
+       { 0x0000, 0x0000 }, /* R892 */
+       { 0x0000, 0x0000 }, /* R893 */
+       { 0x0000, 0x0000 }, /* R894 */
+       { 0x0000, 0x0000 }, /* R895 */
+       { 0x0000, 0x0000 }, /* R896 */
+       { 0x0000, 0x0000 }, /* R897 */
+       { 0x0000, 0x0000 }, /* R898 */
+       { 0x0000, 0x0000 }, /* R899 */
+       { 0x0000, 0x0000 }, /* R900 */
+       { 0x0000, 0x0000 }, /* R901 */
+       { 0x0000, 0x0000 }, /* R902 */
+       { 0x0000, 0x0000 }, /* R903 */
+       { 0x0000, 0x0000 }, /* R904 */
+       { 0x0000, 0x0000 }, /* R905 */
+       { 0x0000, 0x0000 }, /* R906 */
+       { 0x0000, 0x0000 }, /* R907 */
+       { 0x0000, 0x0000 }, /* R908 */
+       { 0x0000, 0x0000 }, /* R909 */
+       { 0x0000, 0x0000 }, /* R910 */
+       { 0x0000, 0x0000 }, /* R911 */
+       { 0x0000, 0x0000 }, /* R912 */
+       { 0x0000, 0x0000 }, /* R913 */
+       { 0x0000, 0x0000 }, /* R914 */
+       { 0x0000, 0x0000 }, /* R915 */
+       { 0x0000, 0x0000 }, /* R916 */
+       { 0x0000, 0x0000 }, /* R917 */
+       { 0x0000, 0x0000 }, /* R918 */
+       { 0x0000, 0x0000 }, /* R919 */
+       { 0x0000, 0x0000 }, /* R920 */
+       { 0x0000, 0x0000 }, /* R921 */
+       { 0x0000, 0x0000 }, /* R922 */
+       { 0x0000, 0x0000 }, /* R923 */
+       { 0x0000, 0x0000 }, /* R924 */
+       { 0x0000, 0x0000 }, /* R925 */
+       { 0x0000, 0x0000 }, /* R926 */
+       { 0x0000, 0x0000 }, /* R927 */
+       { 0x0000, 0x0000 }, /* R928 */
+       { 0x0000, 0x0000 }, /* R929 */
+       { 0x0000, 0x0000 }, /* R930 */
+       { 0x0000, 0x0000 }, /* R931 */
+       { 0x0000, 0x0000 }, /* R932 */
+       { 0x0000, 0x0000 }, /* R933 */
+       { 0x0000, 0x0000 }, /* R934 */
+       { 0x0000, 0x0000 }, /* R935 */
+       { 0x0000, 0x0000 }, /* R936 */
+       { 0x0000, 0x0000 }, /* R937 */
+       { 0x0000, 0x0000 }, /* R938 */
+       { 0x0000, 0x0000 }, /* R939 */
+       { 0x0000, 0x0000 }, /* R940 */
+       { 0x0000, 0x0000 }, /* R941 */
+       { 0x0000, 0x0000 }, /* R942 */
+       { 0x0000, 0x0000 }, /* R943 */
+       { 0x0000, 0x0000 }, /* R944 */
+       { 0x0000, 0x0000 }, /* R945 */
+       { 0x0000, 0x0000 }, /* R946 */
+       { 0x0000, 0x0000 }, /* R947 */
+       { 0x0000, 0x0000 }, /* R948 */
+       { 0x0000, 0x0000 }, /* R949 */
+       { 0x0000, 0x0000 }, /* R950 */
+       { 0x0000, 0x0000 }, /* R951 */
+       { 0x0000, 0x0000 }, /* R952 */
+       { 0x0000, 0x0000 }, /* R953 */
+       { 0x0000, 0x0000 }, /* R954 */
+       { 0x0000, 0x0000 }, /* R955 */
+       { 0x0000, 0x0000 }, /* R956 */
+       { 0x0000, 0x0000 }, /* R957 */
+       { 0x0000, 0x0000 }, /* R958 */
+       { 0x0000, 0x0000 }, /* R959 */
+       { 0x0000, 0x0000 }, /* R960 */
+       { 0x0000, 0x0000 }, /* R961 */
+       { 0x0000, 0x0000 }, /* R962 */
+       { 0x0000, 0x0000 }, /* R963 */
+       { 0x0000, 0x0000 }, /* R964 */
+       { 0x0000, 0x0000 }, /* R965 */
+       { 0x0000, 0x0000 }, /* R966 */
+       { 0x0000, 0x0000 }, /* R967 */
+       { 0x0000, 0x0000 }, /* R968 */
+       { 0x0000, 0x0000 }, /* R969 */
+       { 0x0000, 0x0000 }, /* R970 */
+       { 0x0000, 0x0000 }, /* R971 */
+       { 0x0000, 0x0000 }, /* R972 */
+       { 0x0000, 0x0000 }, /* R973 */
+       { 0x0000, 0x0000 }, /* R974 */
+       { 0x0000, 0x0000 }, /* R975 */
+       { 0x0000, 0x0000 }, /* R976 */
+       { 0x0000, 0x0000 }, /* R977 */
+       { 0x0000, 0x0000 }, /* R978 */
+       { 0x0000, 0x0000 }, /* R979 */
+       { 0x0000, 0x0000 }, /* R980 */
+       { 0x0000, 0x0000 }, /* R981 */
+       { 0x0000, 0x0000 }, /* R982 */
+       { 0x0000, 0x0000 }, /* R983 */
+       { 0x0000, 0x0000 }, /* R984 */
+       { 0x0000, 0x0000 }, /* R985 */
+       { 0x0000, 0x0000 }, /* R986 */
+       { 0x0000, 0x0000 }, /* R987 */
+       { 0x0000, 0x0000 }, /* R988 */
+       { 0x0000, 0x0000 }, /* R989 */
+       { 0x0000, 0x0000 }, /* R990 */
+       { 0x0000, 0x0000 }, /* R991 */
+       { 0x0000, 0x0000 }, /* R992 */
+       { 0x0000, 0x0000 }, /* R993 */
+       { 0x0000, 0x0000 }, /* R994 */
+       { 0x0000, 0x0000 }, /* R995 */
+       { 0x0000, 0x0000 }, /* R996 */
+       { 0x0000, 0x0000 }, /* R997 */
+       { 0x0000, 0x0000 }, /* R998 */
+       { 0x0000, 0x0000 }, /* R999 */
+       { 0x0000, 0x0000 }, /* R1000 */
+       { 0x0000, 0x0000 }, /* R1001 */
+       { 0x0000, 0x0000 }, /* R1002 */
+       { 0x0000, 0x0000 }, /* R1003 */
+       { 0x0000, 0x0000 }, /* R1004 */
+       { 0x0000, 0x0000 }, /* R1005 */
+       { 0x0000, 0x0000 }, /* R1006 */
+       { 0x0000, 0x0000 }, /* R1007 */
+       { 0x0000, 0x0000 }, /* R1008 */
+       { 0x0000, 0x0000 }, /* R1009 */
+       { 0x0000, 0x0000 }, /* R1010 */
+       { 0x0000, 0x0000 }, /* R1011 */
+       { 0x0000, 0x0000 }, /* R1012 */
+       { 0x0000, 0x0000 }, /* R1013 */
+       { 0x0000, 0x0000 }, /* R1014 */
+       { 0x0000, 0x0000 }, /* R1015 */
+       { 0x0000, 0x0000 }, /* R1016 */
+       { 0x0000, 0x0000 }, /* R1017 */
+       { 0x0000, 0x0000 }, /* R1018 */
+       { 0x0000, 0x0000 }, /* R1019 */
+       { 0x0000, 0x0000 }, /* R1020 */
+       { 0x0000, 0x0000 }, /* R1021 */
+       { 0x0000, 0x0000 }, /* R1022 */
+       { 0x0000, 0x0000 }, /* R1023 */
+       { 0x00FF, 0x01FF }, /* R1024  - AIF1 ADC1 Left Volume */
+       { 0x00FF, 0x01FF }, /* R1025  - AIF1 ADC1 Right Volume */
+       { 0x00FF, 0x01FF }, /* R1026  - AIF1 DAC1 Left Volume */
+       { 0x00FF, 0x01FF }, /* R1027  - AIF1 DAC1 Right Volume */
+       { 0x00FF, 0x01FF }, /* R1028  - AIF1 ADC2 Left Volume */
+       { 0x00FF, 0x01FF }, /* R1029  - AIF1 ADC2 Right Volume */
+       { 0x00FF, 0x01FF }, /* R1030  - AIF1 DAC2 Left Volume */
+       { 0x00FF, 0x01FF }, /* R1031  - AIF1 DAC2 Right Volume */
+       { 0x0000, 0x0000 }, /* R1032 */
+       { 0x0000, 0x0000 }, /* R1033 */
+       { 0x0000, 0x0000 }, /* R1034 */
+       { 0x0000, 0x0000 }, /* R1035 */
+       { 0x0000, 0x0000 }, /* R1036 */
+       { 0x0000, 0x0000 }, /* R1037 */
+       { 0x0000, 0x0000 }, /* R1038 */
+       { 0x0000, 0x0000 }, /* R1039 */
+       { 0xF800, 0xF800 }, /* R1040  - AIF1 ADC1 Filters */
+       { 0x7800, 0x7800 }, /* R1041  - AIF1 ADC2 Filters */
+       { 0x0000, 0x0000 }, /* R1042 */
+       { 0x0000, 0x0000 }, /* R1043 */
+       { 0x0000, 0x0000 }, /* R1044 */
+       { 0x0000, 0x0000 }, /* R1045 */
+       { 0x0000, 0x0000 }, /* R1046 */
+       { 0x0000, 0x0000 }, /* R1047 */
+       { 0x0000, 0x0000 }, /* R1048 */
+       { 0x0000, 0x0000 }, /* R1049 */
+       { 0x0000, 0x0000 }, /* R1050 */
+       { 0x0000, 0x0000 }, /* R1051 */
+       { 0x0000, 0x0000 }, /* R1052 */
+       { 0x0000, 0x0000 }, /* R1053 */
+       { 0x0000, 0x0000 }, /* R1054 */
+       { 0x0000, 0x0000 }, /* R1055 */
+       { 0x02B6, 0x02B6 }, /* R1056  - AIF1 DAC1 Filters (1) */
+       { 0x3F00, 0x3F00 }, /* R1057  - AIF1 DAC1 Filters (2) */
+       { 0x02B6, 0x02B6 }, /* R1058  - AIF1 DAC2 Filters (1) */
+       { 0x3F00, 0x3F00 }, /* R1059  - AIF1 DAC2 Filters (2) */
+       { 0x0000, 0x0000 }, /* R1060 */
+       { 0x0000, 0x0000 }, /* R1061 */
+       { 0x0000, 0x0000 }, /* R1062 */
+       { 0x0000, 0x0000 }, /* R1063 */
+       { 0x0000, 0x0000 }, /* R1064 */
+       { 0x0000, 0x0000 }, /* R1065 */
+       { 0x0000, 0x0000 }, /* R1066 */
+       { 0x0000, 0x0000 }, /* R1067 */
+       { 0x0000, 0x0000 }, /* R1068 */
+       { 0x0000, 0x0000 }, /* R1069 */
+       { 0x0000, 0x0000 }, /* R1070 */
+       { 0x0000, 0x0000 }, /* R1071 */
+       { 0x0000, 0x0000 }, /* R1072 */
+       { 0x0000, 0x0000 }, /* R1073 */
+       { 0x0000, 0x0000 }, /* R1074 */
+       { 0x0000, 0x0000 }, /* R1075 */
+       { 0x0000, 0x0000 }, /* R1076 */
+       { 0x0000, 0x0000 }, /* R1077 */
+       { 0x0000, 0x0000 }, /* R1078 */
+       { 0x0000, 0x0000 }, /* R1079 */
+       { 0x0000, 0x0000 }, /* R1080 */
+       { 0x0000, 0x0000 }, /* R1081 */
+       { 0x0000, 0x0000 }, /* R1082 */
+       { 0x0000, 0x0000 }, /* R1083 */
+       { 0x0000, 0x0000 }, /* R1084 */
+       { 0x0000, 0x0000 }, /* R1085 */
+       { 0x0000, 0x0000 }, /* R1086 */
+       { 0x0000, 0x0000 }, /* R1087 */
+       { 0xFFFF, 0xFFFF }, /* R1088  - AIF1 DRC1 (1) */
+       { 0x1FFF, 0x1FFF }, /* R1089  - AIF1 DRC1 (2) */
+       { 0xFFFF, 0xFFFF }, /* R1090  - AIF1 DRC1 (3) */
+       { 0x07FF, 0x07FF }, /* R1091  - AIF1 DRC1 (4) */
+       { 0x03FF, 0x03FF }, /* R1092  - AIF1 DRC1 (5) */
+       { 0x0000, 0x0000 }, /* R1093 */
+       { 0x0000, 0x0000 }, /* R1094 */
+       { 0x0000, 0x0000 }, /* R1095 */
+       { 0x0000, 0x0000 }, /* R1096 */
+       { 0x0000, 0x0000 }, /* R1097 */
+       { 0x0000, 0x0000 }, /* R1098 */
+       { 0x0000, 0x0000 }, /* R1099 */
+       { 0x0000, 0x0000 }, /* R1100 */
+       { 0x0000, 0x0000 }, /* R1101 */
+       { 0x0000, 0x0000 }, /* R1102 */
+       { 0x0000, 0x0000 }, /* R1103 */
+       { 0xFFFF, 0xFFFF }, /* R1104  - AIF1 DRC2 (1) */
+       { 0x1FFF, 0x1FFF }, /* R1105  - AIF1 DRC2 (2) */
+       { 0xFFFF, 0xFFFF }, /* R1106  - AIF1 DRC2 (3) */
+       { 0x07FF, 0x07FF }, /* R1107  - AIF1 DRC2 (4) */
+       { 0x03FF, 0x03FF }, /* R1108  - AIF1 DRC2 (5) */
+       { 0x0000, 0x0000 }, /* R1109 */
+       { 0x0000, 0x0000 }, /* R1110 */
+       { 0x0000, 0x0000 }, /* R1111 */
+       { 0x0000, 0x0000 }, /* R1112 */
+       { 0x0000, 0x0000 }, /* R1113 */
+       { 0x0000, 0x0000 }, /* R1114 */
+       { 0x0000, 0x0000 }, /* R1115 */
+       { 0x0000, 0x0000 }, /* R1116 */
+       { 0x0000, 0x0000 }, /* R1117 */
+       { 0x0000, 0x0000 }, /* R1118 */
+       { 0x0000, 0x0000 }, /* R1119 */
+       { 0x0000, 0x0000 }, /* R1120 */
+       { 0x0000, 0x0000 }, /* R1121 */
+       { 0x0000, 0x0000 }, /* R1122 */
+       { 0x0000, 0x0000 }, /* R1123 */
+       { 0x0000, 0x0000 }, /* R1124 */
+       { 0x0000, 0x0000 }, /* R1125 */
+       { 0x0000, 0x0000 }, /* R1126 */
+       { 0x0000, 0x0000 }, /* R1127 */
+       { 0x0000, 0x0000 }, /* R1128 */
+       { 0x0000, 0x0000 }, /* R1129 */
+       { 0x0000, 0x0000 }, /* R1130 */
+       { 0x0000, 0x0000 }, /* R1131 */
+       { 0x0000, 0x0000 }, /* R1132 */
+       { 0x0000, 0x0000 }, /* R1133 */
+       { 0x0000, 0x0000 }, /* R1134 */
+       { 0x0000, 0x0000 }, /* R1135 */
+       { 0x0000, 0x0000 }, /* R1136 */
+       { 0x0000, 0x0000 }, /* R1137 */
+       { 0x0000, 0x0000 }, /* R1138 */
+       { 0x0000, 0x0000 }, /* R1139 */
+       { 0x0000, 0x0000 }, /* R1140 */
+       { 0x0000, 0x0000 }, /* R1141 */
+       { 0x0000, 0x0000 }, /* R1142 */
+       { 0x0000, 0x0000 }, /* R1143 */
+       { 0x0000, 0x0000 }, /* R1144 */
+       { 0x0000, 0x0000 }, /* R1145 */
+       { 0x0000, 0x0000 }, /* R1146 */
+       { 0x0000, 0x0000 }, /* R1147 */
+       { 0x0000, 0x0000 }, /* R1148 */
+       { 0x0000, 0x0000 }, /* R1149 */
+       { 0x0000, 0x0000 }, /* R1150 */
+       { 0x0000, 0x0000 }, /* R1151 */
+       { 0xFFFF, 0xFFFF }, /* R1152  - AIF1 DAC1 EQ Gains (1) */
+       { 0xFFC0, 0xFFC0 }, /* R1153  - AIF1 DAC1 EQ Gains (2) */
+       { 0xFFFF, 0xFFFF }, /* R1154  - AIF1 DAC1 EQ Band 1 A */
+       { 0xFFFF, 0xFFFF }, /* R1155  - AIF1 DAC1 EQ Band 1 B */
+       { 0xFFFF, 0xFFFF }, /* R1156  - AIF1 DAC1 EQ Band 1 PG */
+       { 0xFFFF, 0xFFFF }, /* R1157  - AIF1 DAC1 EQ Band 2 A */
+       { 0xFFFF, 0xFFFF }, /* R1158  - AIF1 DAC1 EQ Band 2 B */
+       { 0xFFFF, 0xFFFF }, /* R1159  - AIF1 DAC1 EQ Band 2 C */
+       { 0xFFFF, 0xFFFF }, /* R1160  - AIF1 DAC1 EQ Band 2 PG */
+       { 0xFFFF, 0xFFFF }, /* R1161  - AIF1 DAC1 EQ Band 3 A */
+       { 0xFFFF, 0xFFFF }, /* R1162  - AIF1 DAC1 EQ Band 3 B */
+       { 0xFFFF, 0xFFFF }, /* R1163  - AIF1 DAC1 EQ Band 3 C */
+       { 0xFFFF, 0xFFFF }, /* R1164  - AIF1 DAC1 EQ Band 3 PG */
+       { 0xFFFF, 0xFFFF }, /* R1165  - AIF1 DAC1 EQ Band 4 A */
+       { 0xFFFF, 0xFFFF }, /* R1166  - AIF1 DAC1 EQ Band 4 B */
+       { 0xFFFF, 0xFFFF }, /* R1167  - AIF1 DAC1 EQ Band 4 C */
+       { 0xFFFF, 0xFFFF }, /* R1168  - AIF1 DAC1 EQ Band 4 PG */
+       { 0xFFFF, 0xFFFF }, /* R1169  - AIF1 DAC1 EQ Band 5 A */
+       { 0xFFFF, 0xFFFF }, /* R1170  - AIF1 DAC1 EQ Band 5 B */
+       { 0xFFFF, 0xFFFF }, /* R1171  - AIF1 DAC1 EQ Band 5 PG */
+       { 0x0000, 0x0000 }, /* R1172 */
+       { 0x0000, 0x0000 }, /* R1173 */
+       { 0x0000, 0x0000 }, /* R1174 */
+       { 0x0000, 0x0000 }, /* R1175 */
+       { 0x0000, 0x0000 }, /* R1176 */
+       { 0x0000, 0x0000 }, /* R1177 */
+       { 0x0000, 0x0000 }, /* R1178 */
+       { 0x0000, 0x0000 }, /* R1179 */
+       { 0x0000, 0x0000 }, /* R1180 */
+       { 0x0000, 0x0000 }, /* R1181 */
+       { 0x0000, 0x0000 }, /* R1182 */
+       { 0x0000, 0x0000 }, /* R1183 */
+       { 0xFFFF, 0xFFFF }, /* R1184  - AIF1 DAC2 EQ Gains (1) */
+       { 0xFFC0, 0xFFC0 }, /* R1185  - AIF1 DAC2 EQ Gains (2) */
+       { 0xFFFF, 0xFFFF }, /* R1186  - AIF1 DAC2 EQ Band 1 A */
+       { 0xFFFF, 0xFFFF }, /* R1187  - AIF1 DAC2 EQ Band 1 B */
+       { 0xFFFF, 0xFFFF }, /* R1188  - AIF1 DAC2 EQ Band 1 PG */
+       { 0xFFFF, 0xFFFF }, /* R1189  - AIF1 DAC2 EQ Band 2 A */
+       { 0xFFFF, 0xFFFF }, /* R1190  - AIF1 DAC2 EQ Band 2 B */
+       { 0xFFFF, 0xFFFF }, /* R1191  - AIF1 DAC2 EQ Band 2 C */
+       { 0xFFFF, 0xFFFF }, /* R1192  - AIF1 DAC2 EQ Band 2 PG */
+       { 0xFFFF, 0xFFFF }, /* R1193  - AIF1 DAC2 EQ Band 3 A */
+       { 0xFFFF, 0xFFFF }, /* R1194  - AIF1 DAC2 EQ Band 3 B */
+       { 0xFFFF, 0xFFFF }, /* R1195  - AIF1 DAC2 EQ Band 3 C */
+       { 0xFFFF, 0xFFFF }, /* R1196  - AIF1 DAC2 EQ Band 3 PG */
+       { 0xFFFF, 0xFFFF }, /* R1197  - AIF1 DAC2 EQ Band 4 A */
+       { 0xFFFF, 0xFFFF }, /* R1198  - AIF1 DAC2 EQ Band 4 B */
+       { 0xFFFF, 0xFFFF }, /* R1199  - AIF1 DAC2 EQ Band 4 C */
+       { 0xFFFF, 0xFFFF }, /* R1200  - AIF1 DAC2 EQ Band 4 PG */
+       { 0xFFFF, 0xFFFF }, /* R1201  - AIF1 DAC2 EQ Band 5 A */
+       { 0xFFFF, 0xFFFF }, /* R1202  - AIF1 DAC2 EQ Band 5 B */
+       { 0xFFFF, 0xFFFF }, /* R1203  - AIF1 DAC2 EQ Band 5 PG */
+       { 0x0000, 0x0000 }, /* R1204 */
+       { 0x0000, 0x0000 }, /* R1205 */
+       { 0x0000, 0x0000 }, /* R1206 */
+       { 0x0000, 0x0000 }, /* R1207 */
+       { 0x0000, 0x0000 }, /* R1208 */
+       { 0x0000, 0x0000 }, /* R1209 */
+       { 0x0000, 0x0000 }, /* R1210 */
+       { 0x0000, 0x0000 }, /* R1211 */
+       { 0x0000, 0x0000 }, /* R1212 */
+       { 0x0000, 0x0000 }, /* R1213 */
+       { 0x0000, 0x0000 }, /* R1214 */
+       { 0x0000, 0x0000 }, /* R1215 */
+       { 0x0000, 0x0000 }, /* R1216 */
+       { 0x0000, 0x0000 }, /* R1217 */
+       { 0x0000, 0x0000 }, /* R1218 */
+       { 0x0000, 0x0000 }, /* R1219 */
+       { 0x0000, 0x0000 }, /* R1220 */
+       { 0x0000, 0x0000 }, /* R1221 */
+       { 0x0000, 0x0000 }, /* R1222 */
+       { 0x0000, 0x0000 }, /* R1223 */
+       { 0x0000, 0x0000 }, /* R1224 */
+       { 0x0000, 0x0000 }, /* R1225 */
+       { 0x0000, 0x0000 }, /* R1226 */
+       { 0x0000, 0x0000 }, /* R1227 */
+       { 0x0000, 0x0000 }, /* R1228 */
+       { 0x0000, 0x0000 }, /* R1229 */
+       { 0x0000, 0x0000 }, /* R1230 */
+       { 0x0000, 0x0000 }, /* R1231 */
+       { 0x0000, 0x0000 }, /* R1232 */
+       { 0x0000, 0x0000 }, /* R1233 */
+       { 0x0000, 0x0000 }, /* R1234 */
+       { 0x0000, 0x0000 }, /* R1235 */
+       { 0x0000, 0x0000 }, /* R1236 */
+       { 0x0000, 0x0000 }, /* R1237 */
+       { 0x0000, 0x0000 }, /* R1238 */
+       { 0x0000, 0x0000 }, /* R1239 */
+       { 0x0000, 0x0000 }, /* R1240 */
+       { 0x0000, 0x0000 }, /* R1241 */
+       { 0x0000, 0x0000 }, /* R1242 */
+       { 0x0000, 0x0000 }, /* R1243 */
+       { 0x0000, 0x0000 }, /* R1244 */
+       { 0x0000, 0x0000 }, /* R1245 */
+       { 0x0000, 0x0000 }, /* R1246 */
+       { 0x0000, 0x0000 }, /* R1247 */
+       { 0x0000, 0x0000 }, /* R1248 */
+       { 0x0000, 0x0000 }, /* R1249 */
+       { 0x0000, 0x0000 }, /* R1250 */
+       { 0x0000, 0x0000 }, /* R1251 */
+       { 0x0000, 0x0000 }, /* R1252 */
+       { 0x0000, 0x0000 }, /* R1253 */
+       { 0x0000, 0x0000 }, /* R1254 */
+       { 0x0000, 0x0000 }, /* R1255 */
+       { 0x0000, 0x0000 }, /* R1256 */
+       { 0x0000, 0x0000 }, /* R1257 */
+       { 0x0000, 0x0000 }, /* R1258 */
+       { 0x0000, 0x0000 }, /* R1259 */
+       { 0x0000, 0x0000 }, /* R1260 */
+       { 0x0000, 0x0000 }, /* R1261 */
+       { 0x0000, 0x0000 }, /* R1262 */
+       { 0x0000, 0x0000 }, /* R1263 */
+       { 0x0000, 0x0000 }, /* R1264 */
+       { 0x0000, 0x0000 }, /* R1265 */
+       { 0x0000, 0x0000 }, /* R1266 */
+       { 0x0000, 0x0000 }, /* R1267 */
+       { 0x0000, 0x0000 }, /* R1268 */
+       { 0x0000, 0x0000 }, /* R1269 */
+       { 0x0000, 0x0000 }, /* R1270 */
+       { 0x0000, 0x0000 }, /* R1271 */
+       { 0x0000, 0x0000 }, /* R1272 */
+       { 0x0000, 0x0000 }, /* R1273 */
+       { 0x0000, 0x0000 }, /* R1274 */
+       { 0x0000, 0x0000 }, /* R1275 */
+       { 0x0000, 0x0000 }, /* R1276 */
+       { 0x0000, 0x0000 }, /* R1277 */
+       { 0x0000, 0x0000 }, /* R1278 */
+       { 0x0000, 0x0000 }, /* R1279 */
+       { 0x00FF, 0x01FF }, /* R1280  - AIF2 ADC Left Volume */
+       { 0x00FF, 0x01FF }, /* R1281  - AIF2 ADC Right Volume */
+       { 0x00FF, 0x01FF }, /* R1282  - AIF2 DAC Left Volume */
+       { 0x00FF, 0x01FF }, /* R1283  - AIF2 DAC Right Volume */
+       { 0x0000, 0x0000 }, /* R1284 */
+       { 0x0000, 0x0000 }, /* R1285 */
+       { 0x0000, 0x0000 }, /* R1286 */
+       { 0x0000, 0x0000 }, /* R1287 */
+       { 0x0000, 0x0000 }, /* R1288 */
+       { 0x0000, 0x0000 }, /* R1289 */
+       { 0x0000, 0x0000 }, /* R1290 */
+       { 0x0000, 0x0000 }, /* R1291 */
+       { 0x0000, 0x0000 }, /* R1292 */
+       { 0x0000, 0x0000 }, /* R1293 */
+       { 0x0000, 0x0000 }, /* R1294 */
+       { 0x0000, 0x0000 }, /* R1295 */
+       { 0xF800, 0xF800 }, /* R1296  - AIF2 ADC Filters */
+       { 0x0000, 0x0000 }, /* R1297 */
+       { 0x0000, 0x0000 }, /* R1298 */
+       { 0x0000, 0x0000 }, /* R1299 */
+       { 0x0000, 0x0000 }, /* R1300 */
+       { 0x0000, 0x0000 }, /* R1301 */
+       { 0x0000, 0x0000 }, /* R1302 */
+       { 0x0000, 0x0000 }, /* R1303 */
+       { 0x0000, 0x0000 }, /* R1304 */
+       { 0x0000, 0x0000 }, /* R1305 */
+       { 0x0000, 0x0000 }, /* R1306 */
+       { 0x0000, 0x0000 }, /* R1307 */
+       { 0x0000, 0x0000 }, /* R1308 */
+       { 0x0000, 0x0000 }, /* R1309 */
+       { 0x0000, 0x0000 }, /* R1310 */
+       { 0x0000, 0x0000 }, /* R1311 */
+       { 0x02B6, 0x02B6 }, /* R1312  - AIF2 DAC Filters (1) */
+       { 0x3F00, 0x3F00 }, /* R1313  - AIF2 DAC Filters (2) */
+       { 0x0000, 0x0000 }, /* R1314 */
+       { 0x0000, 0x0000 }, /* R1315 */
+       { 0x0000, 0x0000 }, /* R1316 */
+       { 0x0000, 0x0000 }, /* R1317 */
+       { 0x0000, 0x0000 }, /* R1318 */
+       { 0x0000, 0x0000 }, /* R1319 */
+       { 0x0000, 0x0000 }, /* R1320 */
+       { 0x0000, 0x0000 }, /* R1321 */
+       { 0x0000, 0x0000 }, /* R1322 */
+       { 0x0000, 0x0000 }, /* R1323 */
+       { 0x0000, 0x0000 }, /* R1324 */
+       { 0x0000, 0x0000 }, /* R1325 */
+       { 0x0000, 0x0000 }, /* R1326 */
+       { 0x0000, 0x0000 }, /* R1327 */
+       { 0x0000, 0x0000 }, /* R1328 */
+       { 0x0000, 0x0000 }, /* R1329 */
+       { 0x0000, 0x0000 }, /* R1330 */
+       { 0x0000, 0x0000 }, /* R1331 */
+       { 0x0000, 0x0000 }, /* R1332 */
+       { 0x0000, 0x0000 }, /* R1333 */
+       { 0x0000, 0x0000 }, /* R1334 */
+       { 0x0000, 0x0000 }, /* R1335 */
+       { 0x0000, 0x0000 }, /* R1336 */
+       { 0x0000, 0x0000 }, /* R1337 */
+       { 0x0000, 0x0000 }, /* R1338 */
+       { 0x0000, 0x0000 }, /* R1339 */
+       { 0x0000, 0x0000 }, /* R1340 */
+       { 0x0000, 0x0000 }, /* R1341 */
+       { 0x0000, 0x0000 }, /* R1342 */
+       { 0x0000, 0x0000 }, /* R1343 */
+       { 0xFFFF, 0xFFFF }, /* R1344  - AIF2 DRC (1) */
+       { 0x1FFF, 0x1FFF }, /* R1345  - AIF2 DRC (2) */
+       { 0xFFFF, 0xFFFF }, /* R1346  - AIF2 DRC (3) */
+       { 0x07FF, 0x07FF }, /* R1347  - AIF2 DRC (4) */
+       { 0x03FF, 0x03FF }, /* R1348  - AIF2 DRC (5) */
+       { 0x0000, 0x0000 }, /* R1349 */
+       { 0x0000, 0x0000 }, /* R1350 */
+       { 0x0000, 0x0000 }, /* R1351 */
+       { 0x0000, 0x0000 }, /* R1352 */
+       { 0x0000, 0x0000 }, /* R1353 */
+       { 0x0000, 0x0000 }, /* R1354 */
+       { 0x0000, 0x0000 }, /* R1355 */
+       { 0x0000, 0x0000 }, /* R1356 */
+       { 0x0000, 0x0000 }, /* R1357 */
+       { 0x0000, 0x0000 }, /* R1358 */
+       { 0x0000, 0x0000 }, /* R1359 */
+       { 0x0000, 0x0000 }, /* R1360 */
+       { 0x0000, 0x0000 }, /* R1361 */
+       { 0x0000, 0x0000 }, /* R1362 */
+       { 0x0000, 0x0000 }, /* R1363 */
+       { 0x0000, 0x0000 }, /* R1364 */
+       { 0x0000, 0x0000 }, /* R1365 */
+       { 0x0000, 0x0000 }, /* R1366 */
+       { 0x0000, 0x0000 }, /* R1367 */
+       { 0x0000, 0x0000 }, /* R1368 */
+       { 0x0000, 0x0000 }, /* R1369 */
+       { 0x0000, 0x0000 }, /* R1370 */
+       { 0x0000, 0x0000 }, /* R1371 */
+       { 0x0000, 0x0000 }, /* R1372 */
+       { 0x0000, 0x0000 }, /* R1373 */
+       { 0x0000, 0x0000 }, /* R1374 */
+       { 0x0000, 0x0000 }, /* R1375 */
+       { 0x0000, 0x0000 }, /* R1376 */
+       { 0x0000, 0x0000 }, /* R1377 */
+       { 0x0000, 0x0000 }, /* R1378 */
+       { 0x0000, 0x0000 }, /* R1379 */
+       { 0x0000, 0x0000 }, /* R1380 */
+       { 0x0000, 0x0000 }, /* R1381 */
+       { 0x0000, 0x0000 }, /* R1382 */
+       { 0x0000, 0x0000 }, /* R1383 */
+       { 0x0000, 0x0000 }, /* R1384 */
+       { 0x0000, 0x0000 }, /* R1385 */
+       { 0x0000, 0x0000 }, /* R1386 */
+       { 0x0000, 0x0000 }, /* R1387 */
+       { 0x0000, 0x0000 }, /* R1388 */
+       { 0x0000, 0x0000 }, /* R1389 */
+       { 0x0000, 0x0000 }, /* R1390 */
+       { 0x0000, 0x0000 }, /* R1391 */
+       { 0x0000, 0x0000 }, /* R1392 */
+       { 0x0000, 0x0000 }, /* R1393 */
+       { 0x0000, 0x0000 }, /* R1394 */
+       { 0x0000, 0x0000 }, /* R1395 */
+       { 0x0000, 0x0000 }, /* R1396 */
+       { 0x0000, 0x0000 }, /* R1397 */
+       { 0x0000, 0x0000 }, /* R1398 */
+       { 0x0000, 0x0000 }, /* R1399 */
+       { 0x0000, 0x0000 }, /* R1400 */
+       { 0x0000, 0x0000 }, /* R1401 */
+       { 0x0000, 0x0000 }, /* R1402 */
+       { 0x0000, 0x0000 }, /* R1403 */
+       { 0x0000, 0x0000 }, /* R1404 */
+       { 0x0000, 0x0000 }, /* R1405 */
+       { 0x0000, 0x0000 }, /* R1406 */
+       { 0x0000, 0x0000 }, /* R1407 */
+       { 0xFFFF, 0xFFFF }, /* R1408  - AIF2 EQ Gains (1) */
+       { 0xFFC0, 0xFFC0 }, /* R1409  - AIF2 EQ Gains (2) */
+       { 0xFFFF, 0xFFFF }, /* R1410  - AIF2 EQ Band 1 A */
+       { 0xFFFF, 0xFFFF }, /* R1411  - AIF2 EQ Band 1 B */
+       { 0xFFFF, 0xFFFF }, /* R1412  - AIF2 EQ Band 1 PG */
+       { 0xFFFF, 0xFFFF }, /* R1413  - AIF2 EQ Band 2 A */
+       { 0xFFFF, 0xFFFF }, /* R1414  - AIF2 EQ Band 2 B */
+       { 0xFFFF, 0xFFFF }, /* R1415  - AIF2 EQ Band 2 C */
+       { 0xFFFF, 0xFFFF }, /* R1416  - AIF2 EQ Band 2 PG */
+       { 0xFFFF, 0xFFFF }, /* R1417  - AIF2 EQ Band 3 A */
+       { 0xFFFF, 0xFFFF }, /* R1418  - AIF2 EQ Band 3 B */
+       { 0xFFFF, 0xFFFF }, /* R1419  - AIF2 EQ Band 3 C */
+       { 0xFFFF, 0xFFFF }, /* R1420  - AIF2 EQ Band 3 PG */
+       { 0xFFFF, 0xFFFF }, /* R1421  - AIF2 EQ Band 4 A */
+       { 0xFFFF, 0xFFFF }, /* R1422  - AIF2 EQ Band 4 B */
+       { 0xFFFF, 0xFFFF }, /* R1423  - AIF2 EQ Band 4 C */
+       { 0xFFFF, 0xFFFF }, /* R1424  - AIF2 EQ Band 4 PG */
+       { 0xFFFF, 0xFFFF }, /* R1425  - AIF2 EQ Band 5 A */
+       { 0xFFFF, 0xFFFF }, /* R1426  - AIF2 EQ Band 5 B */
+       { 0xFFFF, 0xFFFF }, /* R1427  - AIF2 EQ Band 5 PG */
+       { 0x0000, 0x0000 }, /* R1428 */
+       { 0x0000, 0x0000 }, /* R1429 */
+       { 0x0000, 0x0000 }, /* R1430 */
+       { 0x0000, 0x0000 }, /* R1431 */
+       { 0x0000, 0x0000 }, /* R1432 */
+       { 0x0000, 0x0000 }, /* R1433 */
+       { 0x0000, 0x0000 }, /* R1434 */
+       { 0x0000, 0x0000 }, /* R1435 */
+       { 0x0000, 0x0000 }, /* R1436 */
+       { 0x0000, 0x0000 }, /* R1437 */
+       { 0x0000, 0x0000 }, /* R1438 */
+       { 0x0000, 0x0000 }, /* R1439 */
+       { 0x0000, 0x0000 }, /* R1440 */
+       { 0x0000, 0x0000 }, /* R1441 */
+       { 0x0000, 0x0000 }, /* R1442 */
+       { 0x0000, 0x0000 }, /* R1443 */
+       { 0x0000, 0x0000 }, /* R1444 */
+       { 0x0000, 0x0000 }, /* R1445 */
+       { 0x0000, 0x0000 }, /* R1446 */
+       { 0x0000, 0x0000 }, /* R1447 */
+       { 0x0000, 0x0000 }, /* R1448 */
+       { 0x0000, 0x0000 }, /* R1449 */
+       { 0x0000, 0x0000 }, /* R1450 */
+       { 0x0000, 0x0000 }, /* R1451 */
+       { 0x0000, 0x0000 }, /* R1452 */
+       { 0x0000, 0x0000 }, /* R1453 */
+       { 0x0000, 0x0000 }, /* R1454 */
+       { 0x0000, 0x0000 }, /* R1455 */
+       { 0x0000, 0x0000 }, /* R1456 */
+       { 0x0000, 0x0000 }, /* R1457 */
+       { 0x0000, 0x0000 }, /* R1458 */
+       { 0x0000, 0x0000 }, /* R1459 */
+       { 0x0000, 0x0000 }, /* R1460 */
+       { 0x0000, 0x0000 }, /* R1461 */
+       { 0x0000, 0x0000 }, /* R1462 */
+       { 0x0000, 0x0000 }, /* R1463 */
+       { 0x0000, 0x0000 }, /* R1464 */
+       { 0x0000, 0x0000 }, /* R1465 */
+       { 0x0000, 0x0000 }, /* R1466 */
+       { 0x0000, 0x0000 }, /* R1467 */
+       { 0x0000, 0x0000 }, /* R1468 */
+       { 0x0000, 0x0000 }, /* R1469 */
+       { 0x0000, 0x0000 }, /* R1470 */
+       { 0x0000, 0x0000 }, /* R1471 */
+       { 0x0000, 0x0000 }, /* R1472 */
+       { 0x0000, 0x0000 }, /* R1473 */
+       { 0x0000, 0x0000 }, /* R1474 */
+       { 0x0000, 0x0000 }, /* R1475 */
+       { 0x0000, 0x0000 }, /* R1476 */
+       { 0x0000, 0x0000 }, /* R1477 */
+       { 0x0000, 0x0000 }, /* R1478 */
+       { 0x0000, 0x0000 }, /* R1479 */
+       { 0x0000, 0x0000 }, /* R1480 */
+       { 0x0000, 0x0000 }, /* R1481 */
+       { 0x0000, 0x0000 }, /* R1482 */
+       { 0x0000, 0x0000 }, /* R1483 */
+       { 0x0000, 0x0000 }, /* R1484 */
+       { 0x0000, 0x0000 }, /* R1485 */
+       { 0x0000, 0x0000 }, /* R1486 */
+       { 0x0000, 0x0000 }, /* R1487 */
+       { 0x0000, 0x0000 }, /* R1488 */
+       { 0x0000, 0x0000 }, /* R1489 */
+       { 0x0000, 0x0000 }, /* R1490 */
+       { 0x0000, 0x0000 }, /* R1491 */
+       { 0x0000, 0x0000 }, /* R1492 */
+       { 0x0000, 0x0000 }, /* R1493 */
+       { 0x0000, 0x0000 }, /* R1494 */
+       { 0x0000, 0x0000 }, /* R1495 */
+       { 0x0000, 0x0000 }, /* R1496 */
+       { 0x0000, 0x0000 }, /* R1497 */
+       { 0x0000, 0x0000 }, /* R1498 */
+       { 0x0000, 0x0000 }, /* R1499 */
+       { 0x0000, 0x0000 }, /* R1500 */
+       { 0x0000, 0x0000 }, /* R1501 */
+       { 0x0000, 0x0000 }, /* R1502 */
+       { 0x0000, 0x0000 }, /* R1503 */
+       { 0x0000, 0x0000 }, /* R1504 */
+       { 0x0000, 0x0000 }, /* R1505 */
+       { 0x0000, 0x0000 }, /* R1506 */
+       { 0x0000, 0x0000 }, /* R1507 */
+       { 0x0000, 0x0000 }, /* R1508 */
+       { 0x0000, 0x0000 }, /* R1509 */
+       { 0x0000, 0x0000 }, /* R1510 */
+       { 0x0000, 0x0000 }, /* R1511 */
+       { 0x0000, 0x0000 }, /* R1512 */
+       { 0x0000, 0x0000 }, /* R1513 */
+       { 0x0000, 0x0000 }, /* R1514 */
+       { 0x0000, 0x0000 }, /* R1515 */
+       { 0x0000, 0x0000 }, /* R1516 */
+       { 0x0000, 0x0000 }, /* R1517 */
+       { 0x0000, 0x0000 }, /* R1518 */
+       { 0x0000, 0x0000 }, /* R1519 */
+       { 0x0000, 0x0000 }, /* R1520 */
+       { 0x0000, 0x0000 }, /* R1521 */
+       { 0x0000, 0x0000 }, /* R1522 */
+       { 0x0000, 0x0000 }, /* R1523 */
+       { 0x0000, 0x0000 }, /* R1524 */
+       { 0x0000, 0x0000 }, /* R1525 */
+       { 0x0000, 0x0000 }, /* R1526 */
+       { 0x0000, 0x0000 }, /* R1527 */
+       { 0x0000, 0x0000 }, /* R1528 */
+       { 0x0000, 0x0000 }, /* R1529 */
+       { 0x0000, 0x0000 }, /* R1530 */
+       { 0x0000, 0x0000 }, /* R1531 */
+       { 0x0000, 0x0000 }, /* R1532 */
+       { 0x0000, 0x0000 }, /* R1533 */
+       { 0x0000, 0x0000 }, /* R1534 */
+       { 0x0000, 0x0000 }, /* R1535 */
+       { 0x01EF, 0x01EF }, /* R1536  - DAC1 Mixer Volumes */
+       { 0x0037, 0x0037 }, /* R1537  - DAC1 Left Mixer Routing */
+       { 0x0037, 0x0037 }, /* R1538  - DAC1 Right Mixer Routing */
+       { 0x01EF, 0x01EF }, /* R1539  - DAC2 Mixer Volumes */
+       { 0x0037, 0x0037 }, /* R1540  - DAC2 Left Mixer Routing */
+       { 0x0037, 0x0037 }, /* R1541  - DAC2 Right Mixer Routing */
+       { 0x0003, 0x0003 }, /* R1542  - AIF1 ADC1 Left Mixer Routing */
+       { 0x0003, 0x0003 }, /* R1543  - AIF1 ADC1 Right Mixer Routing */
+       { 0x0003, 0x0003 }, /* R1544  - AIF1 ADC2 Left Mixer Routing */
+       { 0x0003, 0x0003 }, /* R1545  - AIF1 ADC2 Right mixer Routing */
+       { 0x0000, 0x0000 }, /* R1546 */
+       { 0x0000, 0x0000 }, /* R1547 */
+       { 0x0000, 0x0000 }, /* R1548 */
+       { 0x0000, 0x0000 }, /* R1549 */
+       { 0x0000, 0x0000 }, /* R1550 */
+       { 0x0000, 0x0000 }, /* R1551 */
+       { 0x02FF, 0x03FF }, /* R1552  - DAC1 Left Volume */
+       { 0x02FF, 0x03FF }, /* R1553  - DAC1 Right Volume */
+       { 0x02FF, 0x03FF }, /* R1554  - DAC2 Left Volume */
+       { 0x02FF, 0x03FF }, /* R1555  - DAC2 Right Volume */
+       { 0x0003, 0x0003 }, /* R1556  - DAC Softmute */
+       { 0x0000, 0x0000 }, /* R1557 */
+       { 0x0000, 0x0000 }, /* R1558 */
+       { 0x0000, 0x0000 }, /* R1559 */
+       { 0x0000, 0x0000 }, /* R1560 */
+       { 0x0000, 0x0000 }, /* R1561 */
+       { 0x0000, 0x0000 }, /* R1562 */
+       { 0x0000, 0x0000 }, /* R1563 */
+       { 0x0000, 0x0000 }, /* R1564 */
+       { 0x0000, 0x0000 }, /* R1565 */
+       { 0x0000, 0x0000 }, /* R1566 */
+       { 0x0000, 0x0000 }, /* R1567 */
+       { 0x0003, 0x0003 }, /* R1568  - Oversampling */
+       { 0x03C3, 0x03C3 }, /* R1569  - Sidetone */
 };
 
 static int wm8994_readable(unsigned int reg)
@@ -1902,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
        return snd_soc_put_volsw(kcontrol, ucontrol);
 }
 
-
-
 static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
 {
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -1942,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994_pdata *pdata = wm8994->pdata;
        int drc = wm8994_get_drc(kcontrol->id.name);
        int value = ucontrol->value.integer.value[0];
@@ -2045,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);  
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994_pdata *pdata = wm8994->pdata;
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
        int value = ucontrol->value.integer.value[0];
@@ -2067,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
 
        ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
@@ -2075,6 +2071,22 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static const char *aifdac_src_text[] = {
+       "Left", "Right"
+};
+
+static const struct soc_enum aif1dacl_src =
+       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aifdac_src_text);
+
+static const struct soc_enum aif1dacr_src =
+       SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aifdac_src_text);
+
+static const struct soc_enum aif2dacl_src =
+       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aifdac_src_text);
+
+static const struct soc_enum aif2dacr_src =
+       SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aifdac_src_text);
+
 static const struct snd_kcontrol_new wm8994_snd_controls[] = {
 SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
                 WM8994_AIF1_ADC1_RIGHT_VOLUME,
@@ -2086,6 +2098,11 @@ SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
                 WM8994_AIF2_ADC_RIGHT_VOLUME,
                 1, 119, 0, digital_tlv),
 
+SOC_ENUM("AIF1DACL Source", aif1dacl_src),
+SOC_ENUM("AIF1DACR Source", aif1dacr_src),
+SOC_ENUM("AIF2DACL Source", aif1dacl_src),
+SOC_ENUM("AIF2DACR Source", aif1dacr_src),
+
 SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
                 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
 SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
@@ -2881,10 +2898,9 @@ static int wm8994_get_fll_config(struct fll_div *fll,
        return 0;
 }
 
-static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
+static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
                          unsigned int freq_in, unsigned int freq_out)
 {
-       struct snd_soc_codec *codec = dai->codec;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int reg_offset, ret;
        struct fll_div fll;
@@ -2995,8 +3011,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
        return 0;
 }
 
+
 static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
 
+static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
+                         unsigned int freq_in, unsigned int freq_out)
+{
+       return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out);
+}
+
 static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
                int clk_id, unsigned int freq, int dir)
 {
@@ -3313,20 +3336,24 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                bclk_reg = WM8994_AIF1_BCLK;
                rate_reg = WM8994_AIF1_RATE;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
-                   wm8994->lrclk_shared[0])
+                   wm8994->lrclk_shared[0]) {
                        lrclk_reg = WM8994_AIF1DAC_LRCLK;
-               else
+               } else {
                        lrclk_reg = WM8994_AIF1ADC_LRCLK;
+                       dev_dbg(codec->dev, "AIF1 using split LRCLK\n");
+               }
                break;
        case 2:
                aif1_reg = WM8994_AIF2_CONTROL_1;
                bclk_reg = WM8994_AIF2_BCLK;
                rate_reg = WM8994_AIF2_RATE;
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
-                   wm8994->lrclk_shared[1])
+                   wm8994->lrclk_shared[1]) {
                        lrclk_reg = WM8994_AIF2DAC_LRCLK;
-               else
+               } else {
                        lrclk_reg = WM8994_AIF2ADC_LRCLK;
+                       dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
+               }
                break;
        default:
                return -EINVAL;
@@ -3491,7 +3518,7 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
 #define WM8994_RATES SNDRV_PCM_RATE_8000_96000
 
 #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
-                       SNDRV_PCM_FMTBIT_S24_LE)
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
 static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
        .set_sysclk     = wm8994_set_dai_sysclk,
@@ -3515,9 +3542,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
        .set_tristate   = wm8994_set_tristate,
 };
 
-struct snd_soc_dai wm8994_dai[] = {
+static struct snd_soc_dai_driver wm8994_dai[] = {
        {
-               .name = "WM8994 AIF1",
+               .name = "wm8994-aif1",
                .id = 1,
                .playback = {
                        .stream_name = "AIF1 Playback",
@@ -3536,7 +3563,7 @@ struct snd_soc_dai wm8994_dai[] = {
                .ops = &wm8994_aif1_dai_ops,
        },
        {
-               .name = "WM8994 AIF2",
+               .name = "wm8994-aif2",
                .id = 2,
                .playback = {
                        .stream_name = "AIF2 Playback",
@@ -3555,7 +3582,7 @@ struct snd_soc_dai wm8994_dai[] = {
                .ops = &wm8994_aif2_dai_ops,
        },
        {
-               .name = "WM8994 AIF3",
+               .name = "wm8994-aif3",
                .id = 3,
                .playback = {
                        .stream_name = "AIF3 Playback",
@@ -3574,20 +3601,17 @@ struct snd_soc_dai wm8994_dai[] = {
                .ops = &wm8994_aif3_dai_ops,
        }
 };
-EXPORT_SYMBOL_GPL(wm8994_dai);
 
 #ifdef CONFIG_PM
-static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        int i, ret;
 
        for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
                memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
                       sizeof(struct fll_config));
-               ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0);
+               ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0);
                if (ret < 0)
                        dev_warn(codec->dev, "Failed to stop FLL%d: %d\n",
                                 i + 1, ret);
@@ -3598,10 +3622,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-static int wm8994_resume(struct platform_device *pdev)
+static int wm8994_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        u16 *reg_cache = codec->reg_cache;
        int i, ret;
@@ -3630,7 +3652,7 @@ static int wm8994_resume(struct platform_device *pdev)
                if (!wm8994->fll_suspend[i].out)
                        continue;
 
-               ret = wm8994_set_fll(&codec->dai[0], i + 1,
+               ret = _wm8994_set_fll(codec, i + 1,
                                     wm8994->fll_suspend[i].src,
                                     wm8994->fll_suspend[i].in,
                                     wm8994->fll_suspend[i].out);
@@ -3648,7 +3670,7 @@ static int wm8994_resume(struct platform_device *pdev)
 
 static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
 {
-       struct snd_soc_codec *codec = &wm8994->codec;
+       struct snd_soc_codec *codec = wm8994->codec;
        struct wm8994_pdata *pdata = wm8994->pdata;
        struct snd_kcontrol_new controls[] = {
                SOC_ENUM_EXT("AIF1.1 EQ Mode",
@@ -3706,16 +3728,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
        wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
        wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
 
-       ret = snd_soc_add_controls(&wm8994->codec, controls,
+       ret = snd_soc_add_controls(wm8994->codec, controls,
                                   ARRAY_SIZE(controls));
        if (ret != 0)
-               dev_err(wm8994->codec.dev,
+               dev_err(wm8994->codec->dev,
                        "Failed to add ReTune Mobile controls: %d\n", ret);
 }
 
 static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 {
-       struct snd_soc_codec *codec = &wm8994->codec;
+       struct snd_soc_codec *codec = wm8994->codec;
        struct wm8994_pdata *pdata = wm8994->pdata;
        int ret, i;
 
@@ -3747,7 +3769,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
                wm8994->drc_texts = kmalloc(sizeof(char *)
                                            * pdata->num_drc_cfgs, GFP_KERNEL);
                if (!wm8994->drc_texts) {
-                       dev_err(wm8994->codec.dev,
+                       dev_err(wm8994->codec->dev,
                                "Failed to allocate %d DRC config texts\n",
                                pdata->num_drc_cfgs);
                        return;
@@ -3759,10 +3781,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
                wm8994->drc_enum.max = pdata->num_drc_cfgs;
                wm8994->drc_enum.texts = wm8994->drc_texts;
 
-               ret = snd_soc_add_controls(&wm8994->codec, controls,
+               ret = snd_soc_add_controls(wm8994->codec, controls,
                                           ARRAY_SIZE(controls));
                if (ret != 0)
-                       dev_err(wm8994->codec.dev,
+                       dev_err(wm8994->codec->dev,
                                "Failed to add DRC mode controls: %d\n", ret);
 
                for (i = 0; i < WM8994_NUM_DRC; i++)
@@ -3775,62 +3797,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
        if (pdata->num_retune_mobile_cfgs)
                wm8994_handle_retune_mobile_pdata(wm8994);
        else
-               snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls,
+               snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
                                     ARRAY_SIZE(wm8994_eq_controls));
 }
 
-static int wm8994_probe(struct platform_device *pdev)
-{
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
-
-       if (wm8994_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
-       }
-
-       socdev->card->codec = wm8994_codec;
-       codec = wm8994_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);
-               return ret;
-       }
-
-       wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec));
-
-       wm_hubs_add_analogue_controls(codec);
-       snd_soc_add_controls(codec, wm8994_snd_controls,
-                            ARRAY_SIZE(wm8994_snd_controls));
-       snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
-                                 ARRAY_SIZE(wm8994_dapm_widgets));
-       wm_hubs_add_analogue_routes(codec, 0, 0);
-       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
-
-       return 0;
-}
-
-static int wm8994_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_wm8994 = {
-       .probe =        wm8994_probe,
-       .remove =       wm8994_remove,
-       .suspend =      wm8994_suspend,
-       .resume =       wm8994_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
-
 /**
  * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
  *
@@ -3842,7 +3812,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
  *
  * Enable microphone detection via IRQ on the WM8994.  If GPIOs are
  * being used to bring out signals to the processor then only platform
- * data configuration is needed for WM8903 and processor GPIOs should
+ * data configuration is needed for WM8994 and processor GPIOs should
  * be configured using snd_soc_jack_add_gpios() instead.
  *
  * Configuration of detection levels is available via the micbias1_lvl
@@ -3889,7 +3859,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect);
 static irqreturn_t wm8994_mic_irq(int irq, void *data)
 {
        struct wm8994_priv *priv = data;
-       struct snd_soc_codec *codec = &priv->codec;
+       struct snd_soc_codec *codec = priv->codec;
        int reg;
        int report;
 
@@ -3921,46 +3891,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static int wm8994_codec_probe(struct platform_device *pdev)
+static int wm8994_codec_probe(struct snd_soc_codec *codec)
 {
-       int ret;
        struct wm8994_priv *wm8994;
-       struct snd_soc_codec *codec;
-       int i;
+       int ret, i;
 
-       if (wm8994_codec) {
-               dev_err(&pdev->dev, "Another WM8994 is registered\n");
-               return -EINVAL;
-       }
+       codec->control_data = dev_get_drvdata(codec->dev->parent);
 
        wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
-       if (!wm8994) {
-               dev_err(&pdev->dev, "Failed to allocate private data\n");
+       if (wm8994 == NULL)
                return -ENOMEM;
-       }
-
-       codec = &wm8994->codec;
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
        snd_soc_codec_set_drvdata(codec, wm8994);
-       codec->control_data = dev_get_drvdata(pdev->dev.parent);
-       codec->name = "WM8994";
-       codec->owner = THIS_MODULE;
-       codec->read = wm8994_read;
-       codec->write = wm8994_write;
-       codec->readable_register = wm8994_readable;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm8994_set_bias_level;
-       codec->dai = &wm8994_dai[0];
-       codec->num_dai = 3;
-       codec->reg_cache_size = WM8994_MAX_REGISTER;
-       codec->reg_cache = &wm8994->reg_cache;
-       codec->dev = &pdev->dev;
-
-       wm8994->pdata = pdev->dev.parent->platform_data;
+
+       wm8994->pdata = dev_get_platdata(codec->dev->parent);
+       wm8994->codec = codec;
 
        /* Fill the cache with physical values we inherited; don't reset */
        ret = wm8994_bulk_read(codec->control_data, 0,
@@ -3996,25 +3940,25 @@ static int wm8994_codec_probe(struct platform_device *pdev)
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
                                 wm8994_mic_irq, "Mic 1 detect", wm8994);
        if (ret != 0)
-               dev_warn(&pdev->dev,
+               dev_warn(codec->dev,
                         "Failed to request Mic1 detect IRQ: %d\n", ret);
 
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
                                 wm8994_mic_irq, "Mic 1 short", wm8994);
        if (ret != 0)
-               dev_warn(&pdev->dev,
+               dev_warn(codec->dev,
                         "Failed to request Mic1 short IRQ: %d\n", ret);
 
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
                                 wm8994_mic_irq, "Mic 2 detect", wm8994);
        if (ret != 0)
-               dev_warn(&pdev->dev,
+               dev_warn(codec->dev,
                         "Failed to request Mic2 detect IRQ: %d\n", ret);
 
        ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
                                 wm8994_mic_irq, "Mic 2 short", wm8994);
        if (ret != 0)
-               dev_warn(&pdev->dev,
+               dev_warn(codec->dev,
                         "Failed to request Mic2 short IRQ: %d\n", ret);
 
        /* Remember if AIFnLRCLK is configured as a GPIO.  This should be
@@ -4045,13 +3989,8 @@ static int wm8994_codec_probe(struct platform_device *pdev)
                wm8994->lrclk_shared[1] = 0;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++)
-               wm8994_dai[i].dev = codec->dev;
-
        wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       wm8994_codec = codec;
-
        /* Latch volume updates (right only; we always do left then right). */
        snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
                            WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
@@ -4088,24 +4027,18 @@ static int wm8994_codec_probe(struct platform_device *pdev)
 
        wm8994_update_class_w(codec);
 
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err_irq;
-       }
-
-       ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
-               goto err_codec;
-       }
+       wm8994_handle_pdata(wm8994);
 
-       platform_set_drvdata(pdev, wm8994);
+       wm_hubs_add_analogue_controls(codec);
+       snd_soc_add_controls(codec, wm8994_snd_controls,
+                            ARRAY_SIZE(wm8994_snd_controls));
+       snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
+                                 ARRAY_SIZE(wm8994_dapm_widgets));
+       wm_hubs_add_analogue_routes(codec, 0, 0);
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
 
        return 0;
 
-err_codec:
-       snd_soc_unregister_codec(codec);
 err_irq:
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
@@ -4116,31 +4049,50 @@ err:
        return ret;
 }
 
-static int __devexit wm8994_codec_remove(struct platform_device *pdev)
+static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 {
-       struct wm8994_priv *wm8994 = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = &wm8994->codec;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
        wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
-       snd_soc_unregister_codec(&wm8994->codec);
+
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
        wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
        kfree(wm8994);
-       wm8994_codec = NULL;
 
        return 0;
 }
 
+static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
+       .probe =        wm8994_codec_probe,
+       .remove =       wm8994_codec_remove,
+       .suspend =      wm8994_suspend,
+       .resume =       wm8994_resume,
+       .read = wm8994_read,
+       .write = wm8994_write,
+       .set_bias_level = wm8994_set_bias_level,
+};
+
+static int __devinit wm8994_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
+                       wm8994_dai, ARRAY_SIZE(wm8994_dai));
+}
+
+static int __devexit wm8994_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
 static struct platform_driver wm8994_codec_driver = {
        .driver = {
                   .name = "wm8994-codec",
                   .owner = THIS_MODULE,
                   },
-       .probe = wm8994_codec_probe,
-       .remove = __devexit_p(wm8994_codec_remove),
+       .probe = wm8994_probe,
+       .remove = __devexit_p(wm8994_remove),
 };
 
 static __init int wm8994_init(void)
index 2e0ca67..d8dce26 100644 (file)
@@ -11,9 +11,6 @@
 
 #include <sound/soc.h>
 
-extern struct snd_soc_codec_device soc_codec_dev_wm8994;
-extern struct snd_soc_dai wm8994_dai[];
-
 /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
 #define WM8994_SYSCLK_MCLK1 1
 #define WM8994_SYSCLK_MCLK2 2
index 76b37ff..ecc7c37 100644 (file)
@@ -156,7 +156,8 @@ static struct {
 };
 
 struct wm9081_priv {
-       struct snd_soc_codec codec;
+       enum snd_soc_control_type control_type;
+       void *control_data;
        u16 reg_cache[WM9081_MAX_REGISTER + 1];
        int sysclk_source;
        int mclk_rate;
@@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = {
 /* We report two channels because the CODEC processes a stereo signal, even
  * though it is only capable of handling a mono output.
  */
-struct snd_soc_dai wm9081_dai = {
-       .name = "WM9081",
+static struct snd_soc_dai_driver wm9081_dai = {
+       .name = "wm9081-hifi",
        .playback = {
                .stream_name = "HiFi Playback",
                .channels_min = 1,
@@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = {
        },
        .ops = &wm9081_dai_ops,
 };
-EXPORT_SYMBOL_GPL(wm9081_dai);
 
-
-static struct snd_soc_codec *wm9081_codec;
-
-static int wm9081_probe(struct platform_device *pdev)
+static int wm9081_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       struct wm9081_priv *wm9081;
-       int ret = 0;
+       struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
+       int ret;
+       u16 reg;
 
-       if (wm9081_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       codec->control_data = wm9081->control_data;
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
        }
 
-       socdev->card->codec = wm9081_codec;
-       codec = wm9081_codec;
-       wm9081 = snd_soc_codec_get_drvdata(codec);
+       reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
+       if (reg != 0x9081) {
+               dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
+               ret = -EINVAL;
+               return ret;
+       }
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       ret = wm9081_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
-               goto pcm_err;
+               dev_err(codec->dev, "Failed to issue reset\n");
+               return ret;
        }
 
+       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_SPKPGAZC);
+
        snd_soc_add_controls(codec, wm9081_snd_controls,
                             ARRAY_SIZE(wm9081_snd_controls));
        if (!wm9081->retune) {
@@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev)
        snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
 
        return ret;
-
-pcm_err:
-       return ret;
 }
 
-static int wm9081_remove(struct platform_device *pdev)
+static int wm9081_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-
+       wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
 #ifdef CONFIG_PM
-static int wm9081_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm9081_resume(struct platform_device *pdev)
+static int wm9081_resume(struct snd_soc_codec *codec)
 {
-       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++) {
+       for (i = 0; i < codec->driver->reg_cache_size; i++) {
                if (i == WM9081_SOFTWARE_RESET)
                        continue;
 
@@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev)
 #define wm9081_resume NULL
 #endif
 
-struct snd_soc_codec_device soc_codec_dev_wm9081 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
        .probe =        wm9081_probe,
        .remove =       wm9081_remove,
        .suspend =      wm9081_suspend,
        .resume =       wm9081_resume,
+       .set_bias_level = wm9081_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm9081_reg_defaults,
+       .volatile_register = wm9081_volatile_register,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
-
-static int wm9081_register(struct wm9081_priv *wm9081,
-                          enum snd_soc_control_type control)
-{
-       struct snd_soc_codec *codec = &wm9081->codec;
-       int ret;
-       u16 reg;
-
-       if (wm9081_codec) {
-               dev_err(codec->dev, "Another WM9081 is registered\n");
-               ret = -EINVAL;
-               goto err;
-       }
-
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       snd_soc_codec_set_drvdata(codec, wm9081);
-       codec->name = "WM9081";
-       codec->owner = THIS_MODULE;
-       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);
-               goto err;
-       }
-
-       reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
-       if (reg != 0x9081) {
-               dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = wm9081_reset(codec);
-       if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               goto err;
-       }
-
-       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_SPKPGAZC);
-
-       wm9081_dai.dev = codec->dev;
-
-       wm9081_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(&wm9081_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(wm9081);
-       return ret;
-}
-
-static void wm9081_unregister(struct wm9081_priv *wm9081)
-{
-       wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
-       snd_soc_unregister_dai(&wm9081_dai);
-       snd_soc_unregister_codec(&wm9081->codec);
-       kfree(wm9081);
-       wm9081_codec = NULL;
-}
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm9081_priv *wm9081;
-       struct snd_soc_codec *codec;
+       int ret;
 
        wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
        if (wm9081 == NULL)
                return -ENOMEM;
 
-       codec = &wm9081->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
-       wm9081->retune = i2c->dev.platform_data;
-
        i2c_set_clientdata(i2c, wm9081);
-       codec->control_data = i2c;
-
-       codec->dev = &i2c->dev;
+       wm9081->control_data = i2c;
 
-       return wm9081_register(wm9081, SND_SOC_I2C);
+       ret = snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm9081, &wm9081_dai, 1);
+       if (ret < 0)
+               kfree(wm9081);
+       return ret;
 }
 
 static __devexit int wm9081_i2c_remove(struct i2c_client *client)
 {
-       struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
-       wm9081_unregister(wm9081);
+       snd_soc_unregister_codec(&client->dev);
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
@@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
 
 static struct i2c_driver wm9081_i2c_driver = {
        .driver = {
-               .name = "wm9081",
+               .name = "wm9081-codec",
                .owner = THIS_MODULE,
        },
        .probe =    wm9081_i2c_probe,
        .remove =   __devexit_p(wm9081_i2c_remove),
        .id_table = wm9081_i2c_id,
 };
+#endif
 
 static int __init wm9081_modinit(void)
 {
-       int ret;
-
+       int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm9081_i2c_driver);
        if (ret != 0) {
                printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
                       ret);
        }
-
+#endif
        return ret;
 }
 module_init(wm9081_modinit);
 
 static void __exit wm9081_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        i2c_del_driver(&wm9081_i2c_driver);
+#endif
 }
 module_exit(wm9081_exit);
 
index 42d3bc7..871cccb 100644 (file)
@@ -15,9 +15,6 @@
 
 #include <sound/soc.h>
 
-extern struct snd_soc_dai wm9081_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm9081;
-
 /*
  * SYSCLK sources
  */
index 1592250..7a18254 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "wm9090.h"
 
-static struct snd_soc_codec *wm9090_codec;
-
 static const u16 wm9090_reg_defaults[] = {
        0x9093,     /* R0   - Software Reset */
        0x0006,     /* R1   - Power Management (1) */
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = {
 
 /* This struct is used to save the context */
 struct wm9090_priv {
-       /* We're not really registering as a CODEC since ASoC core
-        * does not yet support multiple CODECs but having the CODEC
-        * structure means we can reuse some of the ASoC core
-        * features.
-        */
-       struct snd_soc_codec codec;
        struct mutex mutex;
        u16 reg_cache[WM9090_MAX_REGISTER + 1];
        struct wm9090_platform_data pdata;
+       void *control_data;
 };
 
 static int wm9090_volatile(unsigned int reg)
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Restore the register cache */
-                       for (i = 1; i < codec->reg_cache_size; i++) {
+                       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                                if (reg_cache[i] == wm9090_reg_defaults[i])
                                        continue;
                                if (wm9090_volatile(i))
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9090_probe(struct platform_device *pdev)
+static int wm9090_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
-       int ret = 0;
+       struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+       int ret;
 
-       if (wm9090_codec == NULL) {
-               dev_err(&pdev->dev, "Codec device not registered\n");
-               return -ENODEV;
+       codec->control_data = wm9090->control_data;
+       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);
+               return ret;
        }
 
-       socdev->card->codec = wm9090_codec;
-       codec = wm9090_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;
+       ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
+       if (ret < 0)
+               return ret;
+       if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
+               dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
+               return -EINVAL;
        }
 
+       ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Configure some defaults; they will be written out when we
+        * bring the bias up.
+        */
+       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+               | WM9090_IN1A_ZC;
+       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+               | WM9090_IN1B_ZC;
+       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+               | WM9090_IN2A_ZC;
+       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+               | WM9090_IN2B_ZC;
+       wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+               WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
+       wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+               WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
+       wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+               WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
+
+       wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+
+       wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
        wm9090_add_controls(codec);
 
        return 0;
-
-pcm_err:
-       return ret;
 }
 
 #ifdef CONFIG_PM
-static int wm9090_suspend(struct platform_device *pdev, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-static int wm9090_resume(struct platform_device *pdev)
+static int wm9090_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        return 0;
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev)
 #define wm9090_resume NULL
 #endif
 
-static int wm9090_remove(struct platform_device *pdev)
+static int wm9090_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
+       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm9090 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
        .probe =        wm9090_probe,
        .remove =       wm9090_remove,
        .suspend =      wm9090_suspend,
        .resume =       wm9090_resume,
+       .set_bias_level = wm9090_set_bias_level,
+       .reg_cache_size = (WM9090_MAX_REGISTER + 1),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_default = wm9090_reg_defaults,
+       .volatile_register = wm9090_volatile,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090);
 
 static int wm9090_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm9090_priv *wm9090;
-       struct snd_soc_codec *codec;
        int ret;
 
        wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
                dev_err(&i2c->dev, "Can not allocate memory\n");
                return -ENOMEM;
        }
-       codec = &wm9090->codec;
 
        if (i2c->dev.platform_data)
                memcpy(&wm9090->pdata, i2c->dev.platform_data,
                       sizeof(wm9090->pdata));
 
-       wm9090_codec = codec;
-
        i2c_set_clientdata(i2c, wm9090);
+       wm9090->control_data = i2c;
+       mutex_init(&wm9090->mutex);
 
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       codec->control_data = i2c;
-       snd_soc_codec_set_drvdata(codec, wm9090);
-       codec->dev = &i2c->dev;
-       codec->name = "WM9090";
-       codec->owner = THIS_MODULE;
-       codec->bias_level = SND_SOC_BIAS_OFF;
-       codec->set_bias_level = wm9090_set_bias_level,
-       codec->reg_cache_size = WM9090_MAX_REGISTER + 1;
-       codec->reg_cache = &wm9090->reg_cache;
-       codec->volatile_register = wm9090_volatile;
-
-       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;
-       }
-
-       memcpy(&wm9090->reg_cache, wm9090_reg_defaults,
-              sizeof(wm9090->reg_cache));
-
-       ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
-       if (ret < 0)
-               goto err;
-       if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
-               dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret);
-               ret = -EINVAL;
-               goto err;
-       }
-
-       ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
+       ret =  snd_soc_register_codec(&i2c->dev,
+                       &soc_codec_dev_wm9090,  NULL, 0);
        if (ret < 0)
-               goto err;
-
-       /* Configure some defaults; they will be written out when we
-        * bring the bias up.
-        */
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
-               | WM9090_IN1A_ZC;
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
-               | WM9090_IN1B_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
-               | WM9090_IN2A_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
-               | WM9090_IN2B_ZC;
-       wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
-               WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
-       wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= 
-               WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
-       wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
-               WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
-
-       wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
-
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-       ret = snd_soc_register_codec(codec);
-       if (ret != 0) {
-               dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
-               goto err_bias;
-       }
-
-       return 0;
-
-err_bias:
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
-err:
-       kfree(wm9090);
-       i2c_set_clientdata(i2c, NULL);
-       wm9090_codec = NULL;
-
+               kfree(wm9090);
        return ret;
 }
 
 static int wm9090_i2c_remove(struct i2c_client *i2c)
 {
        struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
-       struct snd_soc_codec *codec = &wm9090->codec;
 
-       snd_soc_unregister_codec(codec);
-       wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_codec(&i2c->dev);
        kfree(wm9090);
-       wm9090_codec = NULL;
 
        return 0;
 }
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
 
 static struct i2c_driver wm9090_i2c_driver = {
        .driver = {
-               .name = "wm9090",
+               .name = "wm9090-codec",
                .owner = THIS_MODULE,
        },
        .probe = wm9090_i2c_probe,
index b08eab9..29b9d9f 100644 (file)
@@ -23,8 +23,6 @@
 #ifndef __WM9090_H
 #define __WM9090_H
 
-extern struct snd_soc_codec_device soc_codec_dev_wm9090;
-
 /*
  * Register values.
  */
index 8793341..a144acd 100644 (file)
@@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        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 snd_soc_codec *codec = rtd->codec;
        int reg;
        u16 vra;
 
@@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = {
        .prepare        = ac97_prepare,
 };
 
-struct snd_soc_dai wm9705_dai[] = {
+static struct snd_soc_dai_driver wm9705_dai[] = {
        {
-               .name = "AC97 HiFi",
+               .name = "wm9705-hifi",
                .ac97_control = 1,
                .playback = {
                        .stream_name = "HiFi Playback",
@@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = {
                .ops = &wm9705_dai_ops,
        },
        {
-               .name = "AC97 Aux",
+               .name = "wm9705-aux",
                .playback = {
                        .stream_name = "Aux Playback",
                        .channels_min = 1,
@@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = {
                },
        }
 };
-EXPORT_SYMBOL_GPL(wm9705_dai);
 
 static int wm9705_reset(struct snd_soc_codec *codec)
 {
@@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec)
 }
 
 #ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg)
+static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
 
        return 0;
 }
 
-static int wm9705_soc_resume(struct platform_device *pdev)
+static int wm9705_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        int i, ret;
        u16 *cache = codec->reg_cache;
 
@@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev)
 #define wm9705_soc_resume NULL
 #endif
 
-static int wm9705_soc_probe(struct platform_device *pdev)
+static int wm9705_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
        int ret = 0;
 
        printk(KERN_INFO "WM9705 SoC Audio Codec\n");
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
-                                     GFP_KERNEL);
-       if (socdev->card->codec == NULL)
-               return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-       codec->reg_cache_size = sizeof(wm9705_reg);
-       codec->reg_cache_step = 2;
-
-       codec->name = "WM9705";
-       codec->owner = THIS_MODULE;
-       codec->dai = wm9705_dai;
-       codec->num_dai = ARRAY_SIZE(wm9705_dai);
-       codec->write = ac97_write;
-       codec->read = ac97_read;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0) {
                printk(KERN_ERR "wm9705: failed to register AC97 codec\n");
-               goto codec_err;
+               return ret;
        }
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
        ret = wm9705_reset(codec);
        if (ret)
                goto reset_err;
@@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev)
        return 0;
 
 reset_err:
-       snd_soc_free_pcms(socdev);
-pcm_err:
        snd_soc_free_ac97_codec(codec);
-codec_err:
-       kfree(codec->reg_cache);
-cache_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
        return ret;
 }
 
-static int wm9705_soc_remove(struct platform_device *pdev)
+static int wm9705_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-
-       snd_soc_dapm_free(socdev);
-       snd_soc_free_pcms(socdev);
        snd_soc_free_ac97_codec(codec);
-       kfree(codec->reg_cache);
-       kfree(codec);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm9705 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
        .probe =        wm9705_soc_probe,
        .remove =       wm9705_soc_remove,
        .suspend =      wm9705_soc_suspend,
        .resume =       wm9705_soc_resume,
+       .read = ac97_read,
+       .write = ac97_write,
+       .reg_cache_size = ARRAY_SIZE(wm9705_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_step = 2,
+       .reg_cache_default = wm9705_reg,
+};
+
+static __devinit int wm9705_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
+}
+
+static int __devexit wm9705_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver wm9705_codec_driver = {
+       .driver = {
+                       .name = "wm9705-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = wm9705_probe,
+       .remove = __devexit_p(wm9705_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705);
+
+static int __init wm9705_init(void)
+{
+       return platform_driver_register(&wm9705_codec_driver);
+}
+module_init(wm9705_init);
+
+static void __exit wm9705_exit(void)
+{
+       platform_driver_unregister(&wm9705_codec_driver);
+}
+module_exit(wm9705_exit);
 
 MODULE_DESCRIPTION("ASoC WM9705 driver");
 MODULE_AUTHOR("Ian Molton");
index d380f11..23ea9ce 100644 (file)
@@ -8,7 +8,4 @@
 #define WM9705_DAI_AC97_HIFI   0
 #define WM9705_DAI_AC97_AUX    1
 
-extern struct snd_soc_dai wm9705_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm9705;
-
 #endif
index 28790a2..d2f224d 100644 (file)
@@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        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 snd_soc_codec *codec =rtd->codec;
        int reg;
        u16 vra;
 
@@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        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 snd_soc_codec *codec = rtd->codec;
        u16 vra, xsle;
 
        vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
        .prepare        = ac97_aux_prepare,
 };
 
-struct snd_soc_dai wm9712_dai[] = {
+static struct snd_soc_dai_driver wm9712_dai[] = {
 {
-       .name = "AC97 HiFi",
+       .name = "wm9712-hifi",
        .ac97_control = 1,
        .playback = {
                .stream_name = "HiFi Playback",
@@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = {
        .ops = &wm9712_dai_ops_hifi,
 },
 {
-       .name = "AC97 Aux",
+       .name = "wm9712-aux",
        .playback = {
                .stream_name = "Aux Playback",
                .channels_min = 1,
@@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = {
        .ops = &wm9712_dai_ops_aux,
 }
 };
-EXPORT_SYMBOL_GPL(wm9712_dai);
 
 static int wm9712_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
@@ -597,20 +594,15 @@ err:
        return -EIO;
 }
 
-static int wm9712_soc_suspend(struct platform_device *pdev,
+static int wm9712_soc_suspend(struct snd_soc_codec *codec,
        pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
        wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
 
-static int wm9712_soc_resume(struct platform_device *pdev)
+static int wm9712_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        int i, ret;
        u16 *cache = codec->reg_cache;
 
@@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev)
        return ret;
 }
 
-static int wm9712_soc_probe(struct platform_device *pdev)
+static int wm9712_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
        int ret = 0;
 
        printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
-                                     GFP_KERNEL);
-       if (socdev->card->codec == NULL)
-               return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
-
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-       codec->reg_cache_size = sizeof(wm9712_reg);
-       codec->reg_cache_step = 2;
-
-       codec->name = "WM9712";
-       codec->owner = THIS_MODULE;
-       codec->dai = wm9712_dai;
-       codec->num_dai = ARRAY_SIZE(wm9712_dai);
-       codec->write = ac97_write;
-       codec->read = ac97_read;
-       codec->set_bias_level = wm9712_set_bias_level;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0) {
                printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
-               goto codec_err;
+               return ret;
        }
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
        ret = wm9712_reset(codec, 0);
        if (ret < 0) {
                printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
@@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev)
        return 0;
 
 reset_err:
-       snd_soc_free_pcms(socdev);
-pcm_err:
        snd_soc_free_ac97_codec(codec);
-
-codec_err:
-       kfree(codec->reg_cache);
-
-cache_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
        return ret;
 }
 
-static int wm9712_soc_remove(struct platform_device *pdev)
+static int wm9712_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-
-       snd_soc_dapm_free(socdev);
-       snd_soc_free_pcms(socdev);
        snd_soc_free_ac97_codec(codec);
-       kfree(codec->reg_cache);
-       kfree(codec);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm9712 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
        .probe =        wm9712_soc_probe,
        .remove =       wm9712_soc_remove,
        .suspend =      wm9712_soc_suspend,
        .resume =       wm9712_soc_resume,
+       .read = ac97_read,
+       .write = ac97_write,
+       .set_bias_level = wm9712_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm9712_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_step = 2,
+       .reg_cache_default = wm9712_reg,
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
+
+static __devinit int wm9712_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
+}
+
+static int __devexit wm9712_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver wm9712_codec_driver = {
+       .driver = {
+                       .name = "wm9712-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = wm9712_probe,
+       .remove = __devexit_p(wm9712_remove),
+};
+
+static int __init wm9712_init(void)
+{
+       return platform_driver_register(&wm9712_codec_driver);
+}
+module_init(wm9712_init);
+
+static void __exit wm9712_exit(void)
+{
+       platform_driver_unregister(&wm9712_codec_driver);
+}
+module_exit(wm9712_exit);
 
 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
 MODULE_AUTHOR("Liam Girdwood");
index d29e8a1..fb69c3a 100644 (file)
@@ -8,7 +8,4 @@
 #define WM9712_DAI_AC97_HIFI   0
 #define WM9712_DAI_AC97_AUX            1
 
-extern struct snd_soc_dai wm9712_dai[2];
-extern struct snd_soc_codec_device soc_codec_dev_wm9712;
-
 #endif
index 34e0c91..7da13b0 100644 (file)
@@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
        .set_tristate   = wm9713_set_dai_tristate,
 };
 
-struct snd_soc_dai wm9713_dai[] = {
+static struct snd_soc_dai_driver wm9713_dai[] = {
 {
-       .name = "AC97 HiFi",
+       .name = "wm9713-hifi",
        .ac97_control = 1,
        .playback = {
                .stream_name = "HiFi Playback",
@@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = {
        .ops = &wm9713_dai_ops_hifi,
        },
        {
-       .name = "AC97 Aux",
+       .name = "wm9713-aux",
        .playback = {
                .stream_name = "Aux Playback",
                .channels_min = 1,
@@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = {
        .ops = &wm9713_dai_ops_aux,
        },
        {
-       .name = "WM9713 Voice",
+       .name = "wm9713-voice",
        .playback = {
                .stream_name = "Voice Playback",
                .channels_min = 1,
@@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = {
        .symmetric_rates = 1,
        },
 };
-EXPORT_SYMBOL_GPL(wm9713_dai);
 
 int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
 {
@@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
-static int wm9713_soc_suspend(struct platform_device *pdev,
+static int wm9713_soc_suspend(struct snd_soc_codec *codec,
        pm_message_t state)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        u16 reg;
 
        /* Disable everything except touchpanel - that will be handled
@@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev,
        return 0;
 }
 
-static int wm9713_soc_resume(struct platform_device *pdev)
+static int wm9713_soc_resume(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
        int i, ret;
        u16 *cache = codec->reg_cache;
@@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev)
        return ret;
 }
 
-static int wm9713_soc_probe(struct platform_device *pdev)
+static int wm9713_soc_probe(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec;
+       struct wm9713_priv *wm9713;
        int ret = 0, reg;
 
-       socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
-                                     GFP_KERNEL);
-       if (socdev->card->codec == NULL)
+       wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
+       if (wm9713 == NULL)
                return -ENOMEM;
-       codec = socdev->card->codec;
-       mutex_init(&codec->mutex);
-
-       codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL) {
-               ret = -ENOMEM;
-               goto cache_err;
-       }
-       codec->reg_cache_size = sizeof(wm9713_reg);
-       codec->reg_cache_step = 2;
-
-       snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv),
-                                                GFP_KERNEL));
-       if (snd_soc_codec_get_drvdata(codec) == NULL) {
-               ret = -ENOMEM;
-               goto priv_err;
-       }
-
-       codec->name = "WM9713";
-       codec->owner = THIS_MODULE;
-       codec->dai = wm9713_dai;
-       codec->num_dai = ARRAY_SIZE(wm9713_dai);
-       codec->write = ac97_write;
-       codec->read = ac97_read;
-       codec->set_bias_level = wm9713_set_bias_level;
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
+       snd_soc_codec_set_drvdata(codec, wm9713);
 
        ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
        if (ret < 0)
                goto codec_err;
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0)
-               goto pcm_err;
-
        /* do a cold reset for the controller and then try
         * a warm reset followed by an optional cold reset for codec */
        wm9713_reset(codec, 0);
@@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev)
        return 0;
 
 reset_err:
-       snd_soc_free_pcms(socdev);
-pcm_err:
        snd_soc_free_ac97_codec(codec);
-
 codec_err:
-       kfree(snd_soc_codec_get_drvdata(codec));
-
-priv_err:
-       kfree(codec->reg_cache);
-
-cache_err:
-       kfree(socdev->card->codec);
-       socdev->card->codec = NULL;
+       kfree(wm9713);
        return ret;
 }
 
-static int wm9713_soc_remove(struct platform_device *pdev)
+static int wm9713_soc_remove(struct snd_soc_codec *codec)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec == NULL)
-               return 0;
-
-       snd_soc_dapm_free(socdev);
-       snd_soc_free_pcms(socdev);
+       struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
        snd_soc_free_ac97_codec(codec);
-       kfree(snd_soc_codec_get_drvdata(codec));
-       kfree(codec->reg_cache);
-       kfree(codec);
+       kfree(wm9713);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_wm9713 = {
+static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
        .probe =        wm9713_soc_probe,
        .remove =       wm9713_soc_remove,
        .suspend =      wm9713_soc_suspend,
        .resume =       wm9713_soc_resume,
+       .read = ac97_read,
+       .write = ac97_write,
+       .set_bias_level = wm9713_set_bias_level,
+       .reg_cache_size = ARRAY_SIZE(wm9713_reg),
+       .reg_word_size = sizeof(u16),
+       .reg_cache_step = 2,
+       .reg_cache_default = wm9713_reg,
+};
+
+static __devinit int wm9713_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev,
+                       &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
+}
+
+static int __devexit wm9713_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver wm9713_codec_driver = {
+       .driver = {
+                       .name = "wm9713-codec",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = wm9713_probe,
+       .remove = __devexit_p(wm9713_remove),
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713);
+
+static int __init wm9713_init(void)
+{
+       return platform_driver_register(&wm9713_codec_driver);
+}
+module_init(wm9713_init);
+
+static void __exit wm9713_exit(void)
+{
+       platform_driver_unregister(&wm9713_codec_driver);
+}
+module_exit(wm9713_exit);
 
 MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
 MODULE_AUTHOR("Liam Girdwood");
index 63b8d81..793da86 100644 (file)
@@ -45,9 +45,6 @@
 #define WM9713_DAI_AC97_AUX            1
 #define WM9713_DAI_PCM_VOICE   2
 
-extern struct snd_soc_codec_device soc_codec_dev_wm9713;
-extern struct snd_soc_dai wm9713_dai[3];
-
 int wm9713_reset(struct snd_soc_codec *codec,  int try_warm);
 
 #endif
index 97f74d6..2b07b17 100644 (file)
 #include <mach/mux.h>
 
 #include "../codecs/tlv320aic3x.h"
-#include "../codecs/cq93vc.h"
-#include "../codecs/spdif_transciever.h"
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
 #include "davinci-mcasp.h"
-#include "davinci-vcif.h"
 
 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
                SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -41,8 +38,8 @@ static int evm_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret = 0;
        unsigned sysclk;
 
@@ -87,7 +84,7 @@ static int evm_spdif_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 *cpu_dai = rtd->cpu_dai;
 
        /* set cpu DAI configuration */
        return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
@@ -132,8 +129,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
 };
 
 /* Logic for a aic3x as connected on a davinci-evm */
-static int evm_aic3x_init(struct snd_soc_codec *codec)
+static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        /* Add davinci-evm specific widgets */
        snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
                                  ARRAY_SIZE(aic3x_dapm_widgets));
@@ -161,8 +160,10 @@ static int evm_aic3x_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link evm_dai = {
        .name = "TLV320AIC3X",
        .stream_name = "AIC3X",
-       .cpu_dai = &davinci_i2s_dai,
-       .codec_dai = &aic3x_dai,
+       .cpu_dai_name = "davinci-mcasp.0",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .codec_name = "tlv320aic3x-codec.0-001a",
+       .platform_name = "davinci-pcm-audio",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
 };
@@ -171,40 +172,49 @@ static struct snd_soc_dai_link dm365_evm_dai = {
 #ifdef CONFIG_SND_DM365_AIC3X_CODEC
        .name = "TLV320AIC3X",
        .stream_name = "AIC3X",
-       .cpu_dai = &davinci_i2s_dai,
-       .codec_dai = &aic3x_dai,
+       .cpu_dai_name = "davinci-i2s",
+       .codec_dai_name = "tlv320aic3x-hifi",
        .init = evm_aic3x_init,
+       .codec_name = "tlv320aic3x-codec.0-001a",
        .ops = &evm_ops,
 #elif defined(CONFIG_SND_DM365_VOICE_CODEC)
        .name = "Voice Codec - CQ93VC",
        .stream_name = "CQ93",
-       .cpu_dai = &davinci_vcif_dai,
-       .codec_dai = &cq93vc_dai,
+       .cpu_dai_name = "davinci-vcif",
+       .codec_dai_name = "cq93vc-hifi",
+       .codec_name = "cq93vc-codec",
 #endif
+       .platform_name = "davinci-pcm-audio",
 };
 
 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,
+               .cpu_dai_name= "davinci-mcasp.0",
+               .codec_dai_name = "tlv320aic3x-hifi",
+               .platform_name ="davinci-pcm-audio",
+               .codec_name = "tlv320aic3x-codec.0-001a",
                .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,
+               .cpu_dai_name= "davinci-mcasp.1",
+               .codec_dai_name = "dit-hifi",
+               .codec_name = "spdif_dit",
+               .platform_name = "davinci-pcm-audio",
                .ops = &evm_spdif_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,
+       .cpu_dai_name= "davinci-mcasp.0",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .codec_name = "tlv320aic3x-codec.0-001a",
+       .platform_name = "davinci-pcm-audio",
        .init = evm_aic3x_init,
        .ops = &evm_ops,
 };
@@ -212,7 +222,6 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
 /* davinci dm6446, dm355 evm audio machine driver */
 static struct snd_soc_card snd_soc_card_evm = {
        .name = "DaVinci EVM",
-       .platform = &davinci_soc_platform,
        .dai_link = &evm_dai,
        .num_links = 1,
 };
@@ -220,16 +229,13 @@ static struct snd_soc_card snd_soc_card_evm = {
 /* davinci dm365 evm audio machine driver */
 static struct snd_soc_card dm365_snd_soc_card_evm = {
        .name = "DaVinci DM365 EVM",
-       .platform = &davinci_soc_platform,
        .dai_link = &dm365_evm_dai,
        .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),
 };
@@ -237,82 +243,40 @@ static struct snd_soc_card dm6467_snd_soc_card_evm = {
 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,
-};
-
-/* evm audio subsystem */
-static struct snd_soc_device dm365_evm_snd_devdata = {
-       .card = &dm365_snd_soc_card_evm,
-#ifdef CONFIG_SND_DM365_AIC3X_CODEC
-       .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &aic3x_setup,
-#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
-       .codec_dev = &soc_codec_dev_cq93vc,
-#endif
-};
-
-/* 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,
-};
-
-/* 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 snd_soc_device da850_evm_snd_devdata = {
-       .card           = &da850_snd_soc_card,
-       .codec_dev      = &soc_codec_dev_aic3x,
-       .codec_data     = &aic3x_setup,
-};
-
 static struct platform_device *evm_snd_device;
 
 static int __init evm_init(void)
 {
-       struct snd_soc_device *evm_snd_dev_data;
+       struct snd_soc_card *evm_snd_dev_data;
        int index;
        int ret;
 
        if (machine_is_davinci_evm()) {
-               evm_snd_dev_data = &evm_snd_devdata;
+               evm_snd_dev_data = &snd_soc_card_evm;
                index = 0;
        } else if (machine_is_davinci_dm355_evm()) {
-               evm_snd_dev_data = &evm_snd_devdata;
+               evm_snd_dev_data = &snd_soc_card_evm;
                index = 1;
        } else if (machine_is_davinci_dm365_evm()) {
-               evm_snd_dev_data = &dm365_evm_snd_devdata;
+               evm_snd_dev_data = &dm365_snd_soc_card_evm;
                index = 0;
        } else if (machine_is_davinci_dm6467_evm()) {
-               evm_snd_dev_data = &dm6467_evm_snd_devdata;
+               evm_snd_dev_data = &dm6467_snd_soc_card_evm;
                index = 0;
        } else if (machine_is_davinci_da830_evm()) {
-               evm_snd_dev_data = &da830_evm_snd_devdata;
+               evm_snd_dev_data = &da830_snd_soc_card;
                index = 1;
        } else if (machine_is_davinci_da850_evm()) {
-               evm_snd_dev_data = &da850_evm_snd_devdata;
+               evm_snd_dev_data = &da850_snd_soc_card;
                index = 0;
        } else
                return -EINVAL;
@@ -322,7 +286,6 @@ static int __init evm_init(void)
                return -ENOMEM;
 
        platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
-       evm_snd_dev_data->dev = &evm_snd_device->dev;
        ret = platform_device_add(evm_snd_device);
        if (ret)
                platform_device_put(evm_snd_device);
index 9e8932a..d46b545 100644 (file)
@@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
                struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_platform *platform = socdev->card->platform;
+       struct snd_soc_platform *platform = rtd->platform;
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        u32 spcr;
        u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
@@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
        if (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,
+               if (platform->driver->ops->trigger) {
+                       int ret = platform->driver->ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_STOP);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA stop failed\n");
@@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
                toggle_clock(dev, playback);
 
                /* Restart the DMA */
-               if (platform->pcm_ops->trigger) {
-                       int ret = platform->pcm_ops->trigger(substream,
+               if (platform->driver->ops->trigger) {
+                       int ret = platform->driver->ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_START);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA start failed\n");
@@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
 static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                   unsigned int fmt)
 {
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int pcr;
        unsigned int srgr;
        /* Attention srgr is updated by hw_params! */
@@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
                                int div_id, int div)
 {
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
 
        if (div_id != DAVINCI_MCBSP_CLKGDV)
                return -ENODEV;
@@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
-       struct davinci_mcbsp_dev *dev = dai->private_data;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        struct davinci_pcm_dma_params *dma_params =
                                        &dev->dma_params[substream->stream];
        struct snd_interval *i = NULL;
@@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
        snd_pcm_format_t fmt;
        unsigned element_cnt = 1;
 
+       dai->capture_dma_data = dev->dma_params;
+       dai->playback_dma_data = dev->dma_params;
+
        /* general line settings */
        spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -569,24 +571,18 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
 static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct davinci_mcbsp_dev *dev = dai->private_data;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        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;
 }
 
 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;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        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:
@@ -608,7 +604,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
                struct snd_soc_dai *dai)
 {
-       struct davinci_mcbsp_dev *dev = dai->private_data;
+       struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
        int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
        davinci_mcbsp_stop(dev, playback);
 }
@@ -625,9 +621,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
 
 };
 
-struct snd_soc_dai davinci_i2s_dai = {
-       .name = "davinci-i2s",
-       .id = 0,
+static struct snd_soc_dai_driver davinci_i2s_dai = {
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
@@ -641,7 +635,6 @@ struct snd_soc_dai davinci_i2s_dai = {
        .ops = &davinci_i2s_dai_ops,
 
 };
-EXPORT_SYMBOL_GPL(davinci_i2s_dai);
 
 static int davinci_i2s_probe(struct platform_device *pdev)
 {
@@ -720,10 +713,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
        dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
        dev->dev = &pdev->dev;
 
-       davinci_i2s_dai.private_data = dev;
-       davinci_i2s_dai.capture.dma_data = dev->dma_params;
-       davinci_i2s_dai.playback.dma_data = dev->dma_params;
-       ret = snd_soc_register_dai(&davinci_i2s_dai);
+       dev_set_drvdata(&pdev->dev, dev);
+
+       ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
        if (ret != 0)
                goto err_free_mem;
 
@@ -739,10 +731,10 @@ err_release_region:
 
 static int davinci_i2s_remove(struct platform_device *pdev)
 {
-       struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
+       struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
        struct resource *mem;
 
-       snd_soc_unregister_dai(&davinci_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
        clk_disable(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
@@ -757,7 +749,7 @@ static struct platform_driver davinci_mcbsp_driver = {
        .probe          = davinci_i2s_probe,
        .remove         = davinci_i2s_remove,
        .driver         = {
-               .name   = "davinci-asp",
+               .name   = "davinci-i2s",
                .owner  = THIS_MODULE,
        },
 };
index 0b1e77b..48dac3e 100644 (file)
@@ -17,6 +17,4 @@ enum davinci_mcbsp_div {
        DAVINCI_MCBSP_CLKGDV,              /* Sample rate generator divider */
 };
 
-extern struct snd_soc_dai davinci_i2s_dai;
-
 #endif
index b247208..86918ee 100644 (file)
@@ -422,7 +422,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
 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;
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -709,12 +709,15 @@ 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_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        struct davinci_pcm_dma_params *dma_params =
                                        &dev->dma_params[substream->stream];
        int word_length;
        u8 fifo_level;
 
+       cpu_dai->capture_dma_data = dev->dma_params;
+       cpu_dai->playback_dma_data = dev->dma_params;
+
        davinci_hw_common_param(dev, substream->stream);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                fifo_level = dev->txnumevt;
@@ -761,8 +764,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
 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;
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        int ret = 0;
 
        switch (cmd) {
@@ -804,10 +806,9 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
 
 };
 
-struct snd_soc_dai davinci_mcasp_dai[] = {
+static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
        {
-               .name           = "davinci-i2s",
-               .id             = 0,
+               .name           = "davinci-mcasp.0",
                .playback       = {
                        .channels_min   = 2,
                        .channels_max   = 2,
@@ -828,8 +829,7 @@ struct snd_soc_dai davinci_mcasp_dai[] = {
 
        },
        {
-               .name           = "davinci-dit",
-               .id             = 1,
+               "davinci-mcasp.1",
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 384,
@@ -840,7 +840,6 @@ struct snd_soc_dai davinci_mcasp_dai[] = {
        },
 
 };
-EXPORT_SYMBOL_GPL(davinci_mcasp_dai);
 
 static int davinci_mcasp_probe(struct platform_device *pdev)
 {
@@ -899,6 +898,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
        if (!res) {
                dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENODEV;
                goto err_release_region;
        }
 
@@ -913,15 +913,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
        if (!res) {
                dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENODEV;
                goto err_release_region;
        }
 
        dma_data->channel = res->start;
-       davinci_mcasp_dai[pdata->op_mode].private_data = dev;
-       davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params;
-       davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params;
-       davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
-       ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
+       dev_set_drvdata(&pdev->dev, dev);
+       ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
 
        if (ret != 0)
                goto err_release_region;
@@ -937,12 +935,10 @@ err_release_data:
 
 static int davinci_mcasp_remove(struct platform_device *pdev)
 {
-       struct snd_platform_data *pdata = pdev->dev.platform_data;
-       struct davinci_audio_dev *dev;
+       struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
        struct resource *mem;
 
-       snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]);
-       dev = davinci_mcasp_dai[pdata->op_mode].private_data;
+       snd_soc_unregister_dai(&pdev->dev);
        clk_disable(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
index e755b51..4681acc 100644 (file)
@@ -22,8 +22,6 @@
 #include <mach/asp.h>
 #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
index a712411..9d35b8c 100644 (file)
@@ -653,7 +653,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
        struct davinci_pcm_dma_params *pa;
        struct davinci_pcm_dma_params *params;
 
-       pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
        if (!pa)
                return -ENODEV;
        params = &pa[substream->stream];
@@ -821,7 +821,7 @@ static int davinci_pcm_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = 0xffffffff;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = davinci_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK,
                        pcm_hardware_playback.buffer_bytes_max);
@@ -829,7 +829,7 @@ static int davinci_pcm_new(struct snd_card *card,
                        return ret;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = davinci_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE,
                        pcm_hardware_capture.buffer_bytes_max);
@@ -840,25 +840,44 @@ static int davinci_pcm_new(struct snd_card *card,
        return 0;
 }
 
-struct snd_soc_platform davinci_soc_platform = {
-       .name =         "davinci-audio",
-       .pcm_ops =      &davinci_pcm_ops,
+static struct snd_soc_platform_driver davinci_soc_platform = {
+       .ops =          &davinci_pcm_ops,
        .pcm_new =      davinci_pcm_new,
        .pcm_free =     davinci_pcm_free,
 };
-EXPORT_SYMBOL_GPL(davinci_soc_platform);
 
-static int __init davinci_soc_platform_init(void)
+static int __devinit davinci_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&davinci_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform);
 }
-module_init(davinci_soc_platform_init);
 
-static void __exit davinci_soc_platform_exit(void)
+static int __devexit davinci_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&davinci_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver davinci_pcm_driver = {
+       .driver = {
+                       .name = "davinci-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = davinci_soc_platform_probe,
+       .remove = __devexit_p(davinci_soc_platform_remove),
+};
+
+static int __init snd_davinci_pcm_init(void)
+{
+       return platform_driver_register(&davinci_pcm_driver);
+}
+module_init(snd_davinci_pcm_init);
+
+static void __exit snd_davinci_pcm_exit(void)
+{
+       platform_driver_unregister(&davinci_pcm_driver);
 }
-module_exit(davinci_soc_platform_exit);
+module_exit(snd_davinci_pcm_exit);
 
 MODULE_AUTHOR("Vladimir Barinov");
 MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
index b799a02..c0d6c9b 100644 (file)
@@ -28,7 +28,4 @@ struct davinci_pcm_dma_params {
        unsigned int fifo_level;
 };
 
-
-extern struct snd_soc_platform davinci_soc_platform;
-
 #endif
index 40eccfe..009b652 100644 (file)
@@ -29,7 +29,6 @@
 #include <asm/plat-sffsdr/sffsdr-fpga.h>
 #endif
 
-#include <mach/mcbsp.h>
 #include <mach/edma.h>
 
 #include "../codecs/pcm3008.h"
@@ -48,7 +47,7 @@ static int sffsdr_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 *cpu_dai = rtd->cpu_dai;
        int fs;
        int ret = 0;
 
@@ -85,15 +84,16 @@ static struct snd_soc_ops sffsdr_ops = {
 static struct snd_soc_dai_link sffsdr_dai = {
        .name = "PCM3008", /* Codec name */
        .stream_name = "PCM3008 HiFi",
-       .cpu_dai = &davinci_i2s_dai,
-       .codec_dai = &pcm3008_dai,
+       .cpu_dai_name = "davinci-asp.0",
+       .codec_dai_name = "pcm3008-hifi",
+       .codec_name = "pcm3008-codec",
+       .platform_name = "davinci-pcm-audio",
        .ops = &sffsdr_ops,
 };
 
 /* davinci-sffsdr audio machine driver */
 static struct snd_soc_card snd_soc_sffsdr = {
        .name = "DaVinci SFFSDR",
-       .platform = &davinci_soc_platform,
        .dai_link = &sffsdr_dai,
        .num_links = 1,
 };
@@ -106,11 +106,12 @@ static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
        .pdda_pin = GPIO(38),
 };
 
-/* sffsdr audio subsystem */
-static struct snd_soc_device sffsdr_snd_devdata = {
-       .card = &snd_soc_sffsdr,
-       .codec_dev = &soc_codec_dev_pcm3008,
-       .codec_data = &sffsdr_pcm3008_setup,
+struct platform_device pcm3008_codec = {
+               .name = "pcm3008-codec",
+               .id = 0,
+               .dev = {
+                               .platform_data = &sffsdr_pcm3008_setup,
+               },
 };
 
 static struct resource sffsdr_snd_resources[] = {
@@ -135,14 +136,15 @@ static int __init sffsdr_init(void)
        if (!machine_is_sffsdr())
                return -EINVAL;
 
+       platform_device_register(&pcm3008_codec);
+
        sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
        if (!sffsdr_snd_device) {
                printk(KERN_ERR "platform device allocation failed\n");
                return -ENOMEM;
        }
 
-       platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
-       sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
+       platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr);
        platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data,
                                 sizeof(sffsdr_snd_data));
 
@@ -150,7 +152,7 @@ static int __init sffsdr_init(void)
                                            sffsdr_snd_resources,
                                            ARRAY_SIZE(sffsdr_snd_resources));
        if (ret) {
-               printk(KERN_ERR "platform device add ressources failed\n");
+               printk(KERN_ERR "platform device add resources failed\n");
                goto error;
        }
 
@@ -168,6 +170,7 @@ error:
 static void __exit sffsdr_exit(void)
 {
        platform_device_unregister(sffsdr_snd_device);
+       platform_device_unregister(&pcm3008_codec);
 }
 
 module_init(sffsdr_init);
index 4867853..ea232f6 100644 (file)
@@ -36,7 +36,6 @@
 
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
-#include "davinci-vcif.h"
 
 #define MOD_REG_BIT(val, mask, set) do { \
        if (set) { \
@@ -55,7 +54,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct davinci_vcif_dev *davinci_vcif_dev =
-                                       rtd->dai->cpu_dai->private_data;
+                       snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
        u32 w;
 
@@ -74,7 +73,7 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct davinci_vcif_dev *davinci_vcif_dev =
-                                       rtd->dai->cpu_dai->private_data;
+                       snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
        u32 w;
 
@@ -92,12 +91,15 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
 {
-       struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data;
+       struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai);
        struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
        struct davinci_pcm_dma_params *dma_params =
                        &davinci_vcif_dev->dma_params[substream->stream];
        u32 w;
 
+       dai->capture_dma_data = davinci_vcif_dev->dma_params;
+       dai->playback_dma_data = davinci_vcif_dev->dma_params;
+
        /* Restart the codec before setup */
        davinci_vcif_stop(substream);
        davinci_vcif_start(substream);
@@ -179,8 +181,7 @@ static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
        .hw_params      = davinci_vcif_hw_params,
 };
 
-struct snd_soc_dai davinci_vcif_dai = {
-       .name = "davinci-vcif",
+static struct snd_soc_dai_driver davinci_vcif_dai = {
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
@@ -194,7 +195,6 @@ struct snd_soc_dai davinci_vcif_dai = {
        .ops = &davinci_vcif_dai_ops,
 
 };
-EXPORT_SYMBOL_GPL(davinci_vcif_dai);
 
 static int davinci_vcif_probe(struct platform_device *pdev)
 {
@@ -222,12 +222,9 @@ static int davinci_vcif_probe(struct platform_device *pdev)
        davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
                                        davinci_vc->davinci_vcif.dma_rx_addr;
 
-       davinci_vcif_dai.dev = &pdev->dev;
-       davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params;
-       davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params;
-       davinci_vcif_dai.private_data = davinci_vcif_dev;
+       dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
 
-       ret = snd_soc_register_dai(&davinci_vcif_dai);
+       ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai);
        if (ret != 0) {
                dev_err(&pdev->dev, "could not register dai\n");
                goto fail;
@@ -243,7 +240,7 @@ fail:
 
 static int davinci_vcif_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&davinci_vcif_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
        return 0;
 }
@@ -252,7 +249,7 @@ static struct platform_driver davinci_vcif_driver = {
        .probe          = davinci_vcif_probe,
        .remove         = davinci_vcif_remove,
        .driver         = {
-               .name   = "davinci_vcif",
+               .name   = "davinci-vcif",
                .owner  = THIS_MODULE,
        },
 };
diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h
deleted file mode 100644 (file)
index 571c994..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * ALSA SoC Voice Codec Interface for TI DAVINCI processor
- *
- * Copyright (C) 2010 Texas Instruments.
- *
- * Author: Miguel Aguilar <miguel.aguilar@ridgerun.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.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _DAVINCI_VCIF_H
-#define _DAVINCI_VCIF_H
-
-extern struct snd_soc_dai davinci_vcif_dai;
-
-#endif
index f617f56..5742904 100644 (file)
@@ -3,11 +3,16 @@ config SND_EP93XX_SOC
        depends on ARCH_EP93XX && SND_SOC
        help
          Say Y or M if you want to add support for codecs attached to
-         the EP93xx I2S interface.
+         the EP93xx I2S or AC97 interfaces.
 
 config SND_EP93XX_SOC_I2S
        tristate
 
+config SND_EP93XX_SOC_AC97
+       tristate
+       select AC97_BUS
+       select SND_SOC_AC97_BUS
+
 config SND_EP93XX_SOC_SNAPPERCL15
         tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
         depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
@@ -16,3 +21,12 @@ config SND_EP93XX_SOC_SNAPPERCL15
         help
           Say Y or M here if you want to add support for I2S audio on the
           Bluewater Systems Snapper CL15 module.
+
+config SND_EP93XX_SOC_SIMONE
+       tristate "SoC Audio support for Simplemachines Sim.One board"
+       depends on SND_EP93XX_SOC && MACH_SIM_ONE
+       select SND_EP93XX_SOC_AC97
+       select SND_SOC_AC97_CODEC
+       help
+         Say Y or M here if you want to add support for AC97 audio on the
+         Simplemachines Sim.One board.
index 272e60f..8e7977f 100644 (file)
@@ -1,11 +1,15 @@
 # EP93xx Platform Support
 snd-soc-ep93xx-objs                            := ep93xx-pcm.o
 snd-soc-ep93xx-i2s-objs                                := ep93xx-i2s.o
+snd-soc-ep93xx-ac97-objs                       := ep93xx-ac97.o
 
 obj-$(CONFIG_SND_EP93XX_SOC)                   += snd-soc-ep93xx.o
 obj-$(CONFIG_SND_EP93XX_SOC_I2S)               += snd-soc-ep93xx-i2s.o
+obj-$(CONFIG_SND_EP93XX_SOC_AC97)              += snd-soc-ep93xx-ac97.o
 
 # EP93XX Machine Support
 snd-soc-snappercl15-objs                       := snappercl15.o
+snd-soc-simone-objs                            := simone.o
 
 obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15)       += snd-soc-snappercl15.o
+obj-$(CONFIG_SND_EP93XX_SOC_SIMONE)            += snd-soc-simone.o
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
new file mode 100644 (file)
index 0000000..68a0bae
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * ASoC driver for Cirrus Logic EP93xx AC97 controller.
+ *
+ * Copyright (c) 2010 Mika Westerberg
+ *
+ * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/ac97_codec.h>
+#include <sound/soc.h>
+
+#include <mach/dma.h>
+#include "ep93xx-pcm.h"
+
+/*
+ * Per channel (1-4) registers.
+ */
+#define AC97CH(n)              (((n) - 1) * 0x20)
+
+#define AC97DR(n)              (AC97CH(n) + 0x0000)
+
+#define AC97RXCR(n)            (AC97CH(n) + 0x0004)
+#define AC97RXCR_REN           BIT(0)
+#define AC97RXCR_RX3           BIT(3)
+#define AC97RXCR_RX4           BIT(4)
+#define AC97RXCR_CM            BIT(15)
+
+#define AC97TXCR(n)            (AC97CH(n) + 0x0008)
+#define AC97TXCR_TEN           BIT(0)
+#define AC97TXCR_TX3           BIT(3)
+#define AC97TXCR_TX4           BIT(4)
+#define AC97TXCR_CM            BIT(15)
+
+#define AC97SR(n)              (AC97CH(n) + 0x000c)
+#define AC97SR_TXFE            BIT(1)
+#define AC97SR_TXUE            BIT(6)
+
+#define AC97RISR(n)            (AC97CH(n) + 0x0010)
+#define AC97ISR(n)             (AC97CH(n) + 0x0014)
+#define AC97IE(n)              (AC97CH(n) + 0x0018)
+
+/*
+ * Global AC97 controller registers.
+ */
+#define AC97S1DATA             0x0080
+#define AC97S2DATA             0x0084
+#define AC97S12DATA            0x0088
+
+#define AC97RGIS               0x008c
+#define AC97GIS                        0x0090
+#define AC97IM                 0x0094
+/*
+ * Common bits for RGIS, GIS and IM registers.
+ */
+#define AC97_SLOT2RXVALID      BIT(1)
+#define AC97_CODECREADY                BIT(5)
+#define AC97_SLOT2TXCOMPLETE   BIT(6)
+
+#define AC97EOI                        0x0098
+#define AC97EOI_WINT           BIT(0)
+#define AC97EOI_CODECREADY     BIT(1)
+
+#define AC97GCR                        0x009c
+#define AC97GCR_AC97IFE                BIT(0)
+
+#define AC97RESET              0x00a0
+#define AC97RESET_TIMEDRESET   BIT(0)
+
+#define AC97SYNC               0x00a4
+#define AC97SYNC_TIMEDSYNC     BIT(0)
+
+#define AC97_TIMEOUT           msecs_to_jiffies(5)
+
+/**
+ * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
+ * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
+ * @dev: pointer to the platform device dev structure
+ * @mem: physical memory resource for the registers
+ * @regs: mapped AC97 controller registers
+ * @irq: AC97 interrupt number
+ * @done: bus ops wait here for an interrupt
+ */
+struct ep93xx_ac97_info {
+       struct mutex            lock;
+       struct device           *dev;
+       struct resource         *mem;
+       void __iomem            *regs;
+       int                     irq;
+       struct completion       done;
+};
+
+/* currently ALSA only supports a single AC97 device */
+static struct ep93xx_ac97_info *ep93xx_ac97_info;
+
+static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
+       .name           = "ac97-pcm-out",
+       .dma_port       = EP93XX_DMA_M2P_PORT_AAC1,
+};
+
+static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
+       .name           = "ac97-pcm-in",
+       .dma_port       = EP93XX_DMA_M2P_PORT_AAC1,
+};
+
+static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
+                                           unsigned reg)
+{
+       return __raw_readl(info->regs + reg);
+}
+
+static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
+                                        unsigned reg, unsigned val)
+{
+       __raw_writel(val, info->regs + reg);
+}
+
+static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
+                                      unsigned short reg)
+{
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+       unsigned short val;
+
+       mutex_lock(&info->lock);
+
+       ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
+               dev_warn(info->dev, "timeout reading register %x\n", reg);
+               mutex_unlock(&info->lock);
+               return -ETIMEDOUT;
+       }
+       val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
+
+       mutex_unlock(&info->lock);
+       return val;
+}
+
+static void ep93xx_ac97_write(struct snd_ac97 *ac97,
+                             unsigned short reg,
+                             unsigned short val)
+{
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+
+       mutex_lock(&info->lock);
+
+       /*
+        * Writes to the codec need to be done so that slot 2 is filled in
+        * before slot 1.
+        */
+       ep93xx_ac97_write_reg(info, AC97S2DATA, val);
+       ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
+
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "timeout writing register %x\n", reg);
+
+       mutex_unlock(&info->lock);
+}
+
+static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+
+       mutex_lock(&info->lock);
+
+       /*
+        * We are assuming that before this functions gets called, the codec
+        * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
+        * control the SYNC signal directly via AC97SYNC register. Using
+        * TIMEDSYNC the controller will keep the SYNC high > 1us.
+        */
+       ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "codec warm reset timeout\n");
+
+       mutex_unlock(&info->lock);
+}
+
+static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+       struct ep93xx_ac97_info *info = ep93xx_ac97_info;
+
+       mutex_lock(&info->lock);
+
+       /*
+        * For doing cold reset, we disable the AC97 controller interface, clear
+        * WINT and CODECREADY bits, and finally enable the interface again.
+        */
+       ep93xx_ac97_write_reg(info, AC97GCR, 0);
+       ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
+       ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
+
+       /*
+        * Now, assert the reset and wait for the codec to become ready.
+        */
+       ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
+       ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
+       if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
+               dev_warn(info->dev, "codec cold reset timeout\n");
+
+       /*
+        * Give the codec some time to come fully out from the reset. This way
+        * we ensure that the subsequent reads/writes will work.
+        */
+       usleep_range(15000, 20000);
+
+       mutex_unlock(&info->lock);
+}
+
+static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
+{
+       struct ep93xx_ac97_info *info = dev_id;
+       unsigned status, mask;
+
+       /*
+        * Just mask out the interrupt and wake up the waiting thread.
+        * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
+        * the waiting thread.
+        */
+       status = ep93xx_ac97_read_reg(info, AC97GIS);
+       mask = ep93xx_ac97_read_reg(info, AC97IM);
+       mask &= ~status;
+       ep93xx_ac97_write_reg(info, AC97IM, mask);
+
+       complete(&info->done);
+       return IRQ_HANDLED;
+}
+
+struct snd_ac97_bus_ops soc_ac97_ops = {
+       .read           = ep93xx_ac97_read,
+       .write          = ep93xx_ac97_write,
+       .reset          = ep93xx_ac97_cold_reset,
+       .warm_reset     = ep93xx_ac97_warm_reset,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops);
+
+static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
+                              int cmd, struct snd_soc_dai *dai)
+{
+       struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
+       unsigned v = 0;
+
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       /*
+                        * Enable compact mode, TX slots 3 & 4, and the TX FIFO
+                        * itself.
+                        */
+                       v |= AC97TXCR_CM;
+                       v |= AC97TXCR_TX3 | AC97TXCR_TX4;
+                       v |= AC97TXCR_TEN;
+                       ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
+               } else {
+                       /*
+                        * Enable compact mode, RX slots 3 & 4, and the RX FIFO
+                        * itself.
+                        */
+                       v |= AC97RXCR_CM;
+                       v |= AC97RXCR_RX3 | AC97RXCR_RX4;
+                       v |= AC97RXCR_REN;
+                       ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
+               }
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       /*
+                        * As per Cirrus EP93xx errata described below:
+                        *
+                        * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
+                        *
+                        * we will wait for the TX FIFO to be empty before
+                        * clearing the TEN bit.
+                        */
+                       unsigned long timeout = jiffies + AC97_TIMEOUT;
+
+                       do {
+                               v = ep93xx_ac97_read_reg(info, AC97SR(1));
+                               if (time_after(jiffies, timeout)) {
+                                       dev_warn(info->dev, "TX timeout\n");
+                                       break;
+                               }
+                       } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
+
+                       /* disable the TX FIFO */
+                       ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
+               } else {
+                       /* disable the RX FIFO */
+                       ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
+               }
+               break;
+
+       default:
+               dev_warn(info->dev, "unknown command %d\n", cmd);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       struct ep93xx_pcm_dma_params *dma_data;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dma_data = &ep93xx_ac97_pcm_out;
+       else
+               dma_data = &ep93xx_ac97_pcm_in;
+
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+       return 0;
+}
+
+static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
+       .startup        = ep93xx_ac97_startup,
+       .trigger        = ep93xx_ac97_trigger,
+};
+
+struct snd_soc_dai_driver ep93xx_ac97_dai = {
+       .name           = "ep93xx-ac97",
+       .id             = 0,
+       .ac97_control   = 1,
+       .playback       = {
+               .stream_name    = "AC97 Playback",
+               .channels_min   = 2,
+               .channels_max   = 2,
+               .rates          = SNDRV_PCM_RATE_8000_48000,
+               .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture        = {
+               .stream_name    = "AC97 Capture",
+               .channels_min   = 2,
+               .channels_max   = 2,
+               .rates          = SNDRV_PCM_RATE_8000_48000,
+               .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops                    = &ep93xx_ac97_dai_ops,
+};
+
+static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
+{
+       struct ep93xx_ac97_info *info;
+       int ret;
+
+       info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       dev_set_drvdata(&pdev->dev, info);
+
+       mutex_init(&info->lock);
+       init_completion(&info->done);
+       info->dev = &pdev->dev;
+
+       info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!info->mem) {
+               ret = -ENXIO;
+               goto fail_free_info;
+       }
+
+       info->irq = platform_get_irq(pdev, 0);
+       if (!info->irq) {
+               ret = -ENXIO;
+               goto fail_free_info;
+       }
+
+       if (!request_mem_region(info->mem->start, resource_size(info->mem),
+                               pdev->name)) {
+               ret = -EBUSY;
+               goto fail_free_info;
+       }
+
+       info->regs = ioremap(info->mem->start, resource_size(info->mem));
+       if (!info->regs) {
+               ret = -ENOMEM;
+               goto fail_release_mem;
+       }
+
+       ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH,
+                         pdev->name, info);
+       if (ret)
+               goto fail_unmap_mem;
+
+       ep93xx_ac97_info = info;
+       platform_set_drvdata(pdev, info);
+
+       ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
+       if (ret)
+               goto fail_free_irq;
+
+       return 0;
+
+fail_free_irq:
+       platform_set_drvdata(pdev, NULL);
+       free_irq(info->irq, info);
+fail_unmap_mem:
+       iounmap(info->regs);
+fail_release_mem:
+       release_mem_region(info->mem->start, resource_size(info->mem));
+fail_free_info:
+       kfree(info);
+
+       return ret;
+}
+
+static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
+{
+       struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_dai(&pdev->dev);
+
+       /* disable the AC97 controller */
+       ep93xx_ac97_write_reg(info, AC97GCR, 0);
+
+       free_irq(info->irq, info);
+       iounmap(info->regs);
+       release_mem_region(info->mem->start, resource_size(info->mem));
+       platform_set_drvdata(pdev, NULL);
+       kfree(info);
+
+       return 0;
+}
+
+static struct platform_driver ep93xx_ac97_driver = {
+       .probe  = ep93xx_ac97_probe,
+       .remove = __devexit_p(ep93xx_ac97_remove),
+       .driver = {
+               .name = "ep93xx-ac97",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init ep93xx_ac97_init(void)
+{
+       return platform_driver_register(&ep93xx_ac97_driver);
+}
+module_init(ep93xx_ac97_init);
+
+static void __exit ep93xx_ac97_exit(void)
+{
+       platform_driver_unregister(&ep93xx_ac97_driver);
+}
+module_exit(ep93xx_ac97_exit);
+
+MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-ac97");
index 00b9466..4f48733 100644 (file)
@@ -31,7 +31,6 @@
 #include <mach/dma.h>
 
 #include "ep93xx-pcm.h"
-#include "ep93xx-i2s.h"
 
 #define EP93XX_I2S_TXCLKCFG            0x00
 #define EP93XX_I2S_RXCLKCFG            0x04
@@ -145,8 +144,8 @@ static int ep93xx_i2s_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 ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        snd_soc_dai_set_dma_data(cpu_dai, substream,
                                 &info->dma_params[substream->stream]);
@@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
 static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 
        ep93xx_i2s_disable(info, substream->stream);
 }
@@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
 static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                  unsigned int fmt)
 {
-       struct ep93xx_i2s_info *info = cpu_dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int clk_cfg, lin_ctrl;
 
        clk_cfg  = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
@@ -242,9 +240,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
                                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;
-       struct ep93xx_i2s_info *info = cpu_dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
        unsigned word_len, div, sdiv, lrdiv;
        int found = 0, err;
 
@@ -302,7 +298,7 @@ out:
 static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
                                 unsigned int freq, int dir)
 {
-       struct ep93xx_i2s_info *info = cpu_dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
 
        if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
                return -EINVAL;
@@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
 #ifdef CONFIG_PM
 static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
 {
-       struct ep93xx_i2s_info *info = dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 
        if (!dai->active)
                return;
@@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
 
 static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
 {
-       struct ep93xx_i2s_info *info = dai->private_data;
+       struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 
        if (!dai->active)
                return;
@@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
                            SNDRV_PCM_FMTBIT_S24_LE | \
                            SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_dai ep93xx_i2s_dai = {
-       .name           = "ep93xx-i2s",
-       .id             = 0,
+static struct snd_soc_dai_driver ep93xx_i2s_dai = {
        .symmetric_rates= 1,
        .suspend        = ep93xx_i2s_suspend,
        .resume         = ep93xx_i2s_resume,
@@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = {
        },
        .ops            = &ep93xx_i2s_dai_ops,
 };
-EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
 
 static int ep93xx_i2s_probe(struct platform_device *pdev)
 {
@@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
                goto fail;
        }
 
-       ep93xx_i2s_dai.dev = &pdev->dev;
-       ep93xx_i2s_dai.private_data = info;
+       dev_set_drvdata(&pdev->dev, info);
        info->dma_params = ep93xx_i2s_dma_params;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
                goto fail_put_sclk;
        }
 
-       err = snd_soc_register_dai(&ep93xx_i2s_dai);
+       err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
        if (err)
                goto fail_put_lrclk;
 
@@ -447,9 +439,9 @@ fail:
 
 static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
 {
-       struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data;
+       struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
 
-       snd_soc_unregister_dai(&ep93xx_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
        clk_put(info->lrclk);
        clk_put(info->sclk);
        clk_put(info->mclk);
diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h
deleted file mode 100644 (file)
index 3bd4ebf..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * linux/sound/soc/ep93xx-i2s.h
- * EP93xx I2S driver
- *
- * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
- *  
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#ifndef _EP93XX_SND_SOC_I2S_H
-#define _EP93XX_SND_SOC_I2S_H
-
-extern struct snd_soc_dai ep93xx_i2s_dai;
-
-#endif /* _EP93XX_SND_SOC_I2S_H */
index 4ba9384..2f121dd 100644 (file)
@@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie,
 static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
        struct ep93xx_pcm_dma_params *dma_params;
        struct ep93xx_runtime_data *rtd;    
        int ret;
@@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = 0xffffffff;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
                                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        return ret;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
                                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        return 0;
 }
 
-struct snd_soc_platform ep93xx_soc_platform = {
-       .name           = "ep93xx-audio",
-       .pcm_ops        = &ep93xx_pcm_ops,
+static struct snd_soc_platform_driver ep93xx_soc_platform = {
+       .ops            = &ep93xx_pcm_ops,
        .pcm_new        = &ep93xx_pcm_new,
        .pcm_free       = &ep93xx_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(ep93xx_soc_platform);
+
+static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
+}
+
+static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver ep93xx_pcm_driver = {
+       .driver = {
+                       .name = "ep93xx-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = ep93xx_soc_platform_probe,
+       .remove = __devexit_p(ep93xx_soc_platform_remove),
+};
 
 static int __init ep93xx_soc_platform_init(void)
 {
-       return snd_soc_register_platform(&ep93xx_soc_platform);
+       return platform_driver_register(&ep93xx_pcm_driver);
 }
 
 static void __exit ep93xx_soc_platform_exit(void)
 {
-       snd_soc_unregister_platform(&ep93xx_soc_platform);
+       platform_driver_unregister(&ep93xx_pcm_driver);
 }
 
 module_init(ep93xx_soc_platform_init);
index 4ffdd3f..111e112 100644 (file)
@@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params {
        int     dma_port;
 };
 
-extern struct snd_soc_platform ep93xx_soc_platform;
-
 #endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c
new file mode 100644 (file)
index 0000000..4b0d199
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * simone.c -- ASoC audio for Simplemachines Sim.One board
+ *
+ * Copyright (c) 2010 Mika Westerberg
+ *
+ * Based on snappercl15 machine driver by Ryan Mallon.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+
+#include "ep93xx-pcm.h"
+
+static struct snd_soc_dai_link simone_dai = {
+       .name           = "AC97",
+       .stream_name    = "AC97 HiFi",
+       .cpu_dai_name   = "ep93xx-ac97",
+       .codec_dai_name = "ac97-hifi",
+       .codec_name     = "ac97-codec",
+       .platform_name  = "ep93xx-pcm-audio",
+};
+
+static struct snd_soc_card snd_soc_simone = {
+       .name           = "Sim.One",
+       .dai_link       = &simone_dai,
+       .num_links      = 1,
+};
+
+static struct platform_device *simone_snd_ac97_device;
+static struct platform_device *simone_snd_device;
+
+static int __init simone_init(void)
+{
+       int ret;
+
+       if (!machine_is_sim_one())
+               return -ENODEV;
+
+       simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1);
+       if (!simone_snd_ac97_device)
+               return -ENOMEM;
+
+       ret = platform_device_add(simone_snd_ac97_device);
+       if (ret)
+               goto fail;
+
+       simone_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!simone_snd_device) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+
+       platform_set_drvdata(simone_snd_device, &snd_soc_simone);
+       ret = platform_device_add(simone_snd_device);
+       if (ret) {
+               platform_device_put(simone_snd_device);
+               goto fail;
+       }
+
+       return ret;
+
+fail:
+       platform_device_put(simone_snd_ac97_device);
+       return ret;
+}
+module_init(simone_init);
+
+static void __exit simone_exit(void)
+{
+       platform_device_unregister(simone_snd_device);
+       platform_device_unregister(simone_snd_ac97_device);
+}
+module_exit(simone_exit);
+
+MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_LICENSE("GPL");
index 6495534..28ab5ff 100644 (file)
@@ -22,7 +22,6 @@
 
 #include "../codecs/tlv320aic23.h"
 #include "ep93xx-pcm.h"
-#include "ep93xx-i2s.h"
 
 #define CODEC_CLOCK 5644800
 
@@ -30,8 +29,8 @@ static int snappercl15_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
@@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic Jack"},
 };
 
-static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)
+static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
                                  ARRAY_SIZE(tlv320aic23_dapm_widgets));
 
@@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link snappercl15_dai = {
        .name           = "tlv320aic23",
        .stream_name    = "AIC23",
-       .cpu_dai        = &ep93xx_i2s_dai,
-       .codec_dai      = &tlv320aic23_dai,
+       .cpu_dai_name   = "ep93xx-i2s",
+       .codec_dai_name = "tlv320aic23-hifi",
+       .codec_name     = "tlv320aic23-codec.0-001a",
+       .platform_name  =  "ep93xx-pcm-audio",
        .init           = snappercl15_tlv320aic23_init,
        .ops            = &snappercl15_ops,
 };
 
 static struct snd_soc_card snd_soc_snappercl15 = {
        .name           = "Snapper CL15",
-       .platform       = &ep93xx_soc_platform,
        .dai_link       = &snappercl15_dai,
        .num_links      = 1,
 };
 
-static struct snd_soc_device snappercl15_snd_devdata = {
-       .card           = &snd_soc_snappercl15,
-       .codec_dev      = &soc_codec_dev_tlv320aic23,
-};
-
 static struct platform_device *snappercl15_snd_device;
 
 static int __init snappercl15_init(void)
@@ -126,8 +123,7 @@ static int __init snappercl15_init(void)
        if (!snappercl15_snd_device)
                return -ENOMEM;
        
-       platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata);
-       snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev;
+       platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);
        ret = platform_device_add(snappercl15_snd_device);
        if (ret)
                platform_device_put(snappercl15_snd_device);
index 8cb65cc..d754d34 100644 (file)
@@ -1,27 +1,36 @@
-config SND_SOC_OF_SIMPLE
-       tristate
-       
 config SND_MPC52xx_DMA
        tristate
 
-# ASoC platform support for the Freescale MPC8610 SOC.  This compiles drivers
-# for the SSI and the Elo DMA controller.  You will still need to select
-# a platform driver and a codec driver.
-config SND_SOC_MPC8610
+# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and
+# an Elo DMA controller, such as the MPC8610 and P1022.  You will still need to
+# select a platform driver and a codec driver.
+config SND_SOC_POWERPC_SSI
        tristate
-       depends on MPC8610
+       depends on FSL_SOC
 
 config SND_SOC_MPC8610_HPCD
        tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
        # I2C is necessary for the CS4270 driver
        depends on MPC8610_HPCD && I2C
-       select SND_SOC_MPC8610
+       select SND_SOC_POWERPC_SSI
        select SND_SOC_CS4270
        select SND_SOC_CS4270_VD33_ERRATA
        default y if MPC8610_HPCD
        help
          Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
 
+config SND_SOC_P1022_DS
+       tristate "ALSA SoC support for the Freescale P1022 DS board"
+       # I2C is necessary for the WM8776 driver
+       depends on P1022_DS && I2C
+       select SND_SOC_POWERPC_SSI
+       select SND_SOC_WM8776
+       default y if P1022_DS
+       help
+         Say Y if you want to enable audio on the Freescale P1022 DS board.
+         This will also include the Wolfson Microelectronics WM8776 codec
+         driver.
+
 config SND_SOC_MPC5200_I2S
        tristate "Freescale MPC5200 PSC in I2S mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
index a83a739..b4a38c0 100644 (file)
@@ -1,14 +1,15 @@
-# Simple machine driver that extracts configuration from the OF device tree
-obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
-
 # MPC8610 HPCD Machine Support
 snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o
 obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
 
-# MPC8610 Platform Support
+# P1022 DS Machine Support
+snd-soc-p1022-ds-objs := p1022_ds.o
+obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
+
+# Freescale PowerPC SSI/DMA Platform Support
 snd-soc-fsl-ssi-objs := fsl_ssi.o
 snd-soc-fsl-dma-objs := fsl_dma.o
-obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
+obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
 
 # MPC5200 Platform Support
 obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
index 1a5b8e0..53251e6 100644 (file)
@@ -24,7 +24,6 @@
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
-#include <sound/soc-of-simple.h>
 
 #include "mpc5200_dma.h"
 #include "mpc5200_psc_ac97.h"
 
 #define DRV_NAME "efika-audio-fabric"
 
-static struct snd_soc_device device;
 static struct snd_soc_card card;
 
 static struct snd_soc_dai_link efika_fabric_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 Analog",
-       .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG],
-       .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL],
+       .codec_dai_name = "stac9766-hifi-analog",
+       .cpu_dai_name = "mpc5200-psc-ac97.0",
+       .platform_name = "mpc5200-pcm-audio",
+       .codec_name = "stac9766-codec",
 },
 {
        .name = "AC97",
        .stream_name = "AC97 IEC958",
-       .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL],
-       .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF],
+       .codec_dai_name = "stac9766-hifi-IEC958",
+       .cpu_dai_name = "mpc5200-psc-ac97.1",
+       .platform_name = "mpc5200-pcm-audio",
+       .codec_name = "stac9766-codec",
 },
 };
 
@@ -58,13 +60,10 @@ static __init int efika_fabric_init(void)
        if (!of_machine_is_compatible("bplan,efika"))
                return -ENODEV;
 
-       card.platform = &mpc5200_audio_dma_platform;
        card.name = "Efika";
        card.dai_link = efika_fabric_dai;
        card.num_links = ARRAY_SIZE(efika_fabric_dai);
 
-       device.card = &card;
-       device.codec_dev = &soc_codec_dev_stac9766;
 
        pdev = platform_device_alloc("soc-audio", 1);
        if (!pdev) {
@@ -72,8 +71,7 @@ static __init int efika_fabric_init(void)
                return -ENODEV;
        }
 
-       platform_set_drvdata(pdev, &device);
-       device.dev = &pdev->dev;
+       platform_set_drvdata(pdev, &card);
 
        rc = platform_device_add(pdev);
        if (rc) {
index 410c749..4cf98c0 100644 (file)
@@ -3,10 +3,11 @@
  *
  * Author: Timur Tabi <timur@freescale.com>
  *
- * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed
- * under the terms of the GNU General Public License version 2.  This
- * program is licensed "as is" without any warranty of any kind, whether
- * express or implied.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  *
  * This driver implements ASoC support for the Elo DMA controller, which is
  * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms,
@@ -20,6 +21,9 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/gfp.h>
+#include <linux/of_platform.h>
+#include <linux/list.h>
+#include <linux/slab.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -29,6 +33,7 @@
 #include <asm/io.h>
 
 #include "fsl_dma.h"
+#include "fsl_ssi.h"   /* For the offset of stx0 and srx0 */
 
 /*
  * The formats that the DMA controller supports, which is anything
 #define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
                          SNDRV_PCM_RATE_CONTINUOUS)
 
-/* DMA global data.  This structure is used by fsl_dma_open() to determine
- * which DMA channels to assign to a substream.  Unfortunately, ASoC V1 does
- * not allow the machine driver to provide this information to the PCM
- * driver in advance, and there's no way to differentiate between the two
- * DMA controllers.  So for now, this driver only supports one SSI device
- * using two DMA channels.  We cannot support multiple DMA devices.
- *
- * ssi_stx_phys: bus address of SSI STX register
- * ssi_srx_phys: bus address of SSI SRX register
- * dma_channel: pointer to the DMA channel's registers
- * irq: IRQ for this DMA channel
- * assigned: set to 1 if that DMA channel is assigned to a substream
- */
-static struct {
+struct dma_object {
+       struct snd_soc_platform_driver dai;
        dma_addr_t ssi_stx_phys;
        dma_addr_t ssi_srx_phys;
-       struct ccsr_dma_channel __iomem *dma_channel[2];
-       unsigned int irq[2];
-       unsigned int assigned[2];
-} dma_global_data;
+       unsigned int ssi_fifo_depth;
+       struct ccsr_dma_channel __iomem *channel;
+       unsigned int irq;
+       bool assigned;
+       char path[1];
+};
 
 /*
  * The number of DMA links to use.  Two is the bare minimum, but if you
@@ -88,8 +83,6 @@ static struct {
  * structure.
  *
  * @link[]: array of link descriptors
- * @controller_id: which DMA controller (0, 1, ...)
- * @channel_id: which DMA channel on the controller (0, 1, 2, ...)
  * @dma_channel: pointer to the DMA channel's registers
  * @irq: IRQ for this DMA channel
  * @substream: pointer to the substream object, needed by the ISR
@@ -104,12 +97,11 @@ static struct {
  */
 struct fsl_dma_private {
        struct fsl_dma_link_descriptor link[NUM_DMA_LINKS];
-       unsigned int controller_id;
-       unsigned int channel_id;
        struct ccsr_dma_channel __iomem *dma_channel;
        unsigned int irq;
        struct snd_pcm_substream *substream;
        dma_addr_t ssi_sxx_phys;
+       unsigned int ssi_fifo_depth;
        dma_addr_t ld_buf_phys;
        unsigned int current_link;
        dma_addr_t dma_buf_phys;
@@ -185,13 +177,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
        struct fsl_dma_link_descriptor *link =
                &dma_private->link[dma_private->current_link];
 
-       /* Update our link descriptors to point to the next period */
-       if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               link->source_addr =
-                       cpu_to_be32(dma_private->dma_buf_next);
-       else
-               link->dest_addr =
-                       cpu_to_be32(dma_private->dma_buf_next);
+       /* Update our link descriptors to point to the next period. On a 36-bit
+        * system, we also need to update the ESAD bits.  We also set (keep) the
+        * snoop bits.  See the comments in fsl_dma_hw_params() about snooping.
+        */
+       if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               link->source_addr = cpu_to_be32(dma_private->dma_buf_next);
+#ifdef CONFIG_PHYS_64BIT
+               link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
+                       upper_32_bits(dma_private->dma_buf_next));
+#endif
+       } else {
+               link->dest_addr = cpu_to_be32(dma_private->dma_buf_next);
+#ifdef CONFIG_PHYS_64BIT
+               link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
+                       upper_32_bits(dma_private->dma_buf_next));
+#endif
+       }
 
        /* Update our variables for next time */
        dma_private->dma_buf_next += dma_private->period_size;
@@ -212,6 +214,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
 static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
 {
        struct fsl_dma_private *dma_private = dev_id;
+       struct snd_pcm_substream *substream = dma_private->substream;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct device *dev = rtd->platform->dev;
        struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
        irqreturn_t ret = IRQ_NONE;
        u32 sr, sr2 = 0;
@@ -222,11 +227,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
        sr = in_be32(&dma_channel->sr);
 
        if (sr & CCSR_DMA_SR_TE) {
-               dev_err(dma_private->substream->pcm->card->dev,
-                       "DMA transmit error (controller=%u channel=%u irq=%u\n",
-                       dma_private->controller_id,
-                       dma_private->channel_id, irq);
-               fsl_dma_abort_stream(dma_private->substream);
+               dev_err(dev, "dma transmit error\n");
+               fsl_dma_abort_stream(substream);
                sr2 |= CCSR_DMA_SR_TE;
                ret = IRQ_HANDLED;
        }
@@ -235,11 +237,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
                ret = IRQ_HANDLED;
 
        if (sr & CCSR_DMA_SR_PE) {
-               dev_err(dma_private->substream->pcm->card->dev,
-                       "DMA%u programming error (channel=%u irq=%u)\n",
-                       dma_private->controller_id,
-                       dma_private->channel_id, irq);
-               fsl_dma_abort_stream(dma_private->substream);
+               dev_err(dev, "dma programming error\n");
+               fsl_dma_abort_stream(substream);
                sr2 |= CCSR_DMA_SR_PE;
                ret = IRQ_HANDLED;
        }
@@ -253,8 +252,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
                ret = IRQ_HANDLED;
 
        if (sr & CCSR_DMA_SR_EOSI) {
-               struct snd_pcm_substream *substream = dma_private->substream;
-
                /* Tell ALSA we completed a period. */
                snd_pcm_period_elapsed(substream);
 
@@ -288,11 +285,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
  * This function is called when the codec driver calls snd_soc_new_pcms(),
  * once for each .dai_link in the machine driver's snd_soc_card
  * structure.
+ *
+ * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which
+ * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM
+ * is specified. Therefore, any DMA buffers we allocate will always be in low
+ * memory, but we support for 36-bit physical addresses anyway.
+ *
+ * Regardless of where the memory is actually allocated, since the device can
+ * technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
  */
 static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
        struct snd_pcm *pcm)
 {
-       static u64 fsl_dma_dmamask = DMA_BIT_MASK(32);
+       static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
        int ret;
 
        if (!card->dev->dma_mask)
@@ -301,25 +306,29 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = fsl_dma_dmamask;
 
-       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-               fsl_dma_hardware.buffer_bytes_max,
-               &pcm->streams[0].substream->dma_buffer);
-       if (ret) {
-               dev_err(card->dev,
-                       "Can't allocate playback DMA buffer (size=%u)\n",
-                       fsl_dma_hardware.buffer_bytes_max);
-               return -ENOMEM;
+       /* Some codecs have separate DAIs for playback and capture, so we
+        * should allocate a DMA buffer only for the streams that are valid.
+        */
+
+       if (dai->driver->playback.channels_min) {
+               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
+                       fsl_dma_hardware.buffer_bytes_max,
+                       &pcm->streams[0].substream->dma_buffer);
+               if (ret) {
+                       dev_err(card->dev, "can't alloc playback dma buffer\n");
+                       return ret;
+               }
        }
 
-       ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
-               fsl_dma_hardware.buffer_bytes_max,
-               &pcm->streams[1].substream->dma_buffer);
-       if (ret) {
-               snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
-               dev_err(card->dev,
-                       "Can't allocate capture DMA buffer (size=%u)\n",
-                       fsl_dma_hardware.buffer_bytes_max);
-               return -ENOMEM;
+       if (dai->driver->capture.channels_min) {
+               ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
+                       fsl_dma_hardware.buffer_bytes_max,
+                       &pcm->streams[1].substream->dma_buffer);
+               if (ret) {
+                       snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+                       dev_err(card->dev, "can't alloc capture dma buffer\n");
+                       return ret;
+               }
        }
 
        return 0;
@@ -390,6 +399,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
 static int fsl_dma_open(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct device *dev = rtd->platform->dev;
+       struct dma_object *dma =
+               container_of(rtd->platform->driver, struct dma_object, dai);
        struct fsl_dma_private *dma_private;
        struct ccsr_dma_channel __iomem *dma_channel;
        dma_addr_t ld_buf_phys;
@@ -407,52 +420,45 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
        ret = snd_pcm_hw_constraint_integer(runtime,
                SNDRV_PCM_HW_PARAM_PERIODS);
        if (ret < 0) {
-               dev_err(substream->pcm->card->dev, "invalid buffer size\n");
+               dev_err(dev, "invalid buffer size\n");
                return ret;
        }
 
        channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
 
-       if (dma_global_data.assigned[channel]) {
-               dev_err(substream->pcm->card->dev,
-                       "DMA channel already assigned\n");
+       if (dma->assigned) {
+               dev_err(dev, "dma channel already assigned\n");
                return -EBUSY;
        }
 
-       dma_private = dma_alloc_coherent(substream->pcm->card->dev,
-               sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL);
+       dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private),
+                                        &ld_buf_phys, GFP_KERNEL);
        if (!dma_private) {
-               dev_err(substream->pcm->card->dev,
-                       "can't allocate DMA private data\n");
+               dev_err(dev, "can't allocate dma private data\n");
                return -ENOMEM;
        }
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys;
+               dma_private->ssi_sxx_phys = dma->ssi_stx_phys;
        else
-               dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys;
+               dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
 
-       dma_private->dma_channel = dma_global_data.dma_channel[channel];
-       dma_private->irq = dma_global_data.irq[channel];
+       dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
+       dma_private->dma_channel = dma->channel;
+       dma_private->irq = dma->irq;
        dma_private->substream = substream;
        dma_private->ld_buf_phys = ld_buf_phys;
        dma_private->dma_buf_phys = substream->dma_buffer.addr;
 
-       /* We only support one DMA controller for now */
-       dma_private->controller_id = 0;
-       dma_private->channel_id = channel;
-
        ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private);
        if (ret) {
-               dev_err(substream->pcm->card->dev,
-                       "can't register ISR for IRQ %u (ret=%i)\n",
+               dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
                        dma_private->irq, ret);
-               dma_free_coherent(substream->pcm->card->dev,
-                       sizeof(struct fsl_dma_private),
+               dma_free_coherent(dev, sizeof(struct fsl_dma_private),
                        dma_private, dma_private->ld_buf_phys);
                return ret;
        }
 
-       dma_global_data.assigned[channel] = 1;
+       dma->assigned = 1;
 
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
        snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
@@ -546,13 +552,15 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_dma_private *dma_private = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct device *dev = rtd->platform->dev;
 
        /* Number of bits per sample */
-       unsigned int sample_size =
+       unsigned int sample_bits =
                snd_pcm_format_physical_width(params_format(hw_params));
 
        /* Number of bytes per frame */
-       unsigned int frame_size = 2 * (sample_size / 8);
+       unsigned int sample_bytes = sample_bits / 8;
 
        /* Bus address of SSI STX register */
        dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
@@ -592,7 +600,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
         * that offset here.  While we're at it, also tell the DMA controller
         * how much data to transfer per sample.
         */
-       switch (sample_size) {
+       switch (sample_bits) {
        case 8:
                mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
                ssi_sxx_phys += 3;
@@ -606,23 +614,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
                break;
        default:
                /* We should never get here */
-               dev_err(substream->pcm->card->dev,
-                       "unsupported sample size %u\n", sample_size);
+               dev_err(dev, "unsupported sample size %u\n", sample_bits);
                return -EINVAL;
        }
 
        /*
-        * BWC should always be a multiple of the frame size.  BWC determines
-        * how many bytes are sent/received before the DMA controller checks the
-        * SSI to see if it needs to stop.  For playback, the transmit FIFO can
-        * hold three frames, so we want to send two frames at a time. For
-        * capture, the receive FIFO is triggered when it contains one frame, so
-        * we want to receive one frame at a time.
+        * BWC determines how many bytes are sent/received before the DMA
+        * controller checks the SSI to see if it needs to stop. BWC should
+        * always be a multiple of the frame size, so that we always transmit
+        * whole frames.  Each frame occupies two slots in the FIFO.  The
+        * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two
+        * (MR[BWC] can only represent even powers of two).
+        *
+        * To simplify the process, we set BWC to the largest value that is
+        * less than or equal to the FIFO watermark.  For playback, this ensures
+        * that we transfer the maximum amount without overrunning the FIFO.
+        * For capture, this ensures that we transfer the maximum amount without
+        * underrunning the FIFO.
+        *
+        * f = SSI FIFO depth
+        * w = SSI watermark value (which equals f - 2)
+        * b = DMA bandwidth count (in bytes)
+        * s = sample size (in bytes, which equals frame_size * 2)
+        *
+        * For playback, we never transmit more than the transmit FIFO
+        * watermark, otherwise we might write more data than the FIFO can hold.
+        * The watermark is equal to the FIFO depth minus two.
+        *
+        * For capture, two equations must hold:
+        *      w > f - (b / s)
+        *      w >= b / s
+        *
+        * So, b > 2 * s, but b must also be <= s * w.  To simplify, we set
+        * b = s * w, which is equal to
+        *      (dma_private->ssi_fifo_depth - 2) * sample_bytes.
         */
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               mr |= CCSR_DMA_MR_BWC(2 * frame_size);
-       else
-               mr |= CCSR_DMA_MR_BWC(frame_size);
+       mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
 
        out_be32(&dma_channel->mr, mr);
 
@@ -631,12 +658,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
 
                link->count = cpu_to_be32(period_size);
 
-               /* Even though the DMA controller supports 36-bit addressing,
-                * for simplicity we allow only 32-bit addresses for the audio
-                * buffer itself.  This was enforced in fsl_dma_new() with the
-                * DMA mask.
-                *
-                * The snoop bit tells the DMA controller whether it should tell
+               /* The snoop bit tells the DMA controller whether it should tell
                 * the ECM to snoop during a read or write to an address. For
                 * audio, we use DMA to transfer data between memory and an I/O
                 * device (the SSI's STX0 or SRX0 register). Snooping is only
@@ -651,20 +673,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
                 * flush out the data for the previous period.  So if you
                 * increased period_bytes_min to a large enough size, you might
                 * get more performance by not snooping, and you'll still be
-                * okay.
+                * okay.  You'll need to update fsl_dma_update_pointers() also.
                 */
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        link->source_addr = cpu_to_be32(temp_addr);
-                       link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
+                       link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
+                               upper_32_bits(temp_addr));
 
                        link->dest_addr = cpu_to_be32(ssi_sxx_phys);
-                       link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
+                       link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
+                               upper_32_bits(ssi_sxx_phys));
                } else {
                        link->source_addr = cpu_to_be32(ssi_sxx_phys);
-                       link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP);
+                       link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
+                               upper_32_bits(ssi_sxx_phys));
 
                        link->dest_addr = cpu_to_be32(temp_addr);
-                       link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP);
+                       link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
+                               upper_32_bits(temp_addr));
                }
 
                temp_addr += period_size;
@@ -689,14 +715,29 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_dma_private *dma_private = runtime->private_data;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct device *dev = rtd->platform->dev;
        struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
        dma_addr_t position;
        snd_pcm_uframes_t frames;
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       /* Obtain the current DMA pointer, but don't read the ESAD bits if we
+        * only have 32-bit DMA addresses.  This function is typically called
+        * in interrupt context, so we need to optimize it.
+        */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                position = in_be32(&dma_channel->sar);
-       else
+#ifdef CONFIG_PHYS_64BIT
+               position |= (u64)(in_be32(&dma_channel->satr) &
+                                 CCSR_DMA_ATR_ESAD_MASK) << 32;
+#endif
+       } else {
                position = in_be32(&dma_channel->dar);
+#ifdef CONFIG_PHYS_64BIT
+               position |= (u64)(in_be32(&dma_channel->datr) &
+                                 CCSR_DMA_ATR_ESAD_MASK) << 32;
+#endif
+       }
 
        /*
         * When capture is started, the SSI immediately starts to fill its FIFO.
@@ -710,8 +751,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
 
        if ((position < dma_private->dma_buf_phys) ||
            (position > dma_private->dma_buf_end)) {
-               dev_err(substream->pcm->card->dev,
-                       "dma pointer is out of range, halting stream\n");
+               dev_err(dev, "dma pointer is out of range, halting stream\n");
                return SNDRV_PCM_POS_XRUN;
        }
 
@@ -772,26 +812,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_dma_private *dma_private = runtime->private_data;
-       int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct device *dev = rtd->platform->dev;
+       struct dma_object *dma =
+               container_of(rtd->platform->driver, struct dma_object, dai);
 
        if (dma_private) {
                if (dma_private->irq)
                        free_irq(dma_private->irq, dma_private);
 
                if (dma_private->ld_buf_phys) {
-                       dma_unmap_single(substream->pcm->card->dev,
-                               dma_private->ld_buf_phys,
-                               sizeof(dma_private->link), DMA_TO_DEVICE);
+                       dma_unmap_single(dev, dma_private->ld_buf_phys,
+                                        sizeof(dma_private->link),
+                                        DMA_TO_DEVICE);
                }
 
                /* Deallocate the fsl_dma_private structure */
-               dma_free_coherent(substream->pcm->card->dev,
-                       sizeof(struct fsl_dma_private),
-                       dma_private, dma_private->ld_buf_phys);
+               dma_free_coherent(dev, sizeof(struct fsl_dma_private),
+                                 dma_private, dma_private->ld_buf_phys);
                substream->runtime->private_data = NULL;
        }
 
-       dma_global_data.assigned[dir] = 0;
+       dma->assigned = 0;
 
        return 0;
 }
@@ -814,6 +856,37 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
+/**
+ * find_ssi_node -- returns the SSI node that points to his DMA channel node
+ *
+ * Although this DMA driver attempts to operate independently of the other
+ * devices, it still needs to determine some information about the SSI device
+ * that it's working with.  Unfortunately, the device tree does not contain
+ * a pointer from the DMA channel node to the SSI node -- the pointer goes the
+ * other way.  So we need to scan the device tree for SSI nodes until we find
+ * the one that points to the given DMA channel node.  It's ugly, but at least
+ * it's contained in this one function.
+ */
+static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
+{
+       struct device_node *ssi_np, *np;
+
+       for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") {
+               /* Check each DMA phandle to see if it points to us.  We
+                * assume that device_node pointers are a valid comparison.
+                */
+               np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0);
+               if (np == dma_channel_np)
+                       return ssi_np;
+
+               np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0);
+               if (np == dma_channel_np)
+                       return ssi_np;
+       }
+
+       return NULL;
+}
+
 static struct snd_pcm_ops fsl_dma_ops = {
        .open           = fsl_dma_open,
        .close          = fsl_dma_close,
@@ -823,59 +896,114 @@ static struct snd_pcm_ops fsl_dma_ops = {
        .pointer        = fsl_dma_pointer,
 };
 
-struct snd_soc_platform fsl_soc_platform = {
-       .name           = "fsl-dma",
-       .pcm_ops        = &fsl_dma_ops,
-       .pcm_new        = fsl_dma_new,
-       .pcm_free       = fsl_dma_free_dma_buffers,
-};
-EXPORT_SYMBOL_GPL(fsl_soc_platform);
+static int __devinit fsl_soc_dma_probe(struct platform_device *pdev,
+                                      const struct of_device_id *match)
+ {
+       struct dma_object *dma;
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *ssi_np;
+       struct resource res;
+       const uint32_t *iprop;
+       int ret;
 
-/**
- * fsl_dma_configure: store the DMA parameters from the fabric driver.
- *
- * This function is called by the ASoC fabric driver to give us the DMA and
- * SSI channel information.
- *
- * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI
- * data when a substream is created, so for now we need to store this data
- * into a global variable.  This means that we can only support one DMA
- * controller, and hence only one SSI.
- */
-int fsl_dma_configure(struct fsl_dma_info *dma_info)
+       /* Find the SSI node that points to us. */
+       ssi_np = find_ssi_node(np);
+       if (!ssi_np) {
+               dev_err(&pdev->dev, "cannot find parent SSI node\n");
+               return -ENODEV;
+       }
+
+       ret = of_address_to_resource(ssi_np, 0, &res);
+       if (ret) {
+               dev_err(&pdev->dev, "could not determine resources for %s\n",
+                       ssi_np->full_name);
+               of_node_put(ssi_np);
+               return ret;
+       }
+
+       dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL);
+       if (!dma) {
+               dev_err(&pdev->dev, "could not allocate dma object\n");
+               of_node_put(ssi_np);
+               return -ENOMEM;
+       }
+
+       strcpy(dma->path, np->full_name);
+       dma->dai.ops = &fsl_dma_ops;
+       dma->dai.pcm_new = fsl_dma_new;
+       dma->dai.pcm_free = fsl_dma_free_dma_buffers;
+
+       /* Store the SSI-specific information that we need */
+       dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
+       dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
+
+       iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
+       if (iprop)
+               dma->ssi_fifo_depth = *iprop;
+       else
+                /* Older 8610 DTs didn't have the fifo-depth property */
+               dma->ssi_fifo_depth = 8;
+
+       of_node_put(ssi_np);
+
+       ret = snd_soc_register_platform(&pdev->dev, &dma->dai);
+       if (ret) {
+               dev_err(&pdev->dev, "could not register platform\n");
+               kfree(dma);
+               return ret;
+       }
+
+       dma->channel = of_iomap(np, 0);
+       dma->irq = irq_of_parse_and_map(np, 0);
+
+       dev_set_drvdata(&pdev->dev, dma);
+
+       return 0;
+}
+
+static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
 {
-       static int initialized;
+       struct dma_object *dma = dev_get_drvdata(&pdev->dev);
 
-       /* We only support one DMA controller for now */
-       if (initialized)
-               return 0;
+       snd_soc_unregister_platform(&pdev->dev);
+       iounmap(dma->channel);
+       irq_dispose_mapping(dma->irq);
+       kfree(dma);
 
-       dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys;
-       dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys;
-       dma_global_data.dma_channel[0] = dma_info->dma_channel[0];
-       dma_global_data.dma_channel[1] = dma_info->dma_channel[1];
-       dma_global_data.irq[0] = dma_info->dma_irq[0];
-       dma_global_data.irq[1] = dma_info->dma_irq[1];
-       dma_global_data.assigned[0] = 0;
-       dma_global_data.assigned[1] = 0;
-
-       initialized = 1;
-       return 1;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(fsl_dma_configure);
 
-static int __init fsl_soc_platform_init(void)
+static const struct of_device_id fsl_soc_dma_ids[] = {
+       { .compatible = "fsl,ssi-dma-channel", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids);
+
+static struct of_platform_driver fsl_soc_dma_driver = {
+       .driver = {
+               .name = "fsl-pcm-audio",
+               .owner = THIS_MODULE,
+               .of_match_table = fsl_soc_dma_ids,
+       },
+       .probe = fsl_soc_dma_probe,
+       .remove = __devexit_p(fsl_soc_dma_remove),
+};
+
+static int __init fsl_soc_dma_init(void)
 {
-       return snd_soc_register_platform(&fsl_soc_platform);
+       pr_info("Freescale Elo DMA ASoC PCM Driver\n");
+
+       return of_register_platform_driver(&fsl_soc_dma_driver);
 }
-module_init(fsl_soc_platform_init);
 
-static void __exit fsl_soc_platform_exit(void)
+static void __exit fsl_soc_dma_exit(void)
 {
-       snd_soc_unregister_platform(&fsl_soc_platform);
+       of_unregister_platform_driver(&fsl_soc_dma_driver);
 }
-module_exit(fsl_soc_platform_exit);
+
+module_init(fsl_soc_dma_init);
+module_exit(fsl_soc_dma_exit);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
-MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
+MODULE_LICENSE("GPL v2");
index 385d4a4..78fee97 100644 (file)
@@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor {
        u8 res[4];      /* Reserved */
 } __attribute__ ((aligned(32), packed));
 
-/* DMA information needed to create a snd_soc_dai object
- *
- * ssi_stx_phys: bus address of SSI STX register to use
- * ssi_srx_phys: bus address of SSI SRX register to use
- * dma[0]: points to the DMA channel to use for playback
- * dma[1]: points to the DMA channel to use for capture
- * dma_irq[0]: IRQ of the DMA channel to use for playback
- * dma_irq[1]: IRQ of the DMA channel to use for capture
- */
-struct fsl_dma_info {
-       dma_addr_t ssi_stx_phys;
-       dma_addr_t ssi_srx_phys;
-       struct ccsr_dma_channel __iomem *dma_channel[2];
-       unsigned int dma_irq[2];
-};
-
-extern struct snd_soc_platform fsl_soc_platform;
-
-int fsl_dma_configure(struct fsl_dma_info *dma_info);
-
 #endif
index 762c1b8..4cc167a 100644 (file)
@@ -3,10 +3,11 @@
  *
  * Author: Timur Tabi <timur@freescale.com>
  *
- * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed
- * under the terms of the GNU General Public License version 2.  This
- * program is licensed "as is" without any warranty of any kind, whether
- * express or implied.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
 #include <linux/init.h>
@@ -15,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/of_platform.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -22,8 +24,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <asm/immap_86xx.h>
-
 #include "fsl_ssi.h"
 
 /**
 /**
  * fsl_ssi_private: per-SSI private data
  *
- * @name: short name for this device ("SSI0", "SSI1", etc)
  * @ssi: pointer to the SSI's registers
  * @ssi_phys: physical address of the SSI registers
  * @irq: IRQ of this SSI
  * @first_stream: pointer to the stream that was opened first
  * @second_stream: pointer to second stream
- * @dev: struct device pointer
  * @playback: the number of playback streams opened
  * @capture: the number of capture streams opened
  * @asynchronous: 0=synchronous mode, 1=asynchronous mode
  * @cpu_dai: the CPU DAI for this device
  * @dev_attr: the sysfs device attribute structure
  * @stats: SSI statistics
+ * @name: name for this device
  */
 struct fsl_ssi_private {
-       char name[8];
        struct ccsr_ssi __iomem *ssi;
        dma_addr_t ssi_phys;
        unsigned int irq;
        struct snd_pcm_substream *first_stream;
        struct snd_pcm_substream *second_stream;
-       struct device *dev;
        unsigned int playback;
        unsigned int capture;
        int asynchronous;
-       struct snd_soc_dai cpu_dai;
+       unsigned int fifo_depth;
+       struct snd_soc_dai_driver cpu_dai_drv;
        struct device_attribute dev_attr;
+       struct platform_device *pdev;
 
        struct {
                unsigned int rfrc;
@@ -122,6 +121,8 @@ struct fsl_ssi_private {
                unsigned int tfe1;
                unsigned int tfe0;
        } stats;
+
+       char name[1];
 };
 
 /**
@@ -280,7 +281,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
 
        /*
         * If this is the first stream opened, then request the IRQ
@@ -290,6 +291,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
                struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
                int ret;
 
+               /* The 'name' should not have any slashes in it. */
                ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
                                  ssi_private->name, ssi_private);
                if (ret < 0) {
@@ -336,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
 
                /*
                 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
-                * don't use FIFO 1.  Since the SSI only supports stereo, the
-                * watermark should never be an odd number.
+                * don't use FIFO 1.  We program the transmit water to signal a
+                * DMA transfer if there are only two (or fewer) elements left
+                * in the FIFO.  Two elements equals one frame (left channel,
+                * right channel).  This value, however, depends on the depth of
+                * the transmit buffer.
+                *
+                * We program the receive FIFO to notify us if at least two
+                * elements (one frame) have been written to the FIFO.  We could
+                * make this value larger (and maybe we should), but this way
+                * data will be written to memory as soon as it's available.
                 */
                out_be32(&ssi->sfcsr,
-                        CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2));
+                       CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
+                       CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
 
                /*
                 * We keep the SSI disabled because if we enable it, then the
@@ -422,7 +433,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
 static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
 {
-       struct fsl_ssi_private *ssi_private = cpu_dai->private_data;
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
 
        if (substream == ssi_private->first_stream) {
                struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
@@ -458,7 +469,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                           struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
 
        switch (cmd) {
@@ -497,7 +508,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
+       struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                ssi_private->playback--;
@@ -523,56 +534,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
        }
 }
 
-/**
- * fsl_ssi_set_sysclk: set the clock frequency and direction
- *
- * This function is called by the machine driver to tell us what the clock
- * frequency and direction are.
- *
- * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
- * and we don't care about the frequency.  Return an error if the direction
- * is not SND_SOC_CLOCK_IN.
- *
- * @clk_id: reserved, should be zero
- * @freq: the frequency of the given clock ID, currently ignored
- * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
- */
-static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
-                             int clk_id, unsigned int freq, int dir)
-{
-
-       return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
-}
-
-/**
- * fsl_ssi_set_fmt: set the serial format.
- *
- * This function is called by the machine driver to tell us what serial
- * format to use.
- *
- * Currently, we only support I2S mode.  Return an error if the format is
- * not SND_SOC_DAIFMT_I2S.
- *
- * @format: one of SND_SOC_DAIFMT_xxx
- */
-static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
-{
-       return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
-}
-
-/**
- * fsl_ssi_dai_template: template CPU DAI for the SSI
- */
 static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
        .startup        = fsl_ssi_startup,
        .hw_params      = fsl_ssi_hw_params,
        .shutdown       = fsl_ssi_shutdown,
        .trigger        = fsl_ssi_trigger,
-       .set_sysclk     = fsl_ssi_set_sysclk,
-       .set_fmt        = fsl_ssi_set_fmt,
 };
 
-static struct snd_soc_dai fsl_ssi_dai_template = {
+/* Template for the CPU dai driver structure */
+static struct snd_soc_dai_driver fsl_ssi_dai_template = {
        .playback = {
                /* The SSI does not support monaural audio. */
                .channels_min = 2,
@@ -640,95 +610,195 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,
 }
 
 /**
- * fsl_ssi_create_dai: create a snd_soc_dai structure
- *
- * This function is called by the machine driver to create a snd_soc_dai
- * structure.  The function creates an ssi_private object, which contains
- * the snd_soc_dai.  It also creates the sysfs statistics device.
+ * Make every character in a string lower-case
  */
-struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
+static void make_lowercase(char *s)
+{
+       char *p = s;
+       char c;
+
+       while ((c = *p)) {
+               if ((c >= 'A') && (c <= 'Z'))
+                       *p = c + ('a' - 'A');
+               p++;
+       }
+}
+
+static int __devinit fsl_ssi_probe(struct platform_device *pdev,
+                                  const struct of_device_id *match)
 {
-       struct snd_soc_dai *fsl_ssi_dai;
        struct fsl_ssi_private *ssi_private;
        int ret = 0;
-       struct device_attribute *dev_attr;
+       struct device_attribute *dev_attr = NULL;
+       struct device_node *np = pdev->dev.of_node;
+       const char *p, *sprop;
+       const uint32_t *iprop;
+       struct resource res;
+       char name[64];
+
+       /* SSIs that are not connected on the board should have a
+        *      status = "disabled"
+        * property in their device tree nodes.
+        */
+       if (!of_device_is_available(np))
+               return -ENODEV;
+
+       /* Check for a codec-handle property. */
+       if (!of_get_property(np, "codec-handle", NULL)) {
+               dev_err(&pdev->dev, "missing codec-handle property\n");
+               return -ENODEV;
+       }
 
-       ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL);
+       /* We only support the SSI in "I2S Slave" mode */
+       sprop = of_get_property(np, "fsl,mode", NULL);
+       if (!sprop || strcmp(sprop, "i2s-slave")) {
+               dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
+               return -ENODEV;
+       }
+
+       /* The DAI name is the last part of the full name of the node. */
+       p = strrchr(np->full_name, '/') + 1;
+       ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p),
+                             GFP_KERNEL);
        if (!ssi_private) {
-               dev_err(ssi_info->dev, "could not allocate DAI object\n");
-               return NULL;
+               dev_err(&pdev->dev, "could not allocate DAI object\n");
+               return -ENOMEM;
        }
-       memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
-              sizeof(struct snd_soc_dai));
 
-       fsl_ssi_dai = &ssi_private->cpu_dai;
-       dev_attr = &ssi_private->dev_attr;
+       strcpy(ssi_private->name, p);
 
-       sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id);
-       ssi_private->ssi = ssi_info->ssi;
-       ssi_private->ssi_phys = ssi_info->ssi_phys;
-       ssi_private->irq = ssi_info->irq;
-       ssi_private->dev = ssi_info->dev;
-       ssi_private->asynchronous = ssi_info->asynchronous;
+       /* Initialize this copy of the CPU DAI driver structure */
+       memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
+              sizeof(fsl_ssi_dai_template));
+       ssi_private->cpu_dai_drv.name = ssi_private->name;
 
-       dev_set_drvdata(ssi_private->dev, fsl_ssi_dai);
+       /* Get the addresses and IRQ */
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret) {
+               dev_err(&pdev->dev, "could not determine device resources\n");
+               kfree(ssi_private);
+               return ret;
+       }
+       ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start);
+       ssi_private->ssi_phys = res.start;
+       ssi_private->irq = irq_of_parse_and_map(np, 0);
+
+       /* Are the RX and the TX clocks locked? */
+       if (of_find_property(np, "fsl,ssi-asynchronous", NULL))
+               ssi_private->asynchronous = 1;
+       else
+               ssi_private->cpu_dai_drv.symmetric_rates = 1;
+
+       /* Determine the FIFO depth. */
+       iprop = of_get_property(np, "fsl,fifo-depth", NULL);
+       if (iprop)
+               ssi_private->fifo_depth = *iprop;
+       else
+                /* Older 8610 DTs didn't have the fifo-depth property */
+               ssi_private->fifo_depth = 8;
 
        /* Initialize the the device_attribute structure */
-       dev_attr->attr.name = "ssi-stats";
+       dev_attr = &ssi_private->dev_attr;
+       dev_attr->attr.name = "statistics";
        dev_attr->attr.mode = S_IRUGO;
        dev_attr->show = fsl_sysfs_ssi_show;
 
-       ret = device_create_file(ssi_private->dev, dev_attr);
+       ret = device_create_file(&pdev->dev, dev_attr);
        if (ret) {
-               dev_err(ssi_info->dev, "could not create sysfs %s file\n",
+               dev_err(&pdev->dev, "could not create sysfs %s file\n",
                        ssi_private->dev_attr.attr.name);
-               kfree(fsl_ssi_dai);
-               return NULL;
+               goto error;
        }
 
-       fsl_ssi_dai->private_data = ssi_private;
-       fsl_ssi_dai->name = ssi_private->name;
-       fsl_ssi_dai->id = ssi_info->id;
-       fsl_ssi_dai->dev = ssi_info->dev;
-       fsl_ssi_dai->symmetric_rates = 1;
+       /* Register with ASoC */
+       dev_set_drvdata(&pdev->dev, ssi_private);
+
+       ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
+               goto error;
+       }
 
-       ret = snd_soc_register_dai(fsl_ssi_dai);
-       if (ret != 0) {
-               dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
-               kfree(fsl_ssi_dai);
-               return NULL;
+       /* Trigger the machine driver's probe function.  The platform driver
+        * name of the machine driver is taken from the /model property of the
+        * device tree.  We also pass the address of the CPU DAI driver
+        * structure.
+        */
+       sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
+       /* Sometimes the model name has a "fsl," prefix, so we strip that. */
+       p = strrchr(sprop, ',');
+       if (p)
+               sprop = p + 1;
+       snprintf(name, sizeof(name), "snd-soc-%s", sprop);
+       make_lowercase(name);
+
+       ssi_private->pdev =
+               platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
+       if (IS_ERR(ssi_private->pdev)) {
+               ret = PTR_ERR(ssi_private->pdev);
+               dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
+               goto error;
        }
 
-       return fsl_ssi_dai;
+       return 0;
+
+error:
+       snd_soc_unregister_dai(&pdev->dev);
+       dev_set_drvdata(&pdev->dev, NULL);
+       if (dev_attr)
+               device_remove_file(&pdev->dev, dev_attr);
+       irq_dispose_mapping(ssi_private->irq);
+       iounmap(ssi_private->ssi);
+       kfree(ssi_private);
+
+       return ret;
 }
-EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
 
-/**
- * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
- *
- * This function undoes the operations of fsl_ssi_create_dai()
- */
-void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
+static int fsl_ssi_remove(struct platform_device *pdev)
 {
-       struct fsl_ssi_private *ssi_private =
-       container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
-
-       device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
+       struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
 
-       snd_soc_unregister_dai(&ssi_private->cpu_dai);
+       platform_device_unregister(ssi_private->pdev);
+       snd_soc_unregister_dai(&pdev->dev);
+       device_remove_file(&pdev->dev, &ssi_private->dev_attr);
 
        kfree(ssi_private);
+       dev_set_drvdata(&pdev->dev, NULL);
+
+       return 0;
 }
-EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
+
+static const struct of_device_id fsl_ssi_ids[] = {
+       { .compatible = "fsl,mpc8610-ssi", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
+
+static struct of_platform_driver fsl_ssi_driver = {
+       .driver = {
+               .name = "fsl-ssi-dai",
+               .owner = THIS_MODULE,
+               .of_match_table = fsl_ssi_ids,
+       },
+       .probe = fsl_ssi_probe,
+       .remove = fsl_ssi_remove,
+};
 
 static int __init fsl_ssi_init(void)
 {
        printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
 
-       return 0;
+       return of_register_platform_driver(&fsl_ssi_driver);
 }
+
+static void __exit fsl_ssi_exit(void)
+{
+       of_unregister_platform_driver(&fsl_ssi_driver);
+}
+
 module_init(fsl_ssi_init);
+module_exit(fsl_ssi_exit);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
 MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index eade01f..2173000 100644 (file)
@@ -196,31 +196,5 @@ struct ccsr_ssi {
 #define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)
 #define CCSR_SSI_SOR_SYNRST            0x00000001
 
-/* Instantiation data for an SSI interface
- *
- * This structure contains all the information that the the SSI driver needs
- * to instantiate an SSI interface with ALSA.  The machine driver should
- * create this structure, fill it in, call fsl_ssi_create_dai(), and then
- * delete the structure.
- *
- * id: which SSI this is (0, 1, etc. )
- * ssi: pointer to the SSI's registers
- * ssi_phys: physical address of the SSI registers
- * irq: IRQ of this SSI
- * dev: struct device, used to create the sysfs statistics file
- * asynchronous: 0=synchronous mode, 1=asynchronous mode
-*/
-struct fsl_ssi_info {
-       unsigned int id;
-       struct ccsr_ssi __iomem *ssi;
-       dma_addr_t ssi_phys;
-       unsigned int irq;
-       struct device *dev;
-       int asynchronous;
-};
-
-struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
-void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai);
-
 #endif
 
index 3dcd146..dce6b55 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
 #include <sound/soc.h>
 
@@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream)
 static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
        struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
@@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct psc_dma_stream *s;
        int rc;
 
@@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
 static int psc_dma_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct psc_dma_stream *s;
 
        dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
@@ -264,7 +266,7 @@ static snd_pcm_uframes_t
 psc_dma_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct psc_dma_stream *s;
        dma_addr_t count;
 
@@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
                           struct snd_pcm *pcm)
 {
        struct snd_soc_pcm_runtime *rtd = pcm->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        size_t size = psc_dma_hardware.buffer_bytes_max;
        int rc = 0;
 
-       dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
+       dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
                card, dai, pcm);
 
        if (!card->dev->dma_mask)
@@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
                        goto capture_alloc_err;
        }
 
-       if (rtd->socdev->card->codec->ac97)
-               rtd->socdev->card->codec->ac97->private_data = psc_dma;
+       if (rtd->codec->ac97)
+               rtd->codec->ac97->private_data = psc_dma;
 
        return 0;
 
@@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm)
        struct snd_pcm_substream *substream;
        int stream;
 
-       dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm);
+       dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm);
 
        for (stream = 0; stream < 2; stream++) {
                substream = pcm->streams[stream].substream;
@@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm)
        }
 }
 
-struct snd_soc_platform mpc5200_audio_dma_platform = {
-       .name           = "mpc5200-psc-audio",
-       .pcm_ops        = &psc_dma_ops,
+static struct snd_soc_platform_driver mpc5200_audio_dma_platform = {
+       .ops            = &psc_dma_ops,
        .pcm_new        = &psc_dma_new,
        .pcm_free       = &psc_dma_free,
 };
-EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform);
 
-int mpc5200_audio_dma_create(struct platform_device *op)
+static int mpc5200_hpcd_probe(struct of_device *op,
+               const struct of_device_id *match)
 {
        phys_addr_t fifo;
        struct psc_dma *psc_dma;
@@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct platform_device *op)
        dev_set_drvdata(&op->dev, psc_dma);
 
        /* Tell the ASoC OF helpers about it */
-       return snd_soc_register_platform(&mpc5200_audio_dma_platform);
+       return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform);
 out_irq:
        free_irq(psc_dma->irq, psc_dma);
        free_irq(psc_dma->capture.irq, &psc_dma->capture);
@@ -486,15 +487,14 @@ out_unmap:
        iounmap(regs);
        return ret;
 }
-EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
 
-int mpc5200_audio_dma_destroy(struct platform_device *op)
+static int mpc5200_hpcd_remove(struct of_device *op)
 {
        struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
 
        dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
 
-       snd_soc_unregister_platform(&mpc5200_audio_dma_platform);
+       snd_soc_unregister_platform(&op->dev);
 
        bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
        bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
@@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct platform_device *op)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy);
+
+static struct of_device_id mpc5200_hpcd_match[] = {
+       {
+               .compatible = "fsl,mpc5200-pcm",
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match);
+
+static struct of_platform_driver mpc5200_hpcd_of_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "mpc5200-pcm-audio",
+       .match_table    = mpc5200_hpcd_match,
+       .probe          = mpc5200_hpcd_probe,
+       .remove         = mpc5200_hpcd_remove,
+};
+
+static int __init mpc5200_hpcd_init(void)
+{
+       return of_register_platform_driver(&mpc5200_hpcd_of_driver);
+}
+
+static void __exit mpc5200_hpcd_exit(void)
+{
+       of_unregister_platform_driver(&mpc5200_hpcd_of_driver);
+}
+
+module_init(mpc5200_hpcd_init);
+module_exit(mpc5200_hpcd_exit);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
 MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
index ca99586..a3c0cd5 100644 (file)
@@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
        return &psc_dma->playback;
 }
 
-int mpc5200_audio_dma_create(struct platform_device *op);
-int mpc5200_audio_dma_destroy(struct platform_device *op);
-
-extern struct snd_soc_platform mpc5200_audio_dma_platform;
-
 #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */
index a956023..40acc8e 100644 (file)
@@ -143,7 +143,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *cpu_dai)
 {
-       struct psc_dma *psc_dma = cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
        struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
 
        dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -166,7 +166,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *cpu_dai)
 {
-       struct psc_dma *psc_dma = cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
 
        dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
 
@@ -181,8 +181,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
 static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
                                                        struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai);
        struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
 
        switch (cmd) {
@@ -207,10 +206,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-static int psc_ac97_probe(struct platform_device *pdev,
-                                       struct snd_soc_dai *cpu_dai)
+static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)
 {
-       struct psc_dma *psc_dma = cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
        struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
 
        /* Go */
@@ -237,9 +235,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = {
        .hw_params      = psc_ac97_hw_digital_params,
 };
 
-struct snd_soc_dai psc_ac97_dai[] = {
+static struct snd_soc_dai_driver psc_ac97_dai[] = {
 {
-       .name   = "AC97",
        .ac97_control = 1,
        .probe  = psc_ac97_probe,
        .playback = {
@@ -257,7 +254,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
        .ops = &psc_ac97_analog_ops,
 },
 {
-       .name   = "SPDIF",
        .ac97_control = 1,
        .playback = {
                .channels_min   = 1,
@@ -268,7 +264,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
        },
        .ops = &psc_ac97_digital_ops,
 } };
-EXPORT_SYMBOL_GPL(psc_ac97_dai);
 
 
 
@@ -280,18 +275,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai);
 static int __devinit psc_ac97_of_probe(struct platform_device *op,
                                      const struct of_device_id *match)
 {
-       int rc, i;
+       int rc;
        struct snd_ac97 ac97;
        struct mpc52xx_psc __iomem *regs;
 
-       rc = mpc5200_audio_dma_create(op);
-       if (rc != 0)
-               return rc;
-
-       for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
-               psc_ac97_dai[i].dev = &op->dev;
-
-       rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
+       rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
        if (rc != 0) {
                dev_err(&op->dev, "Failed to register DAI\n");
                return rc;
@@ -301,9 +289,6 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
        regs = psc_dma->psc_regs;
        ac97.private_data = psc_dma;
 
-       for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
-               psc_ac97_dai[i].private_data = psc_dma;
-
        psc_dma->imr = 0;
        out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
 
@@ -319,7 +304,8 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
 
 static int __devexit psc_ac97_of_remove(struct platform_device *op)
 {
-       return mpc5200_audio_dma_destroy(op);
+       snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
+       return 0;
 }
 
 /* Match table for of_platform binding */
index 4bc18c3..e881e78 100644 (file)
@@ -7,8 +7,6 @@
 #ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
 #define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
 
-extern struct snd_soc_dai psc_ac97_dai[];
-
 #define MPC5200_AC97_NORMAL 0
 #define MPC5200_AC97_SPDIF 1
 
index 534f04c..74ffed4 100644 (file)
@@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        u32 mode;
 
        dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
 static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
                              int clk_id, unsigned int freq, int dir)
 {
-       struct psc_dma *psc_dma = cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
        dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
                                cpu_dai, dir);
        return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
@@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
  */
 static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
 {
-       struct psc_dma *psc_dma = cpu_dai->private_data;
+       struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
        dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
                                cpu_dai, format);
        return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
@@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = {
        .set_fmt        = psc_i2s_set_fmt,
 };
 
-struct snd_soc_dai psc_i2s_dai[] = {{
-       .name   = "I2S",
+static struct snd_soc_dai_driver psc_i2s_dai[] = {{
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
@@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{
        },
        .ops = &psc_i2s_dai_ops,
 } };
-EXPORT_SYMBOL_GPL(psc_i2s_dai);
 
 /* ---------------------------------------------------------------------
  * OF platform bus binding code:
@@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
        struct psc_dma *psc_dma;
        struct mpc52xx_psc __iomem *regs;
 
-       rc = mpc5200_audio_dma_create(op);
-       if (rc != 0)
-               return rc;
-
-       rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
+       rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
        if (rc != 0) {
                pr_err("Failed to register DAI\n");
                return 0;
@@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
 
 static int __devexit psc_i2s_of_remove(struct platform_device *op)
 {
-       return mpc5200_audio_dma_destroy(op);
+       snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
+       return 0;
 }
 
 /* Match table for of_platform binding */
index 3b13b8d..0d7dcf1 100644 (file)
@@ -1,85 +1,97 @@
 /**
- * Freescale MPC8610HPCD ALSA SoC Fabric driver
+ * Freescale MPC8610HPCD ALSA SoC Machine driver
  *
  * Author: Timur Tabi <timur@freescale.com>
  *
- * Copyright 2007-2008 Freescale Semiconductor, Inc.  This file is licensed
- * under the terms of the GNU General Public License version 2.  This
- * program is licensed "as is" without any warranty of any kind, whether
- * express or implied.
+ * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
  */
 
-#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/slab.h>
 #include <sound/soc.h>
-#include <asm/immap_86xx.h>
+#include <asm/fsl_guts.h>
 
-#include "../codecs/cs4270.h"
 #include "fsl_dma.h"
 #include "fsl_ssi.h"
 
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+#define DAI_NAME_SIZE  32
+
 /**
- * mpc8610_hpcd_data: fabric-specific ASoC device data
+ * mpc8610_hpcd_data: machine-specific ASoC device data
  *
  * This structure contains data for a single sound platform device on an
  * MPC8610 HPCD.  Some of the data is taken from the device tree.
  */
 struct mpc8610_hpcd_data {
-       struct snd_soc_device sound_devdata;
-       struct snd_soc_dai_link dai;
-       struct snd_soc_card machine;
+       struct snd_soc_dai_link dai[2];
+       struct snd_soc_card card;
        unsigned int dai_format;
        unsigned int codec_clk_direction;
        unsigned int cpu_clk_direction;
        unsigned int clk_frequency;
-       struct ccsr_guts __iomem *guts;
-       struct ccsr_ssi __iomem *ssi;
-       unsigned int ssi_id;            /* 0 = SSI1, 1 = SSI2, etc */
-       unsigned int ssi_irq;
-       unsigned int dma_id;            /* 0 = DMA1, 1 = DMA2, etc */
-       unsigned int dma_irq[2];
-       struct ccsr_dma_channel __iomem *dma[2];
+       unsigned int ssi_id;            /* 0 = SSI1, 1 = SSI2, etc */
+       unsigned int dma_id[2];         /* 0 = DMA1, 1 = DMA2, etc */
        unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+       char codec_dai_name[DAI_NAME_SIZE];
+       char codec_name[DAI_NAME_SIZE];
+       char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
 };
 
 /**
  * mpc8610_hpcd_machine_probe: initialize the board
  *
- * This function is called when platform_device_add() is called.  It is used
- * to initialize the board-specific hardware.
+ * This function is used to initialize the board-specific hardware.
  *
  * Here we program the DMACR and PMUXCR registers.
  */
 static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
 {
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
        struct mpc8610_hpcd_data *machine_data =
-               sound_device->dev.platform_data;
+               container_of(card, struct mpc8610_hpcd_data, card);
+       struct ccsr_guts_86xx __iomem *guts;
 
-       /* Program the signal routing between the SSI and the DMA */
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI);
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI);
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
 
-       guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[0], 0);
-       guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[1], 0);
+       /* Program the signal routing between the SSI and the DMA */
+       guts_set_dmacr(guts, machine_data->dma_id[0],
+                      machine_data->dma_channel_id[0],
+                      CCSR_GUTS_DMACR_DEV_SSI);
+       guts_set_dmacr(guts, machine_data->dma_id[1],
+                      machine_data->dma_channel_id[1],
+                      CCSR_GUTS_DMACR_DEV_SSI);
+
+       guts_set_pmuxcr_dma(guts, machine_data->dma_id[0],
+                           machine_data->dma_channel_id[0], 0);
+       guts_set_pmuxcr_dma(guts, machine_data->dma_id[1],
+                           machine_data->dma_channel_id[1], 0);
 
        switch (machine_data->ssi_id) {
        case 0:
-               clrsetbits_be32(&machine_data->guts->pmuxcr,
+               clrsetbits_be32(&guts->pmuxcr,
                        CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI);
                break;
        case 1:
-               clrsetbits_be32(&machine_data->guts->pmuxcr,
+               clrsetbits_be32(&guts->pmuxcr,
                        CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI);
                break;
        }
 
+       iounmap(guts);
+
        return 0;
 }
 
@@ -93,38 +105,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
 static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
 {
        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 mpc8610_hpcd_data *machine_data =
-               rtd->socdev->dev->platform_data;
+               container_of(rtd->card, struct mpc8610_hpcd_data, card);
+       struct device *dev = rtd->card->dev;
        int ret = 0;
 
-       /* Tell the CPU driver what the serial protocol is. */
-       ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format);
-       if (ret < 0) {
-               dev_err(substream->pcm->card->dev,
-                       "could not set CPU driver audio format\n");
-               return ret;
-       }
-
        /* Tell the codec driver what the serial protocol is. */
-       ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format);
+       ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format);
        if (ret < 0) {
-               dev_err(substream->pcm->card->dev,
-                       "could not set codec driver audio format\n");
-               return ret;
-       }
-
-       /*
-        * Tell the CPU driver what the clock frequency is, and whether it's a
-        * slave or master.
-        */
-       ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
-                                       machine_data->clk_frequency,
-                                       machine_data->cpu_clk_direction);
-       if (ret < 0) {
-               dev_err(substream->pcm->card->dev,
-                       "could not set CPU driver clock parameters\n");
+               dev_err(dev, "could not set codec driver audio format\n");
                return ret;
        }
 
@@ -132,12 +121,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
         * Tell the codec driver what the MCLK frequency is, and whether it's
         * a slave or master.
         */
-       ret = snd_soc_dai_set_sysclk(codec_dai, 0,
-                                       machine_data->clk_frequency,
-                                       machine_data->codec_clk_direction);
+       ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0,
+                                    machine_data->clk_frequency,
+                                    machine_data->codec_clk_direction);
        if (ret < 0) {
-               dev_err(substream->pcm->card->dev,
-                       "could not set codec driver clock params\n");
+               dev_err(dev, "could not set codec driver clock params\n");
                return ret;
        }
 
@@ -150,116 +138,255 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
  * This function is called to remove the sound device for one SSI.  We
  * de-program the DMACR and PMUXCR register.
  */
-int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
+static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
 {
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
        struct mpc8610_hpcd_data *machine_data =
-               sound_device->dev.platform_data;
+               container_of(card, struct mpc8610_hpcd_data, card);
+       struct ccsr_guts_86xx __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
 
        /* Restore the signal routing */
 
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[0], 0);
-       guts_set_dmacr(machine_data->guts, machine_data->dma_id,
-               machine_data->dma_channel_id[1], 0);
+       guts_set_dmacr(guts, machine_data->dma_id[0],
+                      machine_data->dma_channel_id[0], 0);
+       guts_set_dmacr(guts, machine_data->dma_id[1],
+                      machine_data->dma_channel_id[1], 0);
 
        switch (machine_data->ssi_id) {
        case 0:
-               clrsetbits_be32(&machine_data->guts->pmuxcr,
+               clrsetbits_be32(&guts->pmuxcr,
                        CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
                break;
        case 1:
-               clrsetbits_be32(&machine_data->guts->pmuxcr,
+               clrsetbits_be32(&guts->pmuxcr,
                        CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);
                break;
        }
 
+       iounmap(guts);
+
        return 0;
 }
 
 /**
- * mpc8610_hpcd_ops: ASoC fabric driver operations
+ * mpc8610_hpcd_ops: ASoC machine driver operations
  */
 static struct snd_soc_ops mpc8610_hpcd_ops = {
        .startup = mpc8610_hpcd_startup,
 };
 
 /**
- * mpc8610_hpcd_probe: OF probe function for the fabric driver
+ * get_node_by_phandle_name - get a node by its phandle name
  *
- * This function gets called when an SSI node is found in the device tree.
+ * This function takes a node, the name of a property in that node, and a
+ * compatible string.  Assuming the property is a phandle to another node,
+ * it returns that node, (optionally) if that node is compatible.
  *
- * Although this is a fabric driver, the SSI node is the "master" node with
- * respect to audio hardware connections.  Therefore, we create a new ASoC
- * device for each new SSI node that has a codec attached.
+ * If the property is not a phandle, or the node it points to is not compatible
+ * with the specific string, then NULL is returned.
+ */
+static struct device_node *get_node_by_phandle_name(struct device_node *np,
+                                              const char *name,
+                                              const char *compatible)
+{
+       const phandle *ph;
+       int len;
+
+       ph = of_get_property(np, name, &len);
+       if (!ph || (len != sizeof(phandle)))
+               return NULL;
+
+       np = of_find_node_by_phandle(*ph);
+       if (!np)
+               return NULL;
+
+       if (compatible && !of_device_is_compatible(np, compatible)) {
+               of_node_put(np);
+               return NULL;
+       }
+
+       return np;
+}
+
+/**
+ * get_parent_cell_index -- return the cell-index of the parent of a node
+ *
+ * Return the value of the cell-index property of the parent of the given
+ * node.  This is used for DMA channel nodes that need to know the DMA ID
+ * of the controller they are on.
+ */
+static int get_parent_cell_index(struct device_node *np)
+{
+       struct device_node *parent = of_get_parent(np);
+       const u32 *iprop;
+
+       if (!parent)
+               return -1;
+
+       iprop = of_get_property(parent, "cell-index", NULL);
+       of_node_put(parent);
+
+       if (!iprop)
+               return -1;
+
+       return *iprop;
+}
+
+/**
+ * codec_node_dev_name - determine the dev_name for a codec node
  *
- * FIXME: Currently, we only support one DMA controller, so if there are
- * multiple SSI nodes with codecs, only the first will be supported.
+ * This function determines the dev_name for an I2C node.  This is the name
+ * that would be returned by dev_name() if this device_node were part of a
+ * 'struct device'  It's ugly and hackish, but it works.
  *
- * FIXME: Even if we did support multiple DMA controllers, we have no
- * mechanism for assigning DMA controllers and channels to the individual
- * SSI devices.  We also probably aren't compatible with the generic Elo DMA
- * device driver.
+ * The dev_name for such devices include the bus number and I2C address. For
+ * example, "cs4270-codec.0-004f".
  */
-static int mpc8610_hpcd_probe(struct platform_device *ofdev,
-       const struct of_device_id *match)
+static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
 {
-       struct device_node *np = ofdev->dev.of_node;
-       struct device_node *codec_np = NULL;
-       struct device_node *guts_np = NULL;
-       struct device_node *dma_np = NULL;
-       struct device_node *dma_channel_np = NULL;
-       const phandle *codec_ph;
-       const char *sprop;
        const u32 *iprop;
+       int bus, addr;
+       char temp[DAI_NAME_SIZE];
+
+       of_modalias_node(np, temp, DAI_NAME_SIZE);
+
+       iprop = of_get_property(np, "reg", NULL);
+       if (!iprop)
+               return -EINVAL;
+
+       addr = *iprop;
+
+       bus = get_parent_cell_index(np);
+       if (bus < 0)
+               return bus;
+
+       snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+
+       return 0;
+}
+
+static int get_dma_channel(struct device_node *ssi_np,
+                          const char *compatible,
+                          struct snd_soc_dai_link *dai,
+                          unsigned int *dma_channel_id,
+                          unsigned int *dma_id)
+{
        struct resource res;
+       struct device_node *dma_channel_np;
+       const u32 *iprop;
+       int ret;
+
+       dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+                                                 "fsl,ssi-dma-channel");
+       if (!dma_channel_np)
+               return -EINVAL;
+
+       /* Determine the dev_name for the device_node.  This code mimics the
+        * behavior of of_device_make_bus_id(). We need this because ASoC uses
+        * the dev_name() of the device to match the platform (DMA) device with
+        * the CPU (SSI) device.  It's all ugly and hackish, but it works (for
+        * now).
+        *
+        * dai->platform name should already point to an allocated buffer.
+        */
+       ret = of_address_to_resource(dma_channel_np, 0, &res);
+       if (ret)
+               return ret;
+       snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
+                (unsigned long long) res.start, dma_channel_np->name);
+
+       iprop = of_get_property(dma_channel_np, "cell-index", NULL);
+       if (!iprop) {
+               of_node_put(dma_channel_np);
+               return -EINVAL;
+       }
+
+       *dma_channel_id = *iprop;
+       *dma_id = get_parent_cell_index(dma_channel_np);
+       of_node_put(dma_channel_np);
+
+       return 0;
+}
+
+/**
+ * mpc8610_hpcd_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections.  Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int mpc8610_hpcd_probe(struct platform_device *pdev)
+{
+       struct device *dev = pdev->dev.parent;
+       /* ssi_pdev is the platform device for the SSI node that probed us */
+       struct platform_device *ssi_pdev =
+               container_of(dev, struct platform_device, dev);
+       struct device_node *np = ssi_pdev->dev.of_node;
+       struct device_node *codec_np = NULL;
        struct platform_device *sound_device = NULL;
        struct mpc8610_hpcd_data *machine_data;
-       struct fsl_ssi_info ssi_info;
-       struct fsl_dma_info dma_info;
        int ret = -ENODEV;
-       unsigned int playback_dma_channel;
-       unsigned int capture_dma_channel;
+       const char *sprop;
+       const u32 *iprop;
+
+       /* We are only interested in SSIs with a codec phandle in them,
+        * so let's make sure this SSI has one. The MPC8610 HPCD only
+        * knows about the CS4270 codec, so reject anything else.
+        */
+       codec_np = get_node_by_phandle_name(np, "codec-handle",
+                                           "cirrus,cs4270");
+       if (!codec_np) {
+               dev_err(dev, "invalid codec node\n");
+               return -EINVAL;
+       }
 
        machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
        if (!machine_data)
                return -ENOMEM;
 
-       memset(&ssi_info, 0, sizeof(ssi_info));
-       memset(&dma_info, 0, sizeof(dma_info));
+       machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+       machine_data->dai[0].ops = &mpc8610_hpcd_ops;
 
-       ssi_info.dev = &ofdev->dev;
-
-       /*
-        * We are only interested in SSIs with a codec phandle in them, so let's
-        * make sure this SSI has one.
-        */
-       codec_ph = of_get_property(np, "codec-handle", NULL);
-       if (!codec_ph)
+       /* Determine the codec name, it will be used as the codec DAI name */
+       ret = codec_node_dev_name(codec_np, machine_data->codec_name,
+                                 DAI_NAME_SIZE);
+       if (ret) {
+               dev_err(&pdev->dev, "invalid codec node %s\n",
+                       codec_np->full_name);
+               ret = -EINVAL;
                goto error;
+       }
+       machine_data->dai[0].codec_name = machine_data->codec_name;
 
-       codec_np = of_find_node_by_phandle(*codec_ph);
-       if (!codec_np)
-               goto error;
+       /* The DAI name from the codec (snd_soc_dai_driver.name) */
+       machine_data->dai[0].codec_dai_name = "cs4270-hifi";
 
-       /* The MPC8610 HPCD only knows about the CS4270 codec, so reject
-          anything else. */
-       if (!of_device_is_compatible(codec_np, "cirrus,cs4270"))
-               goto error;
+       /* We register two DAIs per SSI, one for playback and the other for
+        * capture.  Currently, we only support codecs that have one DAI for
+        * both playback and capture.
+        */
+       memcpy(&machine_data->dai[1], &machine_data->dai[0],
+              sizeof(struct snd_soc_dai_link));
 
        /* Get the device ID */
        iprop = of_get_property(np, "cell-index", NULL);
        if (!iprop) {
-               dev_err(&ofdev->dev, "cell-index property not found\n");
+               dev_err(&pdev->dev, "cell-index property not found\n");
                ret = -EINVAL;
                goto error;
        }
        machine_data->ssi_id = *iprop;
-       ssi_info.id = *iprop;
 
        /* Get the serial format and clock direction. */
        sprop = of_get_property(np, "fsl,mode", NULL);
        if (!sprop) {
-               dev_err(&ofdev->dev, "fsl,mode property not found\n");
+               dev_err(&pdev->dev, "fsl,mode property not found\n");
                ret = -EINVAL;
                goto error;
        }
@@ -269,15 +396,14 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
                machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
 
-               /*
-                * In i2s-slave mode, the codec has its own clock source, so we
+               /* In i2s-slave mode, the codec has its own clock source, so we
                 * need to get the frequency from the device tree and pass it to
                 * the codec driver.
                 */
                iprop = of_get_property(codec_np, "clock-frequency", NULL);
                if (!iprop || !*iprop) {
-                       dev_err(&ofdev->dev, "codec bus-frequency property "
-                               "is missing or invalid\n");
+                       dev_err(&pdev->dev, "codec bus-frequency "
+                               "property is missing or invalid\n");
                        ret = -EINVAL;
                        goto error;
                }
@@ -311,317 +437,153 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
                machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
                machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
        } else {
-               dev_err(&ofdev->dev,
-                       "unrecognized fsl,mode property \"%s\"\n", sprop);
+               dev_err(&pdev->dev,
+                       "unrecognized fsl,mode property '%s'\n", sprop);
                ret = -EINVAL;
                goto error;
        }
 
        if (!machine_data->clk_frequency) {
-               dev_err(&ofdev->dev, "unknown clock frequency\n");
+               dev_err(&pdev->dev, "unknown clock frequency\n");
                ret = -EINVAL;
                goto error;
        }
 
-       /* Read the SSI information from the device tree */
-       ret = of_address_to_resource(np, 0, &res);
+       /* Find the playback DMA channel to use. */
+       machine_data->dai[0].platform_name = machine_data->platform_name[0];
+       ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0],
+                             &machine_data->dma_channel_id[0],
+                             &machine_data->dma_id[0]);
        if (ret) {
-               dev_err(&ofdev->dev, "could not obtain SSI address\n");
-               goto error;
-       }
-       if (!res.start) {
-               dev_err(&ofdev->dev, "invalid SSI address\n");
-               goto error;
-       }
-       ssi_info.ssi_phys = res.start;
-
-       machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi));
-       if (!machine_data->ssi) {
-               dev_err(&ofdev->dev, "could not map SSI address %x\n",
-                       ssi_info.ssi_phys);
-               ret = -EINVAL;
-               goto error;
-       }
-       ssi_info.ssi = machine_data->ssi;
-
-
-       /* Get the IRQ of the SSI */
-       machine_data->ssi_irq = irq_of_parse_and_map(np, 0);
-       if (!machine_data->ssi_irq) {
-               dev_err(&ofdev->dev, "could not get SSI IRQ\n");
-               ret = -EINVAL;
-               goto error;
-       }
-       ssi_info.irq = machine_data->ssi_irq;
-
-       /* Do we want to use asynchronous mode? */
-       ssi_info.asynchronous =
-               of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0;
-       if (ssi_info.asynchronous)
-               dev_info(&ofdev->dev, "using asynchronous mode\n");
-
-       /* Map the global utilities registers. */
-       guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
-       if (!guts_np) {
-               dev_err(&ofdev->dev, "could not obtain address of GUTS\n");
-               ret = -EINVAL;
-               goto error;
-       }
-       machine_data->guts = of_iomap(guts_np, 0);
-       of_node_put(guts_np);
-       if (!machine_data->guts) {
-               dev_err(&ofdev->dev, "could not map GUTS\n");
-               ret = -EINVAL;
-               goto error;
-       }
-
-       /* Find the DMA channels to use.  Both SSIs need to use the same DMA
-        * controller, so let's use DMA#1.
-        */
-       for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") {
-               iprop = of_get_property(dma_np, "cell-index", NULL);
-               if (iprop && (*iprop == 0)) {
-                       of_node_put(dma_np);
-                       break;
-               }
-       }
-       if (!dma_np) {
-               dev_err(&ofdev->dev, "could not find DMA node\n");
-               ret = -EINVAL;
-               goto error;
-       }
-       machine_data->dma_id = *iprop;
-
-       /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA
-        * channels 2 and 3.  This is just how the MPC8610 is wired
-        * internally.
-        */
-       playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2;
-       capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3;
-
-       /*
-        * Find the DMA channels to use.
-        */
-       while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) {
-               iprop = of_get_property(dma_channel_np, "cell-index", NULL);
-               if (iprop && (*iprop == playback_dma_channel)) {
-                       /* dma_channel[0] and dma_irq[0] are for playback */
-                       dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0);
-                       dma_info.dma_irq[0] =
-                               irq_of_parse_and_map(dma_channel_np, 0);
-                       machine_data->dma_channel_id[0] = *iprop;
-                       continue;
-               }
-               if (iprop && (*iprop == capture_dma_channel)) {
-                       /* dma_channel[1] and dma_irq[1] are for capture */
-                       dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0);
-                       dma_info.dma_irq[1] =
-                               irq_of_parse_and_map(dma_channel_np, 0);
-                       machine_data->dma_channel_id[1] = *iprop;
-                       continue;
-               }
-       }
-       if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] ||
-           !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) {
-               dev_err(&ofdev->dev, "could not find DMA channels\n");
-               ret = -EINVAL;
+               dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
                goto error;
        }
 
-       dma_info.ssi_stx_phys = ssi_info.ssi_phys +
-               offsetof(struct ccsr_ssi, stx0);
-       dma_info.ssi_srx_phys = ssi_info.ssi_phys +
-               offsetof(struct ccsr_ssi, srx0);
-
-       /* We have the DMA information, so tell the DMA driver what it is */
-       if (!fsl_dma_configure(&dma_info)) {
-               dev_err(&ofdev->dev, "could not instantiate DMA device\n");
-               ret = -EBUSY;
+       /* Find the capture DMA channel to use. */
+       machine_data->dai[1].platform_name = machine_data->platform_name[1];
+       ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1],
+                             &machine_data->dma_channel_id[1],
+                             &machine_data->dma_id[1]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
                goto error;
        }
 
-       /*
-        * Initialize our DAI data structure.  We should probably get this
-        * information from the device tree.
-        */
-       machine_data->dai.name = "CS4270";
-       machine_data->dai.stream_name = "CS4270";
-
-       machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info);
-       machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */
-       machine_data->dai.ops = &mpc8610_hpcd_ops;
+       /* Initialize our DAI data structure.  */
+       machine_data->dai[0].stream_name = "playback";
+       machine_data->dai[1].stream_name = "capture";
+       machine_data->dai[0].name = machine_data->dai[0].stream_name;
+       machine_data->dai[1].name = machine_data->dai[1].stream_name;
 
-       machine_data->machine.probe = mpc8610_hpcd_machine_probe;
-       machine_data->machine.remove = mpc8610_hpcd_machine_remove;
-       machine_data->machine.name = "MPC8610 HPCD";
-       machine_data->machine.num_links = 1;
-       machine_data->machine.dai_link = &machine_data->dai;
+       machine_data->card.probe = mpc8610_hpcd_machine_probe;
+       machine_data->card.remove = mpc8610_hpcd_machine_remove;
+       machine_data->card.name = pdev->name; /* The platform driver name */
+       machine_data->card.num_links = 2;
+       machine_data->card.dai_link = machine_data->dai;
 
        /* Allocate a new audio platform device structure */
        sound_device = platform_device_alloc("soc-audio", -1);
        if (!sound_device) {
-               dev_err(&ofdev->dev, "platform device allocation failed\n");
+               dev_err(&pdev->dev, "platform device alloc failed\n");
                ret = -ENOMEM;
                goto error;
        }
 
-       machine_data->sound_devdata.card = &machine_data->machine;
-       machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
-       machine_data->machine.platform = &fsl_soc_platform;
-
-       sound_device->dev.platform_data = machine_data;
-
+       /* Associate the card data with the sound device */
+       platform_set_drvdata(sound_device, &machine_data->card);
 
-       /* Set the platform device and ASoC device to point to each other */
-       platform_set_drvdata(sound_device, &machine_data->sound_devdata);
-
-       machine_data->sound_devdata.dev = &sound_device->dev;
-
-
-       /* Tell ASoC to probe us.  This will call mpc8610_hpcd_machine.probe(),
-          if it exists. */
+       /* Register with ASoC */
        ret = platform_device_add(sound_device);
-
        if (ret) {
-               dev_err(&ofdev->dev, "platform device add failed\n");
+               dev_err(&pdev->dev, "platform device add failed\n");
                goto error;
        }
 
-       dev_set_drvdata(&ofdev->dev, sound_device);
+       of_node_put(codec_np);
 
        return 0;
 
 error:
        of_node_put(codec_np);
-       of_node_put(guts_np);
-       of_node_put(dma_np);
-       of_node_put(dma_channel_np);
 
        if (sound_device)
                platform_device_unregister(sound_device);
 
-       if (machine_data->dai.cpu_dai)
-               fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
-
-       if (ssi_info.ssi)
-               iounmap(ssi_info.ssi);
-
-       if (ssi_info.irq)
-               irq_dispose_mapping(ssi_info.irq);
-
-       if (dma_info.dma_channel[0])
-               iounmap(dma_info.dma_channel[0]);
-
-       if (dma_info.dma_channel[1])
-               iounmap(dma_info.dma_channel[1]);
-
-       if (dma_info.dma_irq[0])
-               irq_dispose_mapping(dma_info.dma_irq[0]);
-
-       if (dma_info.dma_irq[1])
-               irq_dispose_mapping(dma_info.dma_irq[1]);
-
-       if (machine_data->guts)
-               iounmap(machine_data->guts);
-
        kfree(machine_data);
 
        return ret;
 }
 
 /**
- * mpc8610_hpcd_remove: remove the OF device
+ * mpc8610_hpcd_remove: remove the platform device
  *
- * This function is called when the OF device is removed.
+ * This function is called when the platform device is removed.
  */
-static int mpc8610_hpcd_remove(struct platform_device *ofdev)
+static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
 {
-       struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev);
+       struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
        struct mpc8610_hpcd_data *machine_data =
-               sound_device->dev.platform_data;
+               container_of(card, struct mpc8610_hpcd_data, card);
 
        platform_device_unregister(sound_device);
 
-       if (machine_data->dai.cpu_dai)
-               fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
-
-       if (machine_data->ssi)
-               iounmap(machine_data->ssi);
-
-       if (machine_data->dma[0])
-               iounmap(machine_data->dma[0]);
-
-       if (machine_data->dma[1])
-               iounmap(machine_data->dma[1]);
-
-       if (machine_data->dma_irq[0])
-               irq_dispose_mapping(machine_data->dma_irq[0]);
-
-       if (machine_data->dma_irq[1])
-               irq_dispose_mapping(machine_data->dma_irq[1]);
-
-       if (machine_data->guts)
-               iounmap(machine_data->guts);
-
        kfree(machine_data);
        sound_device->dev.platform_data = NULL;
 
-       dev_set_drvdata(&ofdev->dev, NULL);
+       dev_set_drvdata(&pdev->dev, NULL);
 
        return 0;
 }
 
-static struct of_device_id mpc8610_hpcd_match[] = {
-       {
-               .compatible = "fsl,mpc8610-ssi",
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match);
-
-static struct of_platform_driver mpc8610_hpcd_of_driver = {
+static struct platform_driver mpc8610_hpcd_driver = {
+       .probe = mpc8610_hpcd_probe,
+       .remove = __devexit_p(mpc8610_hpcd_remove),
        .driver = {
-               .name = "mpc8610_hpcd",
+               /* The name must match the 'model' property in the device tree,
+                * in lowercase letters.
+                */
+               .name = "snd-soc-mpc8610hpcd",
                .owner = THIS_MODULE,
-               .of_match_table = mpc8610_hpcd_match,
        },
-       .probe          = mpc8610_hpcd_probe,
-       .remove         = mpc8610_hpcd_remove,
 };
 
 /**
- * mpc8610_hpcd_init: fabric driver initialization.
+ * mpc8610_hpcd_init: machine driver initialization.
  *
  * This function is called when this module is loaded.
  */
 static int __init mpc8610_hpcd_init(void)
 {
-       int ret;
-
-       printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n");
+       struct device_node *guts_np;
+       struct resource res;
 
-       ret = of_register_platform_driver(&mpc8610_hpcd_of_driver);
+       pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n");
 
-       if (ret)
-               printk(KERN_ERR
-                       "mpc8610-hpcd: failed to register platform driver\n");
+       /* Get the physical address of the global utilities registers */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
+       if (of_address_to_resource(guts_np, 0, &res)) {
+               pr_err("mpc8610-hpcd: missing/invalid global utilities node\n");
+               return -EINVAL;
+       }
+       guts_phys = res.start;
 
-       return ret;
+       return platform_driver_register(&mpc8610_hpcd_driver);
 }
 
 /**
- * mpc8610_hpcd_exit: fabric driver exit
+ * mpc8610_hpcd_exit: machine driver exit
  *
  * This function is called when this driver is unloaded.
  */
 static void __exit mpc8610_hpcd_exit(void)
 {
-       of_unregister_platform_driver(&mpc8610_hpcd_of_driver);
+       platform_driver_unregister(&mpc8610_hpcd_driver);
 }
 
 module_init(mpc8610_hpcd_init);
 module_exit(mpc8610_hpcd_exit);
 
 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
-MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver");
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
new file mode 100644 (file)
index 0000000..63b9eaa
--- /dev/null
@@ -0,0 +1,591 @@
+/**
+ * Freescale P1022DS ALSA SoC Machine driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <asm/fsl_guts.h>
+
+#include "fsl_dma.h"
+#include "fsl_ssi.h"
+
+/* P1022-specific PMUXCR and DMUXCR bit definitions */
+
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK       0x0001c000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI  0x00010000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI                0x00018000
+
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK      0x00000c00
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI       0x00000000
+
+#define CCSR_GUTS_DMUXCR_PAD   1       /* DMA controller/channel set to pad */
+#define CCSR_GUTS_DMUXCR_SSI   2       /* DMA controller/channel set to SSI */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
+ */
+static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts,
+       unsigned int co, unsigned int ch, unsigned int device)
+{
+       unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+       clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
+}
+
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+#define DAI_NAME_SIZE  32
+
+/**
+ * machine_data: machine-specific ASoC device data
+ *
+ * This structure contains data for a single sound platform device on an
+ * P1022 DS.  Some of the data is taken from the device tree.
+ */
+struct machine_data {
+       struct snd_soc_dai_link dai[2];
+       struct snd_soc_card card;
+       unsigned int dai_format;
+       unsigned int codec_clk_direction;
+       unsigned int cpu_clk_direction;
+       unsigned int clk_frequency;
+       unsigned int ssi_id;            /* 0 = SSI1, 1 = SSI2, etc */
+       unsigned int dma_id[2];         /* 0 = DMA1, 1 = DMA2, etc */
+       unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+       char codec_name[DAI_NAME_SIZE];
+       char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
+};
+
+/**
+ * p1022_ds_machine_probe: initialize the board
+ *
+ * This function is used to initialize the board-specific hardware.
+ *
+ * Here we program the DMACR and PMUXCR registers.
+ */
+static int p1022_ds_machine_probe(struct platform_device *sound_device)
+{
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts_85xx __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Enable SSI Tx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
+                       CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
+
+       /* Enable SSI Rx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
+                       CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
+
+       /* Enable DMA Channel for SSI */
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_ds_startup: program the board with various hardware parameters
+ *
+ * This function takes board-specific information, like clock frequencies
+ * and serial data formats, and passes that information to the codec and
+ * transport drivers.
+ */
+static int p1022_ds_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct machine_data *mdata =
+               container_of(rtd->card, struct machine_data, card);
+       struct device *dev = rtd->card->dev;
+       int ret = 0;
+
+       /* Tell the codec driver what the serial protocol is. */
+       ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec driver audio format\n");
+               return ret;
+       }
+
+       /*
+        * Tell the codec driver what the MCLK frequency is, and whether it's
+        * a slave or master.
+        */
+       ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, mdata->clk_frequency,
+                                    mdata->codec_clk_direction);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec driver clock params\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * p1022_ds_machine_remove: Remove the sound device
+ *
+ * This function is called to remove the sound device for one SSI.  We
+ * de-program the DMACR and PMUXCR register.
+ */
+static int p1022_ds_machine_remove(struct platform_device *sound_device)
+{
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts_85xx __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Restore the signal routing */
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_ds_ops: ASoC machine driver operations
+ */
+static struct snd_soc_ops p1022_ds_ops = {
+       .startup = p1022_ds_startup,
+};
+
+/**
+ * get_node_by_phandle_name - get a node by its phandle name
+ *
+ * This function takes a node, the name of a property in that node, and a
+ * compatible string.  Assuming the property is a phandle to another node,
+ * it returns that node, (optionally) if that node is compatible.
+ *
+ * If the property is not a phandle, or the node it points to is not compatible
+ * with the specific string, then NULL is returned.
+ */
+static struct device_node *get_node_by_phandle_name(struct device_node *np,
+       const char *name, const char *compatible)
+{
+       np = of_parse_phandle(np, name, 0);
+       if (!np)
+               return NULL;
+
+       if (!of_device_is_compatible(np, compatible)) {
+               of_node_put(np);
+               return NULL;
+       }
+
+       return np;
+}
+
+/**
+ * get_parent_cell_index -- return the cell-index of the parent of a node
+ *
+ * Return the value of the cell-index property of the parent of the given
+ * node.  This is used for DMA channel nodes that need to know the DMA ID
+ * of the controller they are on.
+ */
+static int get_parent_cell_index(struct device_node *np)
+{
+       struct device_node *parent = of_get_parent(np);
+       const u32 *iprop;
+       int ret = -1;
+
+       if (!parent)
+               return -1;
+
+       iprop = of_get_property(parent, "cell-index", NULL);
+       if (iprop)
+               ret = *iprop;
+
+       of_node_put(parent);
+
+       return ret;
+}
+
+/**
+ * codec_node_dev_name - determine the dev_name for a codec node
+ *
+ * This function determines the dev_name for an I2C node.  This is the name
+ * that would be returned by dev_name() if this device_node were part of a
+ * 'struct device'  It's ugly and hackish, but it works.
+ *
+ * The dev_name for such devices include the bus number and I2C address. For
+ * example, "cs4270-codec.0-004f".
+ */
+static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
+{
+       const u32 *iprop;
+       int bus, addr;
+       char temp[DAI_NAME_SIZE];
+
+       of_modalias_node(np, temp, DAI_NAME_SIZE);
+
+       iprop = of_get_property(np, "reg", NULL);
+       if (!iprop)
+               return -EINVAL;
+
+       addr = *iprop;
+
+       bus = get_parent_cell_index(np);
+       if (bus < 0)
+               return bus;
+
+       snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+
+       return 0;
+}
+
+static int get_dma_channel(struct device_node *ssi_np,
+                          const char *compatible,
+                          struct snd_soc_dai_link *dai,
+                          unsigned int *dma_channel_id,
+                          unsigned int *dma_id)
+{
+       struct resource res;
+       struct device_node *dma_channel_np;
+       const u32 *iprop;
+       int ret;
+
+       dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+                                                 "fsl,ssi-dma-channel");
+       if (!dma_channel_np)
+               return -EINVAL;
+
+       /* Determine the dev_name for the device_node.  This code mimics the
+        * behavior of of_device_make_bus_id(). We need this because ASoC uses
+        * the dev_name() of the device to match the platform (DMA) device with
+        * the CPU (SSI) device.  It's all ugly and hackish, but it works (for
+        * now).
+        *
+        * dai->platform name should already point to an allocated buffer.
+        */
+       ret = of_address_to_resource(dma_channel_np, 0, &res);
+       if (ret)
+               return ret;
+       snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
+                (unsigned long long) res.start, dma_channel_np->name);
+
+       iprop = of_get_property(dma_channel_np, "cell-index", NULL);
+       if (!iprop) {
+               of_node_put(dma_channel_np);
+               return -EINVAL;
+       }
+
+       *dma_channel_id = *iprop;
+       *dma_id = get_parent_cell_index(dma_channel_np);
+       of_node_put(dma_channel_np);
+
+       return 0;
+}
+
+/**
+ * p1022_ds_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections.  Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int p1022_ds_probe(struct platform_device *pdev)
+{
+       struct device *dev = pdev->dev.parent;
+       /* ssi_pdev is the platform device for the SSI node that probed us */
+       struct platform_device *ssi_pdev =
+               container_of(dev, struct platform_device, dev);
+       struct device_node *np = ssi_pdev->dev.of_node;
+       struct device_node *codec_np = NULL;
+       struct platform_device *sound_device = NULL;
+       struct machine_data *mdata;
+       int ret = -ENODEV;
+       const char *sprop;
+       const u32 *iprop;
+
+       /* Find the codec node for this SSI. */
+       codec_np = of_parse_phandle(np, "codec-handle", 0);
+       if (!codec_np) {
+               dev_err(dev, "could not find codec node\n");
+               return -EINVAL;
+       }
+
+       mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
+       if (!mdata) {
+               ret = -ENOMEM;
+               goto error_put;
+       }
+
+       mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+       mdata->dai[0].ops = &p1022_ds_ops;
+
+       /* Determine the codec name, it will be used as the codec DAI name */
+       ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE);
+       if (ret) {
+               dev_err(&pdev->dev, "invalid codec node %s\n",
+                       codec_np->full_name);
+               ret = -EINVAL;
+               goto error;
+       }
+       mdata->dai[0].codec_name = mdata->codec_name;
+
+       /* We register two DAIs per SSI, one for playback and the other for
+        * capture.  We support codecs that have separate DAIs for both playback
+        * and capture.
+        */
+       memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
+
+       /* The DAI names from the codec (snd_soc_dai_driver.name) */
+       mdata->dai[0].codec_dai_name = "wm8776-hifi-playback";
+       mdata->dai[1].codec_dai_name = "wm8776-hifi-capture";
+
+       /* Get the device ID */
+       iprop = of_get_property(np, "cell-index", NULL);
+       if (!iprop) {
+               dev_err(&pdev->dev, "cell-index property not found\n");
+               ret = -EINVAL;
+               goto error;
+       }
+       mdata->ssi_id = *iprop;
+
+       /* Get the serial format and clock direction. */
+       sprop = of_get_property(np, "fsl,mode", NULL);
+       if (!sprop) {
+               dev_err(&pdev->dev, "fsl,mode property not found\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (strcasecmp(sprop, "i2s-slave") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_I2S;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+
+               /* In i2s-slave mode, the codec has its own clock source, so we
+                * need to get the frequency from the device tree and pass it to
+                * the codec driver.
+                */
+               iprop = of_get_property(codec_np, "clock-frequency", NULL);
+               if (!iprop || !*iprop) {
+                       dev_err(&pdev->dev, "codec bus-frequency "
+                               "property is missing or invalid\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
+               mdata->clk_frequency = *iprop;
+       } else if (strcasecmp(sprop, "i2s-master") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_I2S;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "lj-slave") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "lj-master") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "rj-slave") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "rj-master") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else if (strcasecmp(sprop, "ac97-slave") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_AC97;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+       } else if (strcasecmp(sprop, "ac97-master") == 0) {
+               mdata->dai_format = SND_SOC_DAIFMT_AC97;
+               mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
+               mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
+       } else {
+               dev_err(&pdev->dev,
+                       "unrecognized fsl,mode property '%s'\n", sprop);
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (!mdata->clk_frequency) {
+               dev_err(&pdev->dev, "unknown clock frequency\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* Find the playback DMA channel to use. */
+       mdata->dai[0].platform_name = mdata->platform_name[0];
+       ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+                             &mdata->dma_channel_id[0],
+                             &mdata->dma_id[0]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
+               goto error;
+       }
+
+       /* Find the capture DMA channel to use. */
+       mdata->dai[1].platform_name = mdata->platform_name[1];
+       ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+                             &mdata->dma_channel_id[1],
+                             &mdata->dma_id[1]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
+               goto error;
+       }
+
+       /* Initialize our DAI data structure.  */
+       mdata->dai[0].stream_name = "playback";
+       mdata->dai[1].stream_name = "capture";
+       mdata->dai[0].name = mdata->dai[0].stream_name;
+       mdata->dai[1].name = mdata->dai[1].stream_name;
+
+       mdata->card.probe = p1022_ds_machine_probe;
+       mdata->card.remove = p1022_ds_machine_remove;
+       mdata->card.name = pdev->name; /* The platform driver name */
+       mdata->card.num_links = 2;
+       mdata->card.dai_link = mdata->dai;
+
+       /* Allocate a new audio platform device structure */
+       sound_device = platform_device_alloc("soc-audio", -1);
+       if (!sound_device) {
+               dev_err(&pdev->dev, "platform device alloc failed\n");
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       /* Associate the card data with the sound device */
+       platform_set_drvdata(sound_device, &mdata->card);
+
+       /* Register with ASoC */
+       ret = platform_device_add(sound_device);
+       if (ret) {
+               dev_err(&pdev->dev, "platform device add failed\n");
+               goto error;
+       }
+
+       of_node_put(codec_np);
+
+       return 0;
+
+error:
+       if (sound_device)
+               platform_device_unregister(sound_device);
+
+       kfree(mdata);
+error_put:
+       of_node_put(codec_np);
+       return ret;
+}
+
+/**
+ * p1022_ds_remove: remove the platform device
+ *
+ * This function is called when the platform device is removed.
+ */
+static int __devexit p1022_ds_remove(struct platform_device *pdev)
+{
+       struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
+       struct snd_soc_card *card = platform_get_drvdata(sound_device);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+
+       platform_device_unregister(sound_device);
+
+       kfree(mdata);
+       sound_device->dev.platform_data = NULL;
+
+       dev_set_drvdata(&pdev->dev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver p1022_ds_driver = {
+       .probe = p1022_ds_probe,
+       .remove = __devexit_p(p1022_ds_remove),
+       .driver = {
+               /* The name must match the 'model' property in the device tree,
+                * in lowercase letters, but only the part after that last
+                * comma.  This is because some model properties have a "fsl,"
+                * prefix.
+                */
+               .name = "snd-soc-p1022",
+               .owner = THIS_MODULE,
+       },
+};
+
+/**
+ * p1022_ds_init: machine driver initialization.
+ *
+ * This function is called when this module is loaded.
+ */
+static int __init p1022_ds_init(void)
+{
+       struct device_node *guts_np;
+       struct resource res;
+
+       pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
+
+       /* Get the physical address of the global utilities registers */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (of_address_to_resource(guts_np, 0, &res)) {
+               pr_err("p1022-ds: missing/invalid global utilities node\n");
+               return -EINVAL;
+       }
+       guts_phys = res.start;
+       of_node_put(guts_np);
+
+       return platform_driver_register(&p1022_ds_driver);
+}
+
+/**
+ * p1022_ds_exit: machine driver exit
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit p1022_ds_exit(void)
+{
+       platform_driver_unregister(&p1022_ds_driver);
+}
+
+module_init(p1022_ds_init);
+module_exit(p1022_ds_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale P1022 DS ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
index 6644cba..fe15bb2 100644 (file)
 
 #define DRV_NAME "pcm030-audio-fabric"
 
-static struct snd_soc_device device;
 static struct snd_soc_card card;
 
 static struct snd_soc_dai_link pcm030_fabric_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 Analog",
-       .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
-       .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL],
+       .codec_dai_name = "wm9712-hifi",
+       .cpu_dai_name = "mpc5200-psc-ac97.0",
+       .platform_name = "mpc5200-pcm-audio",
+       .codec_name = "wm9712-codec",
 },
 {
        .name = "AC97",
        .stream_name = "AC97 IEC958",
-       .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
-       .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF],
+       .codec_dai_name = "wm9712-aux",
+       .cpu_dai_name = "mpc5200-psc-ac97.1",
+       .platform_name = "mpc5200-pcm-audio",
+       ..codec_name = "wm9712-codec",
 },
 };
 
@@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void)
        if (!of_machine_is_compatible("phytec,pcm030"))
                return -ENODEV;
 
-       card.platform = &mpc5200_audio_dma_platform;
+
        card.name = "pcm030";
        card.dai_link = pcm030_fabric_dai;
        card.num_links = ARRAY_SIZE(pcm030_fabric_dai);
 
-       device.card = &card;
-       device.codec_dev = &soc_codec_dev_wm9712;
-
        pdev = platform_device_alloc("soc-audio", 1);
        if (!pdev) {
                pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");
                return -ENODEV;
        }
 
-       platform_set_drvdata(pdev, &device);
-       device.dev = &pdev->dev;
+       platform_set_drvdata(pdev, &card);
 
        rc = platform_device_add(pdev);
        if (rc) {
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
deleted file mode 100644 (file)
index 3bc13fd..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * OF helpers for ALSA SoC Layer
- *
- * Copyright (C) 2008, Secret Lab Technologies Ltd.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-of-simple.h>
-#include <sound/initval.h>
-
-MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
-
-static DEFINE_MUTEX(of_snd_soc_mutex);
-static LIST_HEAD(of_snd_soc_device_list);
-static int of_snd_soc_next_index;
-
-struct of_snd_soc_device {
-       int id;
-       struct list_head list;
-       struct snd_soc_device device;
-       struct snd_soc_card card;
-       struct snd_soc_dai_link dai_link;
-       struct platform_device *pdev;
-       struct device_node *platform_node;
-       struct device_node *codec_node;
-};
-
-static struct snd_soc_ops of_snd_soc_ops = {
-};
-
-static struct of_snd_soc_device *
-of_snd_soc_get_device(struct device_node *codec_node)
-{
-       struct of_snd_soc_device *of_soc;
-
-       list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
-               if (of_soc->codec_node == codec_node)
-                       return of_soc;
-       }
-
-       of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL);
-       if (!of_soc)
-               return NULL;
-
-       /* Initialize the structure and add it to the global list */
-       of_soc->codec_node = codec_node;
-       of_soc->id = of_snd_soc_next_index++;
-       of_soc->card.dai_link = &of_soc->dai_link;
-       of_soc->card.num_links = 1;
-       of_soc->device.card = &of_soc->card;
-       of_soc->dai_link.ops = &of_snd_soc_ops;
-       list_add(&of_soc->list, &of_snd_soc_device_list);
-
-       return of_soc;
-}
-
-static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
-{
-       struct platform_device *pdev;
-       int rc;
-
-       /* Only register the device if both the codec and platform have
-        * been registered */
-       if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
-               return;
-
-       pr_info("platform<-->codec match achieved; registering machine\n");
-
-       pdev = platform_device_alloc("soc-audio", of_soc->id);
-       if (!pdev) {
-               pr_err("of_soc: platform_device_alloc() failed\n");
-               return;
-       }
-
-       pdev->dev.platform_data = of_soc;
-       platform_set_drvdata(pdev, &of_soc->device);
-       of_soc->device.dev = &pdev->dev;
-
-       /* The ASoC device is complete; register it */
-       rc = platform_device_add(pdev);
-       if (rc) {
-               pr_err("of_soc: platform_device_add() failed\n");
-               return;
-       }
-
-}
-
-int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
-                             void *codec_data, struct snd_soc_dai *dai,
-                             struct device_node *node)
-{
-       struct of_snd_soc_device *of_soc;
-       int rc = 0;
-
-       pr_info("registering ASoC codec driver: %s\n", node->full_name);
-
-       mutex_lock(&of_snd_soc_mutex);
-       of_soc = of_snd_soc_get_device(node);
-       if (!of_soc) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       /* Store the codec data */
-       of_soc->device.codec_data = codec_data;
-       of_soc->device.codec_dev = codec_dev;
-       of_soc->dai_link.name = (char *)node->name;
-       of_soc->dai_link.stream_name = (char *)node->name;
-       of_soc->dai_link.codec_dai = dai;
-
-       /* Now try to register the SoC device */
-       of_snd_soc_register_device(of_soc);
-
- out:
-       mutex_unlock(&of_snd_soc_mutex);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
-
-int of_snd_soc_register_platform(struct snd_soc_platform *platform,
-                                struct device_node *node,
-                                struct snd_soc_dai *cpu_dai)
-{
-       struct of_snd_soc_device *of_soc;
-       struct device_node *codec_node;
-       const phandle *handle;
-       int len, rc = 0;
-
-       pr_info("registering ASoC platform driver: %s\n", node->full_name);
-
-       handle = of_get_property(node, "codec-handle", &len);
-       if (!handle || len < sizeof(handle))
-               return -ENODEV;
-       codec_node = of_find_node_by_phandle(*handle);
-       if (!codec_node)
-               return -ENODEV;
-       pr_info("looking for codec: %s\n", codec_node->full_name);
-
-       mutex_lock(&of_snd_soc_mutex);
-       of_soc = of_snd_soc_get_device(codec_node);
-       if (!of_soc) {
-               rc = -ENOMEM;
-               goto out;
-       }
-
-       of_soc->platform_node = node;
-       of_soc->dai_link.cpu_dai = cpu_dai;
-       of_soc->card.platform = platform;
-       of_soc->card.name = of_soc->dai_link.cpu_dai->name;
-
-       /* Now try to register the SoC device */
-       of_snd_soc_register_device(of_soc);
-
- out:
-       mutex_unlock(&of_snd_soc_mutex);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);
index 687c76f..642270a 100644 (file)
@@ -8,12 +8,24 @@ menuconfig SND_IMX_SOC
          Say Y or M if you want to add support for codecs attached to
          the i.MX SSI interface.
 
+
 if SND_IMX_SOC
 
+config SND_MXC_SOC_SSI
+       tristate
+
+config SND_MXC_SOC_FIQ
+       tristate
+
+config SND_MXC_SOC_MX2
+       tristate
+
 config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
        depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
        select SND_SOC_WM8350
+       select SND_MXC_SOC_SSI
+       select SND_MXC_SOC_FIQ
        help
          Enable support for audio on the i.MX31ADS with the WM1133-EV1
          PMIC board with WM8835x fitted.
@@ -22,6 +34,8 @@ config SND_SOC_PHYCORE_AC97
        tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
        depends on MACH_PCM043 || MACH_PCA100
        select SND_SOC_WM9712
+       select SND_MXC_SOC_SSI
+       select SND_MXC_SOC_FIQ
        help
          Say Y if you want to add support for SoC audio on Phytec phyCORE
          and phyCARD boards in AC97 mode
@@ -32,6 +46,8 @@ config SND_SOC_EUKREA_TLV320
                || MACH_EUKREA_MBIMXSD25_BASEBOARD \
                || MACH_EUKREA_MBIMXSD35_BASEBOARD
        select SND_SOC_TLV320AIC23
+       select SND_MXC_SOC_SSI
+       select SND_MXC_SOC_FIQ
        help
          Enable I2S based access to the TLV320AIC23B codec attached
          to the SSI interface
index 7bc57ba..b67fc02 100644 (file)
@@ -1,11 +1,11 @@
 # i.MX Platform Support
-snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o
-
-ifdef CONFIG_MACH_MX27
-snd-soc-imx-objs += imx-pcm-dma-mx2.o
-endif
+snd-soc-imx-objs := imx-ssi.o
+snd-soc-imx-fiq-objs := imx-pcm-fiq.o
+snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o
 
 obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
+obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o
+obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
index f15dfbd..b596752 100644 (file)
@@ -79,22 +79,19 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = {
 static struct snd_soc_dai_link eukrea_tlv320_dai = {
        .name           = "tlv320aic23",
        .stream_name    = "TLV320AIC23",
-       .codec_dai      = &tlv320aic23_dai,
+       .codec_dai      = "tlv320aic23-hifi",
+       .platform_name  = "imx-pcm-audio.0",
+       .codec_name     = "tlv320aic23-codec.0-001a",
+       .cpu_dai = "imx-ssi.0",
        .ops            = &eukrea_tlv320_snd_ops,
 };
 
 static struct snd_soc_card eukrea_tlv320 = {
        .name           = "cpuimx-audio",
-       .platform       = &imx_soc_platform,
        .dai_link       = &eukrea_tlv320_dai,
        .num_links      = 1,
 };
 
-static struct snd_soc_device eukrea_tlv320_snd_devdata = {
-       .card           = &eukrea_tlv320,
-       .codec_dev      = &soc_codec_dev_tlv320aic23,
-};
-
 static struct platform_device *eukrea_tlv320_snd_device;
 
 static int __init eukrea_tlv320_init(void)
@@ -110,10 +107,7 @@ static int __init eukrea_tlv320_init(void)
        if (!eukrea_tlv320_snd_device)
                return -ENOMEM;
 
-       eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0];
-
-       platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata);
-       eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev;
+       platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320);
        ret = platform_device_add(eukrea_tlv320_snd_device);
 
        if (ret) {
index 0a595da..fd493ee 100644 (file)
@@ -103,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
        int ret;
 
-       dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
        if (iprtd->dma < 0) {
@@ -213,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
        struct imx_pcm_runtime_data *iprtd = runtime->private_data;
        int err;
 
-       dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        iprtd->substream = substream;
        iprtd->buf = (unsigned int *)substream->dma_buffer.area;
@@ -318,19 +318,42 @@ static struct snd_pcm_ops imx_pcm_ops = {
        .mmap           = snd_imx_pcm_mmap,
 };
 
-static struct snd_soc_platform imx_soc_platform_dma = {
-       .name           = "imx-audio",
-       .pcm_ops        = &imx_pcm_ops,
+static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
+       .ops            = &imx_pcm_ops,
        .pcm_new        = imx_pcm_new,
        .pcm_free       = imx_pcm_free,
 };
 
-struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
-               struct imx_ssi *ssi)
+static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
 {
-       ssi->dma_params_tx.burstsize = DMA_TXFIFO_BURST;
-       ssi->dma_params_rx.burstsize = DMA_RXFIFO_BURST;
+       return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
+}
+
+static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver imx_pcm_driver = {
+       .driver = {
+                       .name = "imx-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
 
-       return &imx_soc_platform_dma;
+       .probe = imx_soc_platform_probe,
+       .remove = __devexit_p(imx_soc_platform_remove),
+};
+
+static int __init snd_imx_pcm_init(void)
+{
+       return platform_driver_register(&imx_pcm_driver);
+}
+module_init(snd_imx_pcm_init);
+
+static void __exit snd_imx_pcm_exit(void)
+{
+       platform_driver_unregister(&imx_pcm_driver);
 }
+module_exit(snd_imx_pcm_exit);
 
index b2bf272..413b78d 100644 (file)
@@ -236,6 +236,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
        .mmap           = snd_imx_pcm_mmap,
 };
 
+static int ssi_irq = 0;
+
 static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
        struct snd_pcm *pcm)
 {
@@ -245,7 +247,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (ret)
                return ret;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                struct snd_pcm_substream *substream =
                        pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
                struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -253,7 +255,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
                imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                struct snd_pcm_substream *substream =
                        pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
                struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -267,24 +269,32 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
        return 0;
 }
 
-static struct snd_soc_platform imx_soc_platform_fiq = {
-       .pcm_ops        = &imx_pcm_ops,
+static void imx_pcm_fiq_free(struct snd_pcm *pcm)
+{
+       mxc_set_irq_fiq(ssi_irq, 0);
+       release_fiq(&fh);
+       imx_pcm_free(pcm);
+}
+
+static struct snd_soc_platform_driver imx_soc_platform_fiq = {
+       .ops            = &imx_pcm_ops,
        .pcm_new        = imx_pcm_fiq_new,
-       .pcm_free       = imx_pcm_free,
+       .pcm_free       = imx_pcm_fiq_free,
 };
 
-struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
-               struct imx_ssi *ssi)
+static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
 {
-       int ret = 0;
+       struct imx_ssi *ssi = platform_get_drvdata(pdev);
+       int ret;
 
        ret = claim_fiq(&fh);
        if (ret) {
                dev_err(&pdev->dev, "failed to claim fiq: %d", ret);
-               return ERR_PTR(ret);
+               return ret;
        }
 
        mxc_set_irq_fiq(ssi->irq, 1);
+       ssi_irq = ssi->irq;
 
        imx_pcm_fiq = ssi->irq;
 
@@ -293,13 +303,43 @@ struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
        ssi->dma_params_tx.burstsize = 4;
        ssi->dma_params_rx.burstsize = 6;
 
-       return &imx_soc_platform_fiq;
+       ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
+       if (ret)
+               goto failed_register;
+
+       return 0;
+
+failed_register:
+       mxc_set_irq_fiq(ssi_irq, 0);
+       release_fiq(&fh);
+
+       return ret;
 }
 
-void imx_ssi_fiq_exit(struct platform_device *pdev,
-               struct imx_ssi *ssi)
+static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
 {
-       mxc_set_irq_fiq(ssi->irq, 0);
-       release_fiq(&fh);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
 }
 
+static struct platform_driver imx_pcm_driver = {
+       .driver = {
+                       .name = "imx-fiq-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = imx_soc_platform_probe,
+       .remove = __devexit_p(imx_soc_platform_remove),
+};
+
+static int __init snd_imx_pcm_init(void)
+{
+       return platform_driver_register(&imx_pcm_driver);
+}
+module_init(snd_imx_pcm_init);
+
+static void __exit snd_imx_pcm_exit(void)
+{
+       platform_driver_unregister(&imx_pcm_driver);
+}
+module_exit(snd_imx_pcm_exit);
index c81da05..d4bd345 100644 (file)
@@ -61,7 +61,7 @@
 static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
        unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
        u32 sccr;
 
        sccr = readl(ssi->base + SSI_STCCR);
@@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
  */
 static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 {
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
        u32 strcr = 0, scr;
 
        scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET);
@@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                                  int clk_id, unsigned int freq, int dir)
 {
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
        u32 scr;
 
        scr = readl(ssi->base + SSI_SCR);
@@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
                                  int div_id, int div)
 {
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
        u32 stccr, srccr;
 
        stccr = readl(ssi->base + SSI_STCCR);
@@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params,
                             struct snd_soc_dai *cpu_dai)
 {
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
        struct imx_pcm_dma_params *dma_data;
        u32 reg, sccr;
 
@@ -282,9 +282,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
 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;
-       struct imx_ssi *ssi = cpu_dai->private_data;
+       struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);
        unsigned int sier_bits, sier;
        unsigned int scr;
 
@@ -353,22 +351,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
        .trigger        = imx_ssi_trigger,
 };
 
-static struct snd_soc_dai imx_ssi_dai = {
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_96000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = SNDRV_PCM_RATE_8000_96000,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       },
-       .ops = &imx_ssi_pcm_dai_ops,
-};
-
 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
                struct vm_area_struct *vma)
 {
@@ -384,6 +366,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
                        runtime->dma_bytes);
        return ret;
 }
+EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
 
 static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
@@ -415,14 +398,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
                card->dev->dma_mask = &imx_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = imx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = imx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -432,6 +415,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(imx_pcm_new);
 
 void imx_pcm_free(struct snd_pcm *pcm)
 {
@@ -453,14 +437,40 @@ void imx_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(imx_pcm_free);
 
-struct snd_soc_platform imx_soc_platform = {
-       .name           = "imx-audio",
+static struct snd_soc_dai_driver imx_ssi_dai = {
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_96000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = &imx_ssi_pcm_dai_ops,
 };
-EXPORT_SYMBOL_GPL(imx_soc_platform);
 
-static struct snd_soc_dai imx_ac97_dai = {
-       .name = "AC97",
+static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
+{
+       struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
+       uint32_t val;
+
+       snd_soc_dai_set_drvdata(dai, ssi);
+
+       val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
+               SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
+       writel(val, ssi->base + SSI_SFCSR);
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver imx_ac97_dai = {
+       .probe = imx_ssi_dai_probe,
        .ac97_control = 1,
        .playback = {
                .stream_name = "AC97 Playback",
@@ -580,25 +590,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
 };
 EXPORT_SYMBOL_GPL(soc_ac97_ops);
 
-struct snd_soc_dai imx_ssi_pcm_dai[2];
-EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
-
 static int imx_ssi_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct imx_ssi *ssi;
        struct imx_ssi_platform_data *pdata = pdev->dev.platform_data;
-       struct snd_soc_platform *platform;
        int ret = 0;
-       unsigned int val;
-       struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
-
-       if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai))
-               return -EINVAL;
+       struct snd_soc_dai_driver *dai;
 
        ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
        if (!ssi)
                return -ENOMEM;
+       dev_set_drvdata(&pdev->dev, ssi);
 
        if (pdata) {
                ssi->ac97_reset = pdata->ac97_reset;
@@ -643,9 +646,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
                }
                ac97_ssi = ssi;
                setup_channel_to_ac97(ssi);
-               memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai));
+               dai = &imx_ac97_dai;
        } else
-               memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai));
+               dai = &imx_ssi_dai;
 
        writel(0x0, ssi->base + SSI_SIER);
 
@@ -660,37 +663,36 @@ static int imx_ssi_probe(struct platform_device *pdev)
        if (res)
                ssi->dma_params_rx.dma = res->start;
 
-       dai->id = pdev->id;
-       dai->dev = &pdev->dev;
-       dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id);
-       dai->private_data = ssi;
-
        if ((cpu_is_mx27() || cpu_is_mx21()) &&
                        !(ssi->flags & IMX_SSI_USE_AC97) &&
                        (ssi->flags & IMX_SSI_DMA)) {
                ssi->flags |= IMX_SSI_DMA;
-               platform = imx_ssi_dma_mx2_init(pdev, ssi);
-       } else
-               platform = imx_ssi_fiq_init(pdev, ssi);
-
-       imx_soc_platform.pcm_ops = platform->pcm_ops;
-       imx_soc_platform.pcm_new = platform->pcm_new;
-       imx_soc_platform.pcm_free = platform->pcm_free;
+       }
 
-       val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
-               SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
-       writel(val, ssi->base + SSI_SFCSR);
+       platform_set_drvdata(pdev, ssi);
 
-       ret = snd_soc_register_dai(dai);
+       ret = snd_soc_register_dai(&pdev->dev, dai);
        if (ret) {
                dev_err(&pdev->dev, "register DAI failed\n");
                goto failed_register;
        }
 
-       platform_set_drvdata(pdev, ssi);
+       ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
+       if (!ssi->soc_platform_pdev)
+               goto failed_pdev_alloc;
+       platform_set_drvdata(ssi->soc_platform_pdev, ssi);
+       ret = platform_device_add(ssi->soc_platform_pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add platform device\n");
+               goto failed_pdev_add;
+       }
 
        return 0;
 
+failed_pdev_add:
+       platform_device_put(ssi->soc_platform_pdev);
+failed_pdev_alloc:
+       snd_soc_unregister_dai(&pdev->dev);
 failed_register:
 failed_ac97:
        iounmap(ssi->base);
@@ -709,16 +711,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
 {
        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        struct imx_ssi *ssi = platform_get_drvdata(pdev);
-       struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
 
-       snd_soc_unregister_dai(dai);
+       platform_device_del(ssi->soc_platform_pdev);
+       platform_device_put(ssi->soc_platform_pdev);
+
+       snd_soc_unregister_dai(&pdev->dev);
 
        if (ssi->flags & IMX_SSI_USE_AC97)
                ac97_ssi = NULL;
 
-       if (!(ssi->flags & IMX_SSI_DMA))
-               imx_ssi_fiq_exit(pdev, ssi);
-
        iounmap(ssi->base);
        release_mem_region(res->start, resource_size(res));
        clk_disable(ssi->clk);
@@ -733,34 +734,19 @@ static struct platform_driver imx_ssi_driver = {
        .remove = __devexit_p(imx_ssi_remove),
 
        .driver = {
-               .name = DRV_NAME,
+               .name = "imx-ssi",
                .owner = THIS_MODULE,
        },
 };
 
 static int __init imx_ssi_init(void)
 {
-       int ret;
-
-       ret = snd_soc_register_platform(&imx_soc_platform);
-       if (ret) {
-               pr_err("failed to register soc platform: %d\n", ret);
-               return ret;
-       }
-
-       ret = platform_driver_register(&imx_ssi_driver);
-       if (ret) {
-               snd_soc_unregister_platform(&imx_soc_platform);
-               return ret;
-       }
-
-       return 0;
+       return platform_driver_register(&imx_ssi_driver);
 }
 
 static void __exit imx_ssi_exit(void)
 {
        platform_driver_unregister(&imx_ssi_driver);
-       snd_soc_unregister_platform(&imx_soc_platform);
 }
 
 module_init(imx_ssi_init);
index 55f26eb..53b780d 100644 (file)
 #define IMX_SSI_RX_DIV_PSR     4
 #define IMX_SSI_RX_DIV_PM      5
 
-extern struct snd_soc_dai imx_ssi_pcm_dai[2];
-extern struct snd_soc_platform imx_soc_platform;
-
 #define DRV_NAME "imx-ssi"
 
 struct imx_pcm_dma_params {
@@ -197,7 +194,7 @@ struct imx_pcm_dma_params {
 struct imx_ssi {
        struct platform_device *ac97_dev;
 
-       struct snd_soc_device imx_ac97;
+       struct snd_soc_dai *imx_ac97;
        struct clk *clk;
        void __iomem *base;
        int irq;
@@ -213,6 +210,8 @@ struct imx_ssi {
        struct imx_pcm_dma_params       dma_params_tx;
 
        int enabled;
+
+       struct platform_device *soc_platform_pdev;
 };
 
 struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
index a8307d5..6a65dd7 100644 (file)
@@ -32,23 +32,20 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
        {
                .name           = "HiFi",
                .stream_name    = "HiFi",
-               .codec_dai      = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+               .codec_dai_name         = "wm9712-hifi",
+               .codec_name     = "wm9712-codec",
+               .cpu_dai_name   = "imx-ssi.0",
+               .platform_name  = "imx-fiq-pcm-audio.0",
                .ops            = &imx_phycore_hifi_ops,
        },
 };
 
 static struct snd_soc_card imx_phycore = {
        .name           = "PhyCORE-audio",
-       .platform       = &imx_soc_platform,
        .dai_link       = imx_phycore_dai_ac97,
        .num_links      = ARRAY_SIZE(imx_phycore_dai_ac97),
 };
 
-static struct snd_soc_device imx_phycore_snd_devdata = {
-       .card           = &imx_phycore,
-       .codec_dev      = &soc_codec_dev_wm9712,
-};
-
 static struct platform_device *imx_phycore_snd_device;
 
 static int __init imx_phycore_init(void)
@@ -63,10 +60,12 @@ static int __init imx_phycore_init(void)
        if (!imx_phycore_snd_device)
                return -ENOMEM;
 
-       imx_phycore_dai_ac97[0].cpu_dai = &imx_ssi_pcm_dai[0];
+       platform_set_drvdata(imx_phycore_snd_device, &imx_phycore);
+       ret = platform_device_add(imx_phycore_snd_device);
 
-       platform_set_drvdata(imx_phycore_snd_device, &imx_phycore_snd_devdata);
-       imx_phycore_snd_devdata.dev = &imx_phycore_snd_device->dev;
+       imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1);
+       if (!imx_phycore_snd_device)
+               return -ENOMEM;
        ret = platform_device_add(imx_phycore_snd_device);
 
        if (ret) {
index a6e7d94..30fdb15 100644 (file)
@@ -82,8 +82,8 @@ static int wm1133_ev1_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int i, found = 0;
        snd_pcm_format_t format = params_format(params);
        unsigned int rate = params_rate(params);
@@ -210,9 +210,9 @@ static struct snd_soc_jack_pin mic_jack_pins[] = {
        { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE },
 };
 
-static int wm1133_ev1_init(struct snd_soc_codec *codec)
+static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_card *card = codec->socdev->card;
+       struct snd_soc_codec *codec = rtd->codec;
 
        snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets,
                                  ARRAY_SIZE(wm1133_ev1_widgets));
@@ -221,13 +221,13 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)
                                ARRAY_SIZE(wm1133_ev1_map));
 
        /* Headphone jack detection */
-       snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
+       snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
        snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
                              hp_jack_pins);
        wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
 
        /* Microphone jack detection */
-       snd_soc_jack_new(card, "Microphone",
+       snd_soc_jack_new(codec, "Microphone",
                         SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);
        snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
                              mic_jack_pins);
@@ -243,8 +243,10 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link wm1133_ev1_dai = {
        .name = "WM1133-EV1",
        .stream_name = "Audio",
-       .cpu_dai = &imx_ssi_pcm_dai[0],
-       .codec_dai = &wm8350_dai,
+       .cpu_dai_name = "imx-ssi.0",
+       .codec_dai_name = "wm8350-hifi",
+       .platform_name = "imx-fiq-pcm-audio.0",
+       .codec_name = "wm8350-codec.0-0x1a",
        .init = wm1133_ev1_init,
        .ops = &wm1133_ev1_ops,
        .symmetric_rates = 1,
@@ -252,16 +254,10 @@ static struct snd_soc_dai_link wm1133_ev1_dai = {
 
 static struct snd_soc_card wm1133_ev1 = {
        .name = "WM1133-EV1",
-       .platform = &imx_soc_platform,
        .dai_link = &wm1133_ev1_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device wm1133_ev1_snd_devdata = {
-       .card = &wm1133_ev1,
-       .codec_dev = &soc_codec_dev_wm8350,
-};
-
 static struct platform_device *wm1133_ev1_snd_device;
 
 static int __init wm1133_ev1_audio_init(void)
@@ -286,8 +282,7 @@ static int __init wm1133_ev1_audio_init(void)
        if (!wm1133_ev1_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata);
-       wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev;
+       platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1);
        ret = platform_device_add(wm1133_ev1_snd_device);
 
        if (ret)
index eb518f0..f3cffd1 100644 (file)
@@ -106,15 +106,10 @@ static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
        writel(value, i2s->base + reg);
 }
 
-static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
-{
-       return dai->private_data;
-}
-
 static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
        struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf, ctrl;
 
        if (dai->active)
@@ -136,7 +131,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
 static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
        struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf;
 
        if (!dai->active)
@@ -152,7 +147,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
 static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 
        uint32_t ctrl;
        uint32_t mask;
@@ -186,7 +181,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 
 static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 
        uint32_t format = 0;
        uint32_t conf;
@@ -238,7 +233,7 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        enum jz4740_dma_width dma_width;
        struct jz4740_pcm_config *pcm_config;
        unsigned int sample_size;
@@ -288,7 +283,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
 static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
        unsigned int freq, int dir)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        struct clk *parent;
        int ret = 0;
 
@@ -312,7 +307,7 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 
 static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf;
 
        if (dai->active) {
@@ -330,7 +325,7 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
 
 static int jz4740_i2s_resume(struct snd_soc_dai *dai)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf;
 
        clk_enable(i2s->clk_aic);
@@ -346,11 +341,38 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
        return 0;
 }
 
-static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
+static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
 {
-       struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai);
+       struct jz4740_dma_config *dma_config;
+
+       /* Playback */
+       dma_config = &i2s->pcm_config_playback.dma_config;
+       dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
+       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
+       dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
+       dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
+       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
+       i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+
+       /* Capture */
+       dma_config = &i2s->pcm_config_capture.dma_config;
+       dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
+       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
+       dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
+       dma_config->flags = JZ4740_DMA_DST_AUTOINC;
+       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
+       i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
+}
+
+static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
+{
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
        uint32_t conf;
 
+       clk_enable(i2s->clk_aic);
+
+       jz4740_i2c_init_pcm_config(i2s);
+
        conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
                (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
                JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
@@ -363,6 +385,14 @@ static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *da
        return 0;
 }
 
+static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai)
+{
+       struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+       clk_disable(i2s->clk_aic);
+       return 0;
+}
+
 static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
        .startup = jz4740_i2s_startup,
        .shutdown = jz4740_i2s_shutdown,
@@ -375,9 +405,9 @@ static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
 #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                SNDRV_PCM_FMTBIT_S16_LE)
 
-struct snd_soc_dai jz4740_i2s_dai = {
-       .name = "jz4740-i2s",
-       .probe = jz4740_i2s_probe,
+static struct snd_soc_dai_driver jz4740_i2s_dai = {
+       .probe = jz4740_i2s_dai_probe,
+       .remove = jz4740_i2s_dai_remove,
        .playback = {
                .channels_min = 1,
                .channels_max = 2,
@@ -395,30 +425,6 @@ struct snd_soc_dai jz4740_i2s_dai = {
        .suspend = jz4740_i2s_suspend,
        .resume = jz4740_i2s_resume,
 };
-EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
-
-static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
-{
-       struct jz4740_dma_config *dma_config;
-
-       /* Playback */
-       dma_config = &i2s->pcm_config_playback.dma_config;
-       dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
-       dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
-
-       /* Capture */
-       dma_config = &i2s->pcm_config_capture.dma_config;
-       dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
-       dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
-       dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
-       dma_config->flags = JZ4740_DMA_DST_AUTOINC;
-       dma_config->mode = JZ4740_DMA_MODE_SINGLE;
-       i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
-}
 
 static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
 {
@@ -463,24 +469,17 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
                goto err_clk_put_aic;
        }
 
-       clk_enable(i2s->clk_aic);
-
-       jz4740_i2c_init_pcm_config(i2s);
-
-       jz4740_i2s_dai.private_data = i2s;
-       ret = snd_soc_register_dai(&jz4740_i2s_dai);
+       platform_set_drvdata(pdev, i2s);
+       ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai);
 
        if (ret) {
                dev_err(&pdev->dev, "Failed to register DAI\n");
                goto err_clk_put_i2s;
        }
 
-       platform_set_drvdata(pdev, i2s);
-
        return 0;
 
 err_clk_put_i2s:
-       clk_disable(i2s->clk_aic);
        clk_put(i2s->clk_i2s);
 err_clk_put_aic:
        clk_put(i2s->clk_aic);
@@ -498,9 +497,8 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
 {
        struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
 
-       snd_soc_unregister_dai(&jz4740_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
-       clk_disable(i2s->clk_aic);
        clk_put(i2s->clk_i2s);
        clk_put(i2s->clk_aic);
 
index da22ed8..5e49339 100644 (file)
@@ -13,6 +13,4 @@
 
 #define JZ4740_I2S_BIT_CLK             0
 
-extern struct snd_soc_dai jz4740_i2s_dai;
-
 #endif
index ee68d85..fb1483f 100644 (file)
@@ -109,7 +109,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct jz4740_pcm_config *config;
 
-       config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        if (!config)
                return 0;
@@ -310,14 +310,14 @@ int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = jz4740_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto err;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = jz4740_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -328,22 +328,20 @@ err:
        return ret;
 }
 
-struct snd_soc_platform jz4740_soc_platform = {
-               .name           = "jz4740-pcm",
-               .pcm_ops        = &jz4740_pcm_ops,
+static struct snd_soc_platform_driver jz4740_soc_platform = {
+               .ops            = &jz4740_pcm_ops,
                .pcm_new        = jz4740_pcm_new,
                .pcm_free       = jz4740_pcm_free,
 };
-EXPORT_SYMBOL_GPL(jz4740_soc_platform);
 
 static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&jz4740_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
 }
 
 static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&jz4740_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
        return 0;
 }
 
@@ -351,7 +349,7 @@ static struct platform_driver jz4740_pcm_driver = {
        .probe = jz4740_pcm_probe,
        .remove = __devexit_p(jz4740_pcm_remove),
        .driver = {
-               .name = "jz4740-pcm",
+               .name = "jz4740-pcm-audio",
                .owner = THIS_MODULE,
        },
 };
index e3f221e..1220cbb 100644 (file)
@@ -11,8 +11,6 @@
 #include <linux/dma-mapping.h>
 #include <asm/mach-jz4740/dma.h>
 
-/* platform data */
-extern struct snd_soc_platform jz4740_soc_platform;
 
 struct jz4740_pcm_config {
        struct jz4740_dma_config dma_config;
index f15f491..ef1a99e 100644 (file)
 #include <sound/soc-dapm.h>
 #include <linux/gpio.h>
 
-#include "../codecs/jz4740.h"
-#include "jz4740-pcm.h"
-#include "jz4740-i2s.h"
-
-
 #define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29)
 #define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4)
 
@@ -60,10 +55,11 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = {
                        SND_SOC_DAIFMT_NB_NF | \
                        SND_SOC_DAIFMT_CBM_CFM)
 
-static int qi_lb60_codec_init(struct snd_soc_codec *codec)
+static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
-       struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
 
        snd_soc_dapm_nc_pin(codec, "LIN");
        snd_soc_dapm_nc_pin(codec, "RIN");
@@ -84,8 +80,10 @@ static int qi_lb60_codec_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link qi_lb60_dai = {
        .name = "jz4740",
        .stream_name = "jz4740",
-       .cpu_dai = &jz4740_i2s_dai,
-       .codec_dai = &jz4740_codec_dai,
+       .cpu_dai_name = "jz4740-i2s",
+       .platform_name = "jz4740-pcm-audio",
+       .codec_dai_name = "jz4740-hifi",
+       .codec_name = "jz4740-codec",
        .init = qi_lb60_codec_init,
 };
 
@@ -93,12 +91,6 @@ static struct snd_soc_card qi_lb60 = {
        .name = "QI LB60",
        .dai_link = &qi_lb60_dai,
        .num_links = 1,
-       .platform = &jz4740_soc_platform,
-};
-
-static struct snd_soc_device qi_lb60_snd_devdata = {
-       .card = &qi_lb60,
-       .codec_dev = &soc_codec_dev_jz4740_codec,
 };
 
 static struct platform_device *qi_lb60_snd_device;
@@ -129,8 +121,7 @@ static int __init qi_lb60_init(void)
        gpio_direction_output(QI_LB60_SND_GPIO, 0);
        gpio_direction_output(QI_LB60_AMP_GPIO, 0);
 
-       platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata);
-       qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev;
+       platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
 
        ret = platform_device_add(qi_lb60_snd_device);
        if (ret) {
index a30205b..0fd6a63 100644 (file)
@@ -2,6 +2,7 @@
  * kirkwood-dma.c
  *
  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
+ * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -18,7 +19,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/mbus.h>
 #include <sound/soc.h>
-#include "kirkwood-dma.h"
 #include "kirkwood.h"
 
 #define KIRKWOOD_RATES \
@@ -123,9 +123,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        int err;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
+       struct snd_soc_platform *platform = soc_runtime->platform;
+       struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
        struct kirkwood_dma_data *priv;
-       struct kirkwood_dma_priv *prdata = cpu_dai->private_data;
+       struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
        unsigned long addr;
 
        priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
@@ -151,7 +152,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        if (err < 0)
                return err;
 
-       if (soc_runtime->dai->cpu_dai->private_data == NULL) {
+       if (prdata == NULL) {
                prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);
                if (prdata == NULL)
                        return -ENOMEM;
@@ -165,7 +166,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
                        return -EBUSY;
                }
 
-               soc_runtime->dai->cpu_dai->private_data = prdata;
+               snd_soc_platform_set_drvdata(platform, prdata);
 
                /*
                 * Enable Error interrupts. We're only ack'ing them but
@@ -191,8 +192,9 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
 static int kirkwood_dma_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
-       struct kirkwood_dma_priv *prdata = cpu_dai->private_data;
+       struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
+       struct snd_soc_platform *platform = soc_runtime->platform;
+       struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
        struct kirkwood_dma_data *priv;
 
        priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
@@ -209,7 +211,7 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream)
                writel(0, priv->io + KIRKWOOD_ERR_MASK);
                free_irq(priv->irq, prdata);
                kfree(prdata);
-               soc_runtime->dai->cpu_dai->private_data = NULL;
+               snd_soc_platform_set_drvdata(platform, NULL);
        }
 
        return 0;
@@ -236,7 +238,7 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
        struct kirkwood_dma_data *priv;
        unsigned long size, count;
 
@@ -265,7 +267,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
                                                *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-       struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai;
+       struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
        struct kirkwood_dma_data *priv;
        snd_pcm_uframes_t count;
 
@@ -320,14 +322,14 @@ static int kirkwood_dma_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = 0xffffffff;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = kirkwood_dma_preallocate_dma_buffer(pcm,
                                SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        return ret;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = kirkwood_dma_preallocate_dma_buffer(pcm,
                                SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -357,27 +359,46 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-struct snd_soc_platform kirkwood_soc_platform = {
-       .name           = "kirkwood-dma",
-       .pcm_ops        = &kirkwood_dma_ops,
+static struct snd_soc_platform_driver kirkwood_soc_platform = {
+       .ops            = &kirkwood_dma_ops,
        .pcm_new        = kirkwood_dma_new,
        .pcm_free       = kirkwood_dma_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(kirkwood_soc_platform);
 
-static int __init kirkwood_soc_platform_init(void)
+static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&kirkwood_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
 }
-module_init(kirkwood_soc_platform_init);
 
-static void __exit kirkwood_soc_platform_exit(void)
+static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&kirkwood_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
 }
-module_exit(kirkwood_soc_platform_exit);
 
-MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
+static struct platform_driver kirkwood_pcm_driver = {
+       .driver = {
+                       .name = "kirkwood-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = kirkwood_soc_platform_probe,
+       .remove = __devexit_p(kirkwood_soc_platform_remove),
+};
+
+static int __init kirkwood_pcm_init(void)
+{
+       return platform_driver_register(&kirkwood_pcm_driver);
+}
+module_init(kirkwood_pcm_init);
+
+static void __exit kirkwood_pcm_exit(void)
+{
+       platform_driver_unregister(&kirkwood_pcm_driver);
+}
+module_exit(kirkwood_pcm_exit);
+
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:kirkwood-pcm-audio");
diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h
deleted file mode 100644 (file)
index ba4454c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * kirkwood-dma.h
- *
- * (c) 2010 Arnaud Patard <apatard@mandriva.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.
- */
-
-#ifndef _KIRKWOOD_DMA_H
-#define _KIRKWOOD_DMA_H
-
-extern struct snd_soc_platform kirkwood_soc_platform;
-
-#endif
index 981ffc2..a33fc51 100644 (file)
@@ -2,6 +2,7 @@
  * kirkwood-i2s.c
  *
  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
+ * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
@@ -20,7 +21,6 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <plat/audio.h>
-#include "kirkwood-i2s.h"
 #include "kirkwood.h"
 
 #define DRV_NAME       "kirkwood-i2s"
         SNDRV_PCM_FMTBIT_S24_LE | \
         SNDRV_PCM_FMTBIT_S32_LE)
 
-
-struct snd_soc_dai kirkwood_i2s_dai;
-static struct kirkwood_dma_data *priv;
-
 static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned long mask;
        unsigned long value;
 
@@ -101,10 +98,20 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        } while (value == 0);
 }
 
+static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
+
+       snd_soc_dai_set_dma_data(dai, substream, priv);
+       return 0;
+}
+
 static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
        unsigned int i2s_reg, reg;
        unsigned long i2s_value, value;
 
@@ -171,6 +178,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
 static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
        unsigned long value;
 
        /*
@@ -244,6 +252,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
 static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
        unsigned long value;
 
        value = readl(priv->io + KIRKWOOD_RECCTL);
@@ -323,9 +332,9 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        return 0;
 }
 
-static int kirkwood_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
 {
+       struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
        unsigned long value;
        unsigned int reg_data;
 
@@ -359,21 +368,20 @@ static int kirkwood_i2s_probe(struct platform_device *pdev,
 
 }
 
-static void kirkwood_i2s_remove(struct platform_device *pdev,
-                               struct snd_soc_dai *dai)
+static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
 {
+       return 0;
 }
 
 static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
+       .startup        = kirkwood_i2s_startup,
        .trigger        = kirkwood_i2s_trigger,
        .hw_params      = kirkwood_i2s_hw_params,
        .set_fmt        = kirkwood_i2s_set_fmt,
 };
 
 
-struct snd_soc_dai kirkwood_i2s_dai = {
-       .name = DRV_NAME,
-       .id = 0,
+static struct snd_soc_dai_driver kirkwood_i2s_dai = {
        .probe = kirkwood_i2s_probe,
        .remove = kirkwood_i2s_remove,
        .playback = {
@@ -388,13 +396,13 @@ struct snd_soc_dai kirkwood_i2s_dai = {
                .formats = KIRKWOOD_I2S_FORMATS,},
        .ops = &kirkwood_i2s_dai_ops,
 };
-EXPORT_SYMBOL_GPL(kirkwood_i2s_dai);
 
 static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 {
        struct resource *mem;
        struct kirkwood_asoc_platform_data *data =
                pdev->dev.platform_data;
+       struct kirkwood_dma_data *priv;
        int err;
 
        priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
@@ -403,6 +411,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
                err = -ENOMEM;
                goto error;
        }
+       dev_set_drvdata(&pdev->dev, priv);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
@@ -441,10 +450,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
        priv->dram = data->dram;
        priv->burst = data->burst;
 
-       kirkwood_i2s_dai.capture.dma_data = priv;
-       kirkwood_i2s_dai.playback.dma_data = priv;
-
-       return snd_soc_register_dai(&kirkwood_i2s_dai);
+       return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
 
 err_ioremap:
        iounmap(priv->io);
@@ -458,12 +464,13 @@ error:
 
 static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
 {
-       if (priv) {
-               iounmap(priv->io);
-               release_mem_region(priv->mem->start, SZ_16K);
-               kfree(priv);
-       }
-       snd_soc_unregister_dai(&kirkwood_i2s_dai);
+       struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
+
+       snd_soc_unregister_dai(&pdev->dev);
+       iounmap(priv->io);
+       release_mem_region(priv->mem->start, SZ_16K);
+       kfree(priv);
+
        return 0;
 }
 
@@ -489,7 +496,7 @@ static void __exit kirkwood_i2s_exit(void)
 module_exit(kirkwood_i2s_exit);
 
 /* Module information */
-MODULE_AUTHOR("Arnaud Patard, <apatard@mandriva.com>");
+MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:kirkwood-i2s");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h
deleted file mode 100644 (file)
index c5595c6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * kirkwood-i2s.h
- *
- * (c) 2010 Arnaud Patard <apatard@mandriva.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.
- */
-
-#ifndef _KIRKWOOD_I2S_H
-#define _KIRKWOOD_I2S_H
-
-extern struct snd_soc_dai kirkwood_i2s_dai;
-
-#endif
index 0353d06..9d7c81e 100644 (file)
@@ -2,6 +2,7 @@
  * kirkwood-openrd.c
  *
  * (c) 2010 Arnaud Patard <apatard@mandriva.com>
+ * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
 #include <mach/kirkwood.h>
 #include <plat/audio.h>
 #include <asm/mach-types.h>
-#include "kirkwood-i2s.h"
-#include "kirkwood-dma.h"
 #include "../codecs/cs42l51.h"
 
 static int openrd_client_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
        unsigned int freq, fmt;
 
@@ -66,8 +65,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
 {
        .name = "CS42L51",
        .stream_name = "CS42L51 HiFi",
-       .cpu_dai = &kirkwood_i2s_dai,
-       .codec_dai = &cs42l51_dai,
+       .cpu_dai_name = "kirkwood-i2s",
+       .platform_name = "kirkwood-pcm-audio",
+       .codec_dai_name = "cs42l51-hifi",
+       .codec_name = "cs42l51-codec.0-004a",
        .ops = &openrd_client_ops,
 },
 };
@@ -75,16 +76,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
 
 static struct snd_soc_card openrd_client = {
        .name = "OpenRD Client",
-       .platform = &kirkwood_soc_platform,
        .dai_link = openrd_client_dai,
        .num_links = ARRAY_SIZE(openrd_client_dai),
 };
 
-static struct snd_soc_device openrd_client_snd_devdata = {
-       .card = &openrd_client,
-       .codec_dev = &soc_codec_device_cs42l51,
-};
-
 static struct platform_device *openrd_client_snd_device;
 
 static int __init openrd_client_init(void)
@@ -99,8 +94,7 @@ static int __init openrd_client_init(void)
                return -ENOMEM;
 
        platform_set_drvdata(openrd_client_snd_device,
-                       &openrd_client_snd_devdata);
-       openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev;
+                       &openrd_client);
 
        ret = platform_device_add(openrd_client_snd_device);
        if (ret) {
@@ -120,7 +114,7 @@ module_init(openrd_client_init);
 module_exit(openrd_client_exit);
 
 /* Module information */
-MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
+MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:soc-audio");
index caa7c90..293dc74 100644 (file)
@@ -20,7 +20,6 @@
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
-#include <linux/device.h>
 #include <linux/clk.h>
 
 #include <mach/mfp.h>
@@ -297,8 +296,7 @@ static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
        .trigger        = nuc900_ac97_trigger,
 };
 
-struct snd_soc_dai nuc900_ac97_dai = {
-       .name                   = "nuc900-ac97",
+static struct snd_soc_dai_driver nuc900_ac97_dai = {
        .probe                  = nuc900_ac97_probe,
        .remove                 = nuc900_ac97_remove,
        .ac97_control           = 1,
@@ -316,7 +314,6 @@ struct snd_soc_dai nuc900_ac97_dai = {
        },
        .ops = &nuc900_ac97_dai_ops,
 }
-EXPORT_SYMBOL_GPL(nuc900_ac97_dai);
 
 static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
 {
@@ -365,9 +362,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
 
        nuc900_ac97_data = nuc900_audio;
 
-       nuc900_audio->dev = nuc900_ac97_dai.dev =  &pdev->dev;
-
-       ret = snd_soc_register_dai(&nuc900_ac97_dai);
+       ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai);
        if (ret)
                goto out3;
 
@@ -390,7 +385,7 @@ out0:
 static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
 {
 
-       snd_soc_unregister_dai(&nuc900_ac97_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
        clk_put(nuc900_ac97_data->clk);
        iounmap(nuc900_ac97_data->mmio);
@@ -404,7 +399,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
 
 static struct platform_driver nuc900_ac97_driver = {
        .driver = {
-               .name   = "nuc900-audio",
+               .name   = "nuc900-ac97",
                .owner  = THIS_MODULE,
        },
        .probe          = nuc900_ac97_drvprobe,
index 72e6f51..161f5b6 100644 (file)
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
-#include "../codecs/ac97.h"
 #include "nuc900-audio.h"
 
 static struct snd_soc_dai_link nuc900evb_ac97_dai = {
        .name           = "AC97",
        .stream_name    = "AC97 HiFi",
-       .cpu_dai        = &nuc900_ac97_dai,
-       .codec_dai      = &ac97_dai,
+       .cpu_dai_name   = "nuc900-ac97",
+       .codec_dai_name = "ac97-hifi",
+       .codec_name     = "ac97-codec",
+       .platform_name  = "nuc900-pcm-audio",
 };
 
 static struct snd_soc_card nuc900evb_audio_machine = {
        .name           = "NUC900EVB_AC97",
        .dai_link       = &nuc900evb_ac97_dai,
        .num_links      = 1,
-       .platform       = &nuc900_soc_platform,
-};
-
-static struct snd_soc_device nuc900evb_ac97_devdata = {
-       .card           = &nuc900evb_audio_machine,
-       .codec_dev      = &soc_codec_dev_ac97,
 };
 
 static struct platform_device *nuc900evb_asoc_dev;
@@ -54,9 +49,8 @@ static int __init nuc900evb_audio_init(void)
                goto out;
 
        /* nuc900 board audio device */
-       platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata);
+       platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine);
 
-       nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev;
        ret = platform_device_add(nuc900evb_asoc_dev);
 
        if (ret) {
index 3038f51..aeed8ea 100644 (file)
@@ -110,8 +110,4 @@ struct nuc900_audio {
 
 };
 
-extern struct nuc900_audio *nuc900_ac97_data;
-extern struct snd_soc_dai nuc900_ac97_dai;
-extern struct snd_soc_platform nuc900_soc_platform;
-
 #endif /*end _NUC900_AUDIO_H */
index e81e803..195d1ac 100644 (file)
@@ -328,26 +328,44 @@ static int nuc900_dma_new(struct snd_card *card,
        return 0;
 }
 
-struct snd_soc_platform nuc900_soc_platform = {
-       .name           = "nuc900-dma",
-       .pcm_ops        = &nuc900_dma_ops,
+static struct snd_soc_platform_driver nuc900_soc_platform = {
+       .ops            = &nuc900_dma_ops,
        .pcm_new        = nuc900_dma_new,
        .pcm_free       = nuc900_dma_free_dma_buffers,
 }
-EXPORT_SYMBOL_GPL(nuc900_soc_platform);
 
-static int __init nuc900_soc_platform_init(void)
+static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&nuc900_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);
 }
 
-static void __exit nuc900_soc_platform_exit(void)
+static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&nuc900_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
 }
 
-module_init(nuc900_soc_platform_init);
-module_exit(nuc900_soc_platform_exit);
+static struct platform_driver nuc900_pcm_driver = {
+       .driver = {
+                       .name = "nuc900-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = nuc900_soc_platform_probe,
+       .remove = __devexit_p(nuc900_soc_platform_remove),
+};
+
+static int __init nuc900_pcm_init(void)
+{
+       return platform_driver_register(&nuc900_pcm_driver);
+}
+module_init(nuc900_pcm_init);
+
+static void __exit nuc900_pcm_exit(void)
+{
+       platform_driver_unregister(&nuc900_pcm_driver);
+}
+module_exit(nuc900_pcm_exit);
 
 MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
 MODULE_DESCRIPTION("nuc900 Audio DMA module");
index 135901b..979dd50 100644 (file)
@@ -40,8 +40,8 @@ static int am3517evm_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -111,8 +111,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic In"},
 };
 
-static int am3517evm_aic23_init(struct snd_soc_codec *codec)
+static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        /* Add am3517-evm specific widgets */
        snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
                                  ARRAY_SIZE(tlv320aic23_dapm_widgets));
@@ -134,8 +136,10 @@ static int am3517evm_aic23_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link am3517evm_dai = {
        .name = "TLV320AIC23",
        .stream_name = "AIC23",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &tlv320aic23_dai,
+       .cpu_dai_name ="omap-mcbsp-dai.0",
+       .codec_dai_name = "tlv320aic23-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "tlv320aic23-codec",
        .init = am3517evm_aic23_init,
        .ops = &am3517evm_ops,
 };
@@ -143,27 +147,18 @@ static struct snd_soc_dai_link am3517evm_dai = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_am3517evm = {
        .name = "am3517evm",
-       .platform = &omap_soc_platform,
        .dai_link = &am3517evm_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device am3517evm_snd_devdata = {
-       .card = &snd_soc_am3517evm,
-       .codec_dev = &soc_codec_dev_tlv320aic23,
-};
-
 static struct platform_device *am3517evm_snd_device;
 
 static int __init am3517evm_soc_init(void)
 {
        int ret;
 
-       if (!machine_is_omap3517evm()) {
-               pr_err("Not OMAP3517 / AM3517 EVM!\n");
+       if (!machine_is_omap3517evm())
                return -ENODEV;
-       }
        pr_info("OMAP3517 / AM3517 EVM SoC init\n");
 
        am3517evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -172,9 +167,7 @@ static int __init am3517evm_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata);
-       am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev;
-       *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */
+       platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm);
 
        ret = platform_device_add(am3517evm_snd_device);
        if (ret)
index b0f618e..438146a 100644 (file)
@@ -99,7 +99,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
        int pin, changed = 0;
 
        /* Refuse any mode changes if we are not able to control the codec. */
-       if (!codec->control_data)
+       if (!codec->hw_write)
                return -EUNATCH;
 
        if (ucontrol->value.enumerated.item[0] >= control->max)
@@ -268,10 +268,32 @@ static void cx81801_timeout(unsigned long data)
                ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
 }
 
+/*
+ * Used for passing a codec structure pointer
+ * from the board initialization code to the tty line discipline.
+ */
+static struct snd_soc_codec *cx20442_codec;
+
 /* Line discipline .open() */
 static int cx81801_open(struct tty_struct *tty)
 {
-       return v253_ops.open(tty);
+       int ret;
+
+       if (!cx20442_codec)
+               return -ENODEV;
+
+       /*
+        * Pass the codec structure pointer for use by other ldisc callbacks,
+        * both the card and the codec specific parts.
+        */
+       tty->disc_data = cx20442_codec;
+
+       ret = v253_ops.open(tty);
+
+       if (ret < 0)
+               tty->disc_data = NULL;
+
+       return ret;
 }
 
 /* Line discipline .close() */
@@ -281,11 +303,14 @@ static void cx81801_close(struct tty_struct *tty)
 
        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);
 
+       if (!codec)
+               return;
+
+       v253_ops.close(tty);
+
        /* Revert back to default audio input/output constellation */
        snd_soc_dapm_disable_pin(codec, "Mouthpiece");
        snd_soc_dapm_enable_pin(codec, "Earpiece");
@@ -310,7 +335,10 @@ static void cx81801_receive(struct tty_struct *tty,
        const unsigned char *c;
        int apply, ret;
 
-       if (!codec->control_data) {
+       if (!codec)
+               return;
+
+       if (!codec->hw_write) {
                /* First modem response, complete setup procedure */
 
                /* Initialize timer used for config pulse generation */
@@ -323,7 +351,7 @@ static void cx81801_receive(struct tty_struct *tty,
                                        ARRAY_SIZE(ams_delta_hook_switch_pins),
                                        ams_delta_hook_switch_pins);
                if (ret)
-                       dev_warn(codec->socdev->card->dev,
+                       dev_warn(codec->dev,
                                "Failed to link hook switch to DAPM pins, "
                                "will continue with hook switch unlinked.\n");
 
@@ -383,7 +411,7 @@ static int ams_delta_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
 
        /* Set cpu DAI configuration */
-       return snd_soc_dai_set_fmt(rtd->dai->cpu_dai,
+       return snd_soc_dai_set_fmt(rtd->cpu_dai,
                                   SND_SOC_DAIFMT_DSP_A |
                                   SND_SOC_DAIFMT_NB_NF |
                                   SND_SOC_DAIFMT_CBM_CFM);
@@ -398,7 +426,7 @@ static struct snd_soc_ops ams_delta_ops = {
 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;
+       struct snd_soc_codec *codec = card->rtd->codec;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -461,18 +489,22 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream)
  * Card initialization
  */
 
-static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
+static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_dai *codec_dai = codec->dai;
-       struct snd_soc_card *card = codec->socdev->card;
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_card *card = rtd->card;
        int ret;
        /* Codec is ready, now add/activate board specific controls */
 
+       /* Store a pointer to the codec structure for tty ldisc use */
+       cx20442_codec = codec;
+
        /* 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;
+       if (!codec_dai->driver->ops) {
+               codec_dai->driver->ops = &ams_delta_dai_ops;
+       } else if (!codec_dai->driver->ops->digital_mute) {
+               codec_dai->driver->ops->digital_mute = ams_delta_digital_mute;
        } else {
                ams_delta_ops.startup = ams_delta_startup;
                ams_delta_ops.shutdown = ams_delta_shutdown;
@@ -483,7 +515,7 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
 
        /* 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",
+       ret = snd_soc_jack_new(rtd->codec, "hook_switch",
                                SND_JACK_HEADSET, &ams_delta_hook_switch);
        if (ret)
                dev_warn(card->dev,
@@ -551,27 +583,22 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
 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,
+       .cpu_dai_name ="omap-mcbsp-dai.0",
+       .codec_dai_name = "cx20442-voice",
        .init = ams_delta_cx20442_init,
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "cx20442-codec",
        .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;
@@ -589,9 +616,7 @@ static int __init ams_delta_module_init(void)
                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;
+                               &ams_delta_audio_card);
 
        ret = platform_device_add(ams_delta_audio_platform_device);
        if (ret)
@@ -601,8 +626,8 @@ static int __init ams_delta_module_init(void)
         * 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);
+       cx20442_platform_device =
+               platform_device_register_simple("cx20442-codec", -1, NULL, 0);
        return 0;
 err:
        platform_device_put(ams_delta_audio_platform_device);
@@ -612,19 +637,6 @@ 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");
index 3583c42..fd3a40f 100644 (file)
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 static int igep2_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -82,35 +81,28 @@ static struct snd_soc_ops igep2_ops = {
 static struct snd_soc_dai_link igep2_dai = {
        .name = "TWL4030",
        .stream_name = "TWL4030",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .codec_dai_name = "twl4030-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "twl4030-codec",
        .ops = &igep2_ops,
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_card_igep2 = {
        .name = "igep2",
-       .platform = &omap_soc_platform,
        .dai_link = &igep2_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device igep2_snd_devdata = {
-       .card = &snd_soc_card_igep2,
-       .codec_dev = &soc_codec_dev_twl4030,
-};
-
 static struct platform_device *igep2_snd_device;
 
 static int __init igep2_soc_init(void)
 {
        int ret;
 
-       if (!machine_is_igep0020()) {
-               pr_debug("Not IGEP v2!\n");
+       if (!machine_is_igep0020())
                return -ENODEV;
-       }
        printk(KERN_INFO "IGEP v2 SoC init\n");
 
        igep2_snd_device = platform_device_alloc("soc-audio", -1);
@@ -119,9 +111,7 @@ static int __init igep2_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata);
-       igep2_snd_devdata.dev = &igep2_snd_device->dev;
-       *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);
 
        ret = platform_device_add(igep2_snd_device);
        if (ret)
index 90b8bf7..928f037 100644 (file)
@@ -402,7 +402,7 @@ int omap_mcpdm_set_offset(int offset1, int offset2)
        return 0;
 }
 
-static int __devinit omap_mcpdm_probe(struct platform_device *pdev)
+int __devinit omap_mcpdm_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int ret = 0;
@@ -449,7 +449,7 @@ exit:
        return ret;
 }
 
-static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
+int __devexit omap_mcpdm_remove(struct platform_device *pdev)
 {
        struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
 
@@ -468,18 +468,3 @@ static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_driver omap_mcpdm_driver = {
-       .probe = omap_mcpdm_probe,
-       .remove = __devexit_p(omap_mcpdm_remove),
-       .driver = {
-               .name = "omap-mcpdm",
-       },
-};
-
-static struct platform_device *omap_mcpdm_device;
-
-static int __init omap_mcpdm_init(void)
-{
-       return platform_driver_register(&omap_mcpdm_driver);
-}
-arch_initcall(omap_mcpdm_init);
index 7bb326e..df3e16f 100644 (file)
@@ -149,3 +149,5 @@ extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
 extern int omap_mcpdm_request(void);
 extern void omap_mcpdm_free(void);
 extern int omap_mcpdm_set_offset(int offset1, int offset2);
+int __devinit omap_mcpdm_probe(struct platform_device *pdev);
+int __devexit omap_mcpdm_remove(struct platform_device *pdev);
index 08e09d7..a3b6d89 100644 (file)
@@ -97,7 +97,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        snd_pcm_hw_constraint_minmax(runtime,
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -115,8 +115,8 @@ static int n810_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
@@ -271,8 +271,9 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
                     n810_get_input, n810_set_input),
 };
 
-static int n810_aic33_init(struct snd_soc_codec *codec)
+static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* Not connected */
@@ -307,8 +308,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link n810_dai = {
        .name = "TLV320AIC33",
        .stream_name = "AIC33",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &aic3x_dai,
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "tlv320aic3x-codec.2-0018",
+       .codec_dai_name = "tlv320aic3x-hifi",
        .init = n810_aic33_init,
        .ops = &n810_ops,
 };
@@ -316,33 +319,12 @@ static struct snd_soc_dai_link n810_dai = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_n810 = {
        .name = "N810",
-       .platform = &omap_soc_platform,
        .dai_link = &n810_dai,
        .num_links = 1,
 };
 
-/* Audio private data */
-static struct aic3x_setup_data n810_aic33_setup = {
-       .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
-       .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device n810_snd_devdata = {
-       .card = &snd_soc_n810,
-       .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &n810_aic33_setup,
-};
-
 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,15 +333,11 @@ 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;
 
-       platform_set_drvdata(n810_snd_device, &n810_snd_devdata);
-       n810_snd_devdata.dev = &n810_snd_device->dev;
-       *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(n810_snd_device, &snd_soc_n810);
        err = platform_device_add(n810_snd_device);
        if (err)
                goto err1;
index 86f2139..d211c9f 100644 (file)
@@ -31,7 +31,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "omap-mcbsp.h"
@@ -62,8 +61,6 @@ struct omap_mcbsp_data {
        int                             wlen;
 };
 
-#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
-
 static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
 
 /*
@@ -153,13 +150,13 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {};
 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);
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_pcm_dma_data *dma_data;
        int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
        int words;
 
-       dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
        if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
@@ -203,11 +200,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
 }
 
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
-                                 struct snd_soc_dai *dai)
+                                 struct snd_soc_dai *cpu_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);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        int bus_id = mcbsp_data->bus_id;
        int err = 0;
 
@@ -249,11 +244,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
 }
 
 static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
-                                   struct snd_soc_dai *dai)
+                                   struct snd_soc_dai *cpu_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);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
 
        if (!cpu_dai->active) {
                omap_mcbsp_free(mcbsp_data->bus_id);
@@ -262,11 +255,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
 }
 
 static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
-                                 struct snd_soc_dai *dai)
+                                 struct snd_soc_dai *cpu_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);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
        switch (cmd) {
@@ -295,8 +286,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
                        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);
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        u16 fifo_use;
        snd_pcm_sframes_t delay;
 
@@ -317,11 +308,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
 
 static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *params,
-                                   struct snd_soc_dai *dai)
+                                   struct snd_soc_dai *cpu_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);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        struct omap_pcm_dma_data *dma_data;
        int dma, bus_id = mcbsp_data->bus_id;
@@ -496,7 +485,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                      unsigned int fmt)
 {
-       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        unsigned int temp_fmt = fmt;
 
@@ -596,7 +585,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
                                     int div_id, int div)
 {
-       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
 
        if (div_id != OMAP_MCBSP_CLKGDV)
@@ -608,101 +597,22 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
-                                      int clk_id)
-{
-       int sel_bit;
-       u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
-
-       if (cpu_class_is_omap1()) {
-               /* OMAP1's can use only external source clock */
-               if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
-                       return -EINVAL;
-               else
-                       return 0;
-       }
-
-       if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
-               return -EINVAL;
-
-       if (cpu_is_omap343x())
-               reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
-
-       switch (mcbsp_data->bus_id) {
-       case 0:
-               reg = OMAP2_CONTROL_DEVCONF0;
-               sel_bit = 2;
-               break;
-       case 1:
-               reg = OMAP2_CONTROL_DEVCONF0;
-               sel_bit = 6;
-               break;
-       case 2:
-               reg = reg_devconf1;
-               sel_bit = 0;
-               break;
-       case 3:
-               reg = reg_devconf1;
-               sel_bit = 2;
-               break;
-       case 4:
-               reg = reg_devconf1;
-               sel_bit = 4;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
-               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_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)
 {
-       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int err = 0;
 
+       /* The McBSP signal muxing functions are only available on McBSP1 */
+       if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
+           clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
+           clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
+           clk_id == OMAP_MCBSP_FSR_SRC_FSX)
+               if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
+                       return -EINVAL;
+
        mcbsp_data->in_freq = freq;
 
        switch (clk_id) {
@@ -710,8 +620,20 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                regs->srgr2     |= CLKSM;
                break;
        case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+               if (cpu_class_is_omap1()) {
+                       err = -EINVAL;
+                       break;
+               }
+               err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+                                              MCBSP_CLKS_PRCM_SRC);
+               break;
        case OMAP_MCBSP_SYSCLK_CLKS_EXT:
-               err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
+               if (cpu_class_is_omap1()) {
+                       err = 0;
+                       break;
+               }
+               err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+                                              MCBSP_CLKS_PAD_SRC);
                break;
 
        case OMAP_MCBSP_SYSCLK_CLKX_EXT:
@@ -720,11 +642,18 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                regs->pcr0      |= SCLKME;
                break;
 
+
        case OMAP_MCBSP_CLKR_SRC_CLKR:
+               omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+               break;
        case OMAP_MCBSP_CLKR_SRC_CLKX:
+               omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+               break;
        case OMAP_MCBSP_FSR_SRC_FSR:
+               omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+               break;
        case OMAP_MCBSP_FSR_SRC_FSX:
-               err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
+               omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
                break;
        default:
                err = -ENODEV;
@@ -733,7 +662,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        return err;
 }
 
-static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
+static struct snd_soc_dai_ops mcbsp_dai_ops = {
        .startup        = omap_mcbsp_dai_startup,
        .shutdown       = omap_mcbsp_dai_shutdown,
        .trigger        = omap_mcbsp_dai_trigger,
@@ -744,43 +673,32 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
        .set_sysclk     = omap_mcbsp_dai_set_dai_sysclk,
 };
 
-#define OMAP_MCBSP_DAI_BUILDER(link_id)                                \
-{                                                              \
-       .name = "omap-mcbsp-dai-"#link_id,                      \
-       .id = (link_id),                                        \
-       .playback = {                                           \
-               .channels_min = 1,                              \
-               .channels_max = 16,                             \
-               .rates = OMAP_MCBSP_RATES,                      \
-               .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
-                          SNDRV_PCM_FMTBIT_S32_LE,             \
-       },                                                      \
-       .capture = {                                            \
-               .channels_min = 1,                              \
-               .channels_max = 16,                             \
-               .rates = OMAP_MCBSP_RATES,                      \
-               .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
-                          SNDRV_PCM_FMTBIT_S32_LE,             \
-       },                                                      \
-       .ops = &omap_mcbsp_dai_ops,                             \
-       .private_data = &mcbsp_data[(link_id)].bus_id,          \
+static int mcbsp_dai_probe(struct snd_soc_dai *dai)
+{
+       mcbsp_data[dai->id].bus_id = dai->id;
+       snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
+       return 0;
 }
 
-struct snd_soc_dai omap_mcbsp_dai[] = {
-       OMAP_MCBSP_DAI_BUILDER(0),
-       OMAP_MCBSP_DAI_BUILDER(1),
-#if NUM_LINKS >= 3
-       OMAP_MCBSP_DAI_BUILDER(2),
-#endif
-#if NUM_LINKS == 5
-       OMAP_MCBSP_DAI_BUILDER(3),
-       OMAP_MCBSP_DAI_BUILDER(4),
-#endif
+static struct snd_soc_dai_driver omap_mcbsp_dai =
+{
+       .probe = mcbsp_dai_probe,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 16,
+               .rates = OMAP_MCBSP_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+       },
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 16,
+               .rates = OMAP_MCBSP_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+       },
+       .ops = &mcbsp_dai_ops,
 };
 
-EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
-
-int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
+static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_info *uinfo)
 {
        struct soc_mixer_control *mc =
@@ -910,16 +828,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
 }
 EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
 
+static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+}
+
+static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver asoc_mcbsp_driver = {
+       .driver = {
+                       .name = "omap-mcbsp-dai",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = asoc_mcbsp_probe,
+       .remove = __devexit_p(asoc_mcbsp_remove),
+};
+
 static int __init snd_omap_mcbsp_init(void)
 {
-       return snd_soc_register_dais(omap_mcbsp_dai,
-                                    ARRAY_SIZE(omap_mcbsp_dai));
+       return platform_driver_register(&asoc_mcbsp_driver);
 }
 module_init(snd_omap_mcbsp_init);
 
 static void __exit snd_omap_mcbsp_exit(void)
 {
-       snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
+       platform_driver_unregister(&asoc_mcbsp_driver);
 }
 module_exit(snd_omap_mcbsp_exit);
 
index 6c363e5..ffdcc5a 100644 (file)
@@ -55,8 +55,6 @@ enum omap_mcbsp_div {
 #define NUM_LINKS      5
 #endif
 
-extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
-
 int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
 
 #endif
index b7f4f7e..bed09c2 100644 (file)
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "mcpdm.h"
-#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
 struct omap_mcpdm_data {
@@ -89,11 +87,9 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
 static int omap_mcpdm_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;
        int err = 0;
 
-       if (!cpu_dai->active)
+       if (!dai->active)
                err = omap_mcpdm_request();
 
        return err;
@@ -102,19 +98,14 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
 static void omap_mcpdm_dai_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;
-
-       if (!cpu_dai->active)
+       if (!dai->active)
                omap_mcpdm_free();
 }
 
 static int omap_mcpdm_dai_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;
-       struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
        int stream = substream->stream;
        int err = 0;
 
@@ -143,14 +134,12 @@ static int omap_mcpdm_dai_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;
-       struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
        struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
        int stream = substream->stream;
        int channels, err, link_mask = 0;
 
-       snd_soc_dai_set_dma_data(cpu_dai, substream,
+       snd_soc_dai_set_dma_data(dai, substream,
                                 &omap_mcpdm_dai_dma_params[stream]);
 
        channels = params_channels(params);
@@ -189,9 +178,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 static int omap_mcpdm_dai_hw_free(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_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
+       struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
        struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
        int stream = substream->stream;
        int err;
@@ -215,9 +202,14 @@ static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
 #define OMAP_MCPDM_RATES       (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 #define OMAP_MCPDM_FORMATS     (SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_dai omap_mcpdm_dai = {
-       .name = "omap-mcpdm",
-       .id = -1,
+static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+{
+       snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+       return 0;
+}
+
+static struct snd_soc_dai_driver omap_mcpdm_dai = {
+       .probe = omap_mcpdm_dai_probe,
        .playback = {
                .channels_min = 1,
                .channels_max = 4,
@@ -231,19 +223,47 @@ struct snd_soc_dai omap_mcpdm_dai = {
                .formats = OMAP_MCPDM_FORMATS,
        },
        .ops = &omap_mcpdm_dai_ops,
-       .private_data = &mcpdm_data,
 };
-EXPORT_SYMBOL_GPL(omap_mcpdm_dai);
+
+static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       ret = omap_mcpdm_probe(pdev);
+       if (ret < 0)
+               return ret;
+       ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
+       if (ret < 0)
+               omap_mcpdm_remove(pdev);
+       return ret;
+}
+
+static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       omap_mcpdm_remove(pdev);
+       return 0;
+}
+
+static struct platform_driver asoc_mcpdm_driver = {
+       .driver = {
+                       .name = "omap-mcpdm-dai",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = asoc_mcpdm_probe,
+       .remove = __devexit_p(asoc_mcpdm_remove),
+};
 
 static int __init snd_omap_mcpdm_init(void)
 {
-       return snd_soc_register_dai(&omap_mcpdm_dai);
+       return platform_driver_register(&asoc_mcpdm_driver);
 }
 module_init(snd_omap_mcpdm_init);
 
 static void __exit snd_omap_mcpdm_exit(void)
 {
-       snd_soc_unregister_dai(&omap_mcpdm_dai);
+       platform_driver_unregister(&asoc_mcpdm_driver);
 }
 module_exit(snd_omap_mcpdm_exit);
 
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
deleted file mode 100644 (file)
index 73b80d5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * omap-mcpdm.h
- *
- * Copyright (C) 2009 Texas Instruments
- *
- * Contact: Misael Lopez Cruz <x0052729@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * 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
- *
- */
-
-#ifndef __OMAP_MCPDM_H__
-#define __OMAP_MCPDM_H__
-
-extern struct snd_soc_dai omap_mcpdm_dai;
-
-#endif /* End of __OMAP_MCPDM_H__ */
index 1e52190..8caeb8d 100644 (file)
@@ -101,9 +101,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct omap_runtime_data *prtd = runtime->private_data;
        struct omap_pcm_dma_data *dma_data;
+
        int err = 0;
 
-       dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -374,14 +375,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = omap_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = omap_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -392,25 +393,45 @@ out:
        return ret;
 }
 
-struct snd_soc_platform omap_soc_platform = {
-       .name           = "omap-pcm-audio",
-       .pcm_ops        = &omap_pcm_ops,
+static struct snd_soc_platform_driver omap_soc_platform = {
+       .ops            = &omap_pcm_ops,
        .pcm_new        = omap_pcm_new,
        .pcm_free       = omap_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(omap_soc_platform);
 
-static int __init omap_soc_platform_init(void)
+static __devinit int omap_pcm_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev,
+                       &omap_soc_platform);
+}
+
+static int __devexit omap_pcm_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver omap_pcm_driver = {
+       .driver = {
+                       .name = "omap-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = omap_pcm_probe,
+       .remove = __devexit_p(omap_pcm_remove),
+};
+
+static int __init snd_omap_pcm_init(void)
 {
-       return snd_soc_register_platform(&omap_soc_platform);
+       return platform_driver_register(&omap_pcm_driver);
 }
-module_init(omap_soc_platform_init);
+module_init(snd_omap_pcm_init);
 
-static void __exit omap_soc_platform_exit(void)
+static void __exit snd_omap_pcm_exit(void)
 {
-       snd_soc_unregister_platform(&omap_soc_platform);
+       platform_driver_unregister(&omap_pcm_driver);
 }
-module_exit(omap_soc_platform_exit);
+module_exit(snd_omap_pcm_exit);
 
 MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
 MODULE_DESCRIPTION("OMAP PCM DMA module");
index b19975d..fea0515 100644 (file)
@@ -35,6 +35,4 @@ struct omap_pcm_dma_data {
        int             packet_size;    /* packet size only in PACKET mode */
 };
 
-extern struct snd_soc_platform omap_soc_platform;
-
 #endif
index c7adea3..cf3fc8a 100644 (file)
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 static int omap2evm_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params,
-       struct snd_soc_dai *dai)
+       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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -85,35 +83,28 @@ static struct snd_soc_ops omap2evm_ops = {
 static struct snd_soc_dai_link omap2evm_dai = {
        .name = "TWL4030",
        .stream_name = "TWL4030",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .codec_dai_name = "twl4030-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "twl4030-codec",
        .ops = &omap2evm_ops,
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_omap2evm = {
        .name = "omap2evm",
-       .platform = &omap_soc_platform,
        .dai_link = &omap2evm_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device omap2evm_snd_devdata = {
-       .card = &snd_soc_omap2evm,
-       .codec_dev = &soc_codec_dev_twl4030,
-};
-
 static struct platform_device *omap2evm_snd_device;
 
 static int __init omap2evm_soc_init(void)
 {
        int ret;
 
-       if (!machine_is_omap2evm()) {
-               pr_debug("Not omap2evm!\n");
+       if (!machine_is_omap2evm())
                return -ENODEV;
-       }
        printk(KERN_INFO "omap2evm SoC init\n");
 
        omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -122,9 +113,7 @@ static int __init omap2evm_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata);
-       omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
-       *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm);
 
        ret = platform_device_add(omap2evm_snd_device);
        if (ret)
index 240e097..e56832b 100644 (file)
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 static int omap3beagle_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int fmt;
        int ret;
 
@@ -92,35 +91,29 @@ static struct snd_soc_ops omap3beagle_ops = {
 static struct snd_soc_dai_link omap3beagle_dai = {
        .name = "TWL4030",
        .stream_name = "TWL4030",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .platform_name = "omap-pcm-audio",
+       .codec_dai_name = "twl4030-hifi",
+       .codec_name = "twl4030-codec",
        .ops = &omap3beagle_ops,
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_omap3beagle = {
        .name = "omap3beagle",
-       .platform = &omap_soc_platform,
+       .owner = THIS_MODULE,
        .dai_link = &omap3beagle_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device omap3beagle_snd_devdata = {
-       .card = &snd_soc_omap3beagle,
-       .codec_dev = &soc_codec_dev_twl4030,
-};
-
 static struct platform_device *omap3beagle_snd_device;
 
 static int __init omap3beagle_soc_init(void)
 {
        int ret;
 
-       if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) {
-               pr_debug("Not OMAP3 Beagle or Devkit8000!\n");
+       if (!(machine_is_omap3_beagle() || machine_is_devkit8000()))
                return -ENODEV;
-       }
        pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");
 
        omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
@@ -129,9 +122,7 @@ static int __init omap3beagle_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
-       omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
-       *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);
 
        ret = platform_device_add(omap3beagle_snd_device);
        if (ret)
index dfcb344..810f1e3 100644 (file)
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 static int omap3evm_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -80,42 +79,28 @@ static struct snd_soc_ops omap3evm_ops = {
 static struct snd_soc_dai_link omap3evm_dai = {
        .name           = "TWL4030",
        .stream_name    = "TWL4030",
-       .cpu_dai        = &omap_mcbsp_dai[0],
-       .codec_dai      = &twl4030_dai[TWL4030_DAI_HIFI],
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .codec_dai_name = "twl4030-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "twl4030-codec",
        .ops            = &omap3evm_ops,
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_omap3evm = {
        .name = "omap3evm",
-       .platform = &omap_soc_platform,
        .dai_link = &omap3evm_dai,
        .num_links = 1,
 };
 
-/* twl4030 setup */
-static struct twl4030_setup_data twl4030_setup = {
-       .ramp_delay_value = 4,
-       .sysclk = 26000,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device omap3evm_snd_devdata = {
-       .card = &snd_soc_omap3evm,
-       .codec_dev = &soc_codec_dev_twl4030,
-       .codec_data = &twl4030_setup,
-};
-
 static struct platform_device *omap3evm_snd_device;
 
 static int __init omap3evm_soc_init(void)
 {
        int ret;
 
-       if (!machine_is_omap3evm()) {
-               pr_err("Not OMAP3 EVM!\n");
+       if (!machine_is_omap3evm())
                return -ENODEV;
-       }
        pr_info("OMAP3 EVM SoC init\n");
 
        omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -124,10 +109,7 @@ static int __init omap3evm_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata);
-       omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev;
-       *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1;
-
+       platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);
        ret = platform_device_add(omap3evm_snd_device);
        if (ret)
                goto err1;
index 9eecac1..dbd9d96 100644 (file)
 #include <sound/soc-dapm.h>
 
 #include <asm/mach-types.h>
+#include <plat/mcbsp.h>
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 #define OMAP3_PANDORA_DAC_POWER_GPIO   118
 #define OMAP3_PANDORA_AMP_POWER_GPIO   14
@@ -47,8 +47,8 @@ static int omap3pandora_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                  SND_SOC_DAIFMT_CBS_CFS;
        int ret;
@@ -167,8 +167,9 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
        {"Mic Bias 2", NULL, "Mic (external)"},
 };
 
-static int omap3pandora_out_init(struct snd_soc_codec *codec)
+static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* All TWL4030 output pins are floating */
@@ -194,8 +195,9 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec)
        return snd_soc_dapm_sync(codec);
 }
 
-static int omap3pandora_in_init(struct snd_soc_codec *codec)
+static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* Not comnnected */
@@ -224,15 +226,19 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
        {
                .name = "PCM1773",
                .stream_name = "HiFi Out",
-               .cpu_dai = &omap_mcbsp_dai[0],
-               .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+               .cpu_dai_name = "omap-mcbsp-dai.1",
+               .codec_dai_name = "twl4030-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .ops = &omap3pandora_ops,
                .init = omap3pandora_out_init,
        }, {
                .name = "TWL4030",
                .stream_name = "Line/Mic In",
-               .cpu_dai = &omap_mcbsp_dai[1],
-               .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+               .cpu_dai_name = "omap-mcbsp-dai.3",
+               .codec_dai_name = "twl4030-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .ops = &omap3pandora_ops,
                .init = omap3pandora_in_init,
        }
@@ -241,17 +247,10 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
 /* SoC card */
 static struct snd_soc_card snd_soc_card_omap3pandora = {
        .name = "omap3pandora",
-       .platform = &omap_soc_platform,
        .dai_link = omap3pandora_dai,
        .num_links = ARRAY_SIZE(omap3pandora_dai),
 };
 
-/* Audio subsystem */
-static struct snd_soc_device omap3pandora_snd_data = {
-       .card = &snd_soc_card_omap3pandora,
-       .codec_dev = &soc_codec_dev_twl4030,
-};
-
 static struct platform_device *omap3pandora_snd_device;
 
 static int __init omap3pandora_soc_init(void)
@@ -294,10 +293,7 @@ static int __init omap3pandora_soc_init(void)
                goto fail1;
        }
 
-       platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data);
-       omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
-       *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
-       *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
+       platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);
 
        ret = platform_device_add(omap3pandora_snd_device);
        if (ret) {
index 498ca2e..f0e6625 100644 (file)
@@ -55,8 +55,8 @@ static int osk_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
@@ -113,8 +113,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MICIN", NULL, "Mic Jack"},
 };
 
-static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
+static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* Add osk5912 specific widgets */
        snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -136,8 +137,10 @@ static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link osk_dai = {
        .name = "TLV320AIC23",
        .stream_name = "AIC23",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &tlv320aic23_dai,
+       .cpu_dai_name = "omap-mcbsp-dai.0",
+       .codec_dai_name = "tlv320aic23-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "tlv320aic23-codec",
        .init = osk_tlv320aic23_init,
        .ops = &osk_ops,
 };
@@ -145,17 +148,10 @@ static struct snd_soc_dai_link osk_dai = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_card_osk = {
        .name = "OSK5912",
-       .platform = &omap_soc_platform,
        .dai_link = &osk_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device osk_snd_devdata = {
-       .card = &snd_soc_card_osk,
-       .codec_dev = &soc_codec_dev_tlv320aic23,
-};
-
 static struct platform_device *osk_snd_device;
 
 static int __init osk_soc_init(void)
@@ -171,9 +167,7 @@ static int __init osk_soc_init(void)
        if (!osk_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(osk_snd_device, &osk_snd_devdata);
-       osk_snd_devdata.dev = &osk_snd_device->dev;
-       *(unsigned int *)osk_dai.cpu_dai->private_data = 0;     /* McBSP1 */
+       platform_set_drvdata(osk_snd_device, &snd_soc_card_osk);
        err = platform_device_add(osk_snd_device);
        if (err)
                goto err1;
index c25f527..e95a607 100644 (file)
 
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 static int overo_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -82,25 +81,20 @@ static struct snd_soc_ops overo_ops = {
 static struct snd_soc_dai_link overo_dai = {
        .name = "TWL4030",
        .stream_name = "TWL4030",
-       .cpu_dai = &omap_mcbsp_dai[0],
-       .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+       .cpu_dai_name = "omap-mcbsp-dai.1",
+       .codec_dai_name = "twl4030-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "twl4030-codec",
        .ops = &overo_ops,
 };
 
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_card_overo = {
        .name = "overo",
-       .platform = &omap_soc_platform,
        .dai_link = &overo_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device overo_snd_devdata = {
-       .card = &snd_soc_card_overo,
-       .codec_dev = &soc_codec_dev_twl4030,
-};
-
 static struct platform_device *overo_snd_device;
 
 static int __init overo_soc_init(void)
@@ -119,9 +113,7 @@ static int __init overo_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(overo_snd_device, &overo_snd_devdata);
-       overo_snd_devdata.dev = &overo_snd_device->dev;
-       *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);
 
        ret = platform_device_add(overo_snd_device);
        if (ret)
index 88052d2..04b5723 100644 (file)
@@ -31,6 +31,7 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <plat/mcbsp.h>
 
 #include <asm/mach-types.h>
 
@@ -76,7 +77,7 @@ static int rx51_startup(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        snd_pcm_hw_constraint_minmax(runtime,
                                     SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -89,8 +90,8 @@ static int rx51_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int err;
 
        /* Set codec DAI configuration */
@@ -145,9 +146,9 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w,
                          struct snd_kcontrol *k, int event)
 {
        if (SND_SOC_DAPM_EVENT_ON(event))
-               gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1);
+               gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1);
        else
-               gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0);
+               gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0);
 
        return 0;
 }
@@ -240,9 +241,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
                     rx51_get_jack, rx51_set_jack),
 };
 
-static int rx51_aic34_init(struct snd_soc_codec *codec)
+static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 {
-       struct snd_soc_card *card = codec->socdev->card;
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* Set up NC codec pins */
@@ -266,7 +267,7 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)
        snd_soc_dapm_sync(codec);
 
        /* AV jack detection */
-       err = snd_soc_jack_new(card, "AV Jack",
+       err = snd_soc_jack_new(codec, "AV Jack",
                               SND_JACK_VIDEOOUT, &rx51_av_jack);
        if (err)
                return err;
@@ -282,32 +283,20 @@ static struct snd_soc_dai_link rx51_dai[] = {
        {
                .name = "TLV320AIC34",
                .stream_name = "AIC34",
-               .cpu_dai = &omap_mcbsp_dai[0],
-               .codec_dai = &aic3x_dai,
+               .cpu_dai_name = "omap-mcbsp-dai.1",
+               .codec_dai_name = "tlv320aic3x-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "tlv320aic3x-codec.2-0018",
                .init = rx51_aic34_init,
                .ops = &rx51_ops,
        },
 };
 
-/* Audio private data */
-static struct aic3x_setup_data rx51_aic34_setup = {
-       .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
-       .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
-};
-
 /* Audio card */
 static struct snd_soc_card rx51_sound_card = {
        .name = "RX-51",
        .dai_link = rx51_dai,
        .num_links = ARRAY_SIZE(rx51_dai),
-       .platform = &omap_soc_platform,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device rx51_snd_devdata = {
-       .card = &rx51_sound_card,
-       .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &rx51_aic34_setup,
 };
 
 static struct platform_device *rx51_snd_device;
@@ -330,9 +319,7 @@ static int __init rx51_soc_init(void)
                goto err1;
        }
 
-       platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata);
-       rx51_snd_devdata.dev = &rx51_snd_device->dev;
-       *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
+       platform_set_drvdata(rx51_snd_device, &rx51_sound_card);
 
        err = platform_device_add(rx51_snd_device);
        if (err)
index 3c85c0f..07fbcf7 100644 (file)
 #include <mach/gpio.h>
 #include <plat/mcbsp.h>
 
+/* Register descriptions for twl4030 codec part */
+#include <linux/mfd/twl4030-codec.h>
+
 #include "omap-mcbsp.h"
 #include "omap-pcm.h"
-#include "../codecs/twl4030.h"
 
 /* TWL4030 PMBR1 Register */
 #define TWL4030_INTBR_PMBR1            0x0D
@@ -51,8 +53,8 @@ static int sdp3430_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -94,8 +96,8 @@ static int sdp3430_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -186,8 +188,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Headset Stereophone", NULL, "HSOR"},
 };
 
-static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
+static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* Add SDP3430 specific widgets */
@@ -225,7 +228,7 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
                return ret;
 
        /* Headset jack detection */
-       ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack",
+       ret = snd_soc_jack_new(codec, "Headset Jack",
                                SND_JACK_HEADSET, &hs_jack);
        if (ret)
                return ret;
@@ -241,14 +244,15 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
        return ret;
 }
 
-static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec)
+static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        unsigned short reg;
 
        /* Enable voice interface */
-       reg = codec->read(codec, TWL4030_REG_VOICE_IF);
+       reg = codec->driver->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);
+       codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
 
        return 0;
 }
@@ -259,16 +263,20 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
        {
                .name = "TWL4030 I2S",
                .stream_name = "TWL4030 Audio",
-               .cpu_dai = &omap_mcbsp_dai[0],
-               .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+               .cpu_dai_name = "omap-mcbsp-dai.1",
+               .codec_dai_name = "twl4030-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .init = sdp3430_twl4030_init,
                .ops = &sdp3430_ops,
        },
        {
                .name = "TWL4030 PCM",
                .stream_name = "TWL4030 Voice",
-               .cpu_dai = &omap_mcbsp_dai[1],
-               .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
+               .cpu_dai_name = "omap-mcbsp-dai.2",
+               .codec_dai_name = "twl4030-voice",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .init = sdp3430_twl4030_voice_init,
                .ops = &sdp3430_voice_ops,
        },
@@ -277,25 +285,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_sdp3430 = {
        .name = "SDP3430",
-       .platform = &omap_soc_platform,
        .dai_link = sdp3430_dai,
        .num_links = ARRAY_SIZE(sdp3430_dai),
 };
 
-/* twl4030 setup */
-static struct twl4030_setup_data twl4030_setup = {
-       .ramp_delay_value = 3,
-       .sysclk = 26000,
-       .hs_extmute = 1,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device sdp3430_snd_devdata = {
-       .card = &snd_soc_sdp3430,
-       .codec_dev = &soc_codec_dev_twl4030,
-       .codec_data = &twl4030_setup,
-};
-
 static struct platform_device *sdp3430_snd_device;
 
 static int __init sdp3430_soc_init(void)
@@ -303,10 +296,8 @@ static int __init sdp3430_soc_init(void)
        int ret;
        u8 pin_mux;
 
-       if (!machine_is_omap_3430sdp()) {
-               pr_debug("Not SDP3430!\n");
+       if (!machine_is_omap_3430sdp())
                return -ENODEV;
-       }
        printk(KERN_INFO "SDP3430 SoC init\n");
 
        sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
@@ -315,10 +306,7 @@ static int __init sdp3430_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
-       sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
-       *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
-       *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
+       platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430);
 
        /* Set TWL4030 GPIO6 as EXTMUTE signal */
        twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
index 4ebbde6..4b4463d 100644 (file)
@@ -31,7 +31,6 @@
 #include <plat/mux.h>
 
 #include "mcpdm.h"
-#include "omap-mcpdm.h"
 #include "omap-pcm.h"
 #include "../codecs/twl6040.h"
 
@@ -41,7 +40,7 @@ static int sdp4430_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 *codec_dai = rtd->codec_dai;
        int clk_id, freq;
        int ret;
 
@@ -60,6 +59,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
                printk(KERN_ERR "can't set codec system clock\n");
                return ret;
        }
+       return ret;
 }
 
 static struct snd_soc_ops sdp4430_ops = {
@@ -126,8 +126,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Earphone Spk", NULL, "EP"},
 };
 
-static int sdp4430_twl6040_init(struct snd_soc_codec *codec)
+static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* Add SDP4430 specific controls */
@@ -164,8 +165,10 @@ static int sdp4430_twl6040_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link sdp4430_dai = {
        .name = "TWL6040",
        .stream_name = "TWL6040",
-       .cpu_dai = &omap_mcpdm_dai,
-       .codec_dai = &twl6040_dai,
+       .cpu_dai_name ="omap-mcpdm-dai",
+       .codec_dai_name = "twl6040-hifi",
+       .platform_name = "omap-pcm-audio",
+       .codec_name = "twl6040-codec",
        .init = sdp4430_twl6040_init,
        .ops = &sdp4430_ops,
 };
@@ -173,27 +176,18 @@ static struct snd_soc_dai_link sdp4430_dai = {
 /* Audio machine driver */
 static struct snd_soc_card snd_soc_sdp4430 = {
        .name = "SDP4430",
-       .platform = &omap_soc_platform,
        .dai_link = &sdp4430_dai,
        .num_links = 1,
 };
 
-/* Audio subsystem */
-static struct snd_soc_device sdp4430_snd_devdata = {
-       .card = &snd_soc_sdp4430,
-       .codec_dev = &soc_codec_dev_twl6040,
-};
-
 static struct platform_device *sdp4430_snd_device;
 
 static int __init sdp4430_soc_init(void)
 {
        int ret;
 
-       if (!machine_is_omap_4430sdp()) {
-               pr_debug("Not SDP4430!\n");
+       if (!machine_is_omap_4430sdp())
                return -ENODEV;
-       }
        printk(KERN_INFO "SDP4430 SoC init\n");
 
        sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
@@ -202,8 +196,7 @@ static int __init sdp4430_soc_init(void)
                return -ENOMEM;
        }
 
-       platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata);
-       sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev;
+       platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
 
        ret = platform_device_add(sdp4430_snd_device);
        if (ret)
index 50a94ee..718031e 100644 (file)
 #include <asm/mach-types.h>
 #include <mach/hardware.h>
 #include <mach/gpio.h>
+#include <mach/board-zoom.h>
 #include <plat/mcbsp.h>
 
+/* Register descriptions for twl4030 codec part */
+#include <linux/mfd/twl4030-codec.h>
+
 #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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -85,8 +87,8 @@ 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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set codec DAI configuration */
@@ -157,8 +159,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Aux In", NULL, "AUXR"},
 };
 
-static int zoom2_twl4030_init(struct snd_soc_codec *codec)
+static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* Add Zoom2 specific widgets */
@@ -192,14 +195,15 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec)
        return ret;
 }
 
-static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec)
+static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        unsigned short reg;
 
        /* Enable voice interface */
-       reg = codec->read(codec, TWL4030_REG_VOICE_IF);
+       reg = codec->driver->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);
+       codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
 
        return 0;
 }
@@ -209,16 +213,20 @@ 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],
+               .cpu_dai_name = "omap-mcbsp-dai.1",
+               .codec_dai_name = "twl4030-hifi",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .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],
+               .cpu_dai_name = "omap-mcbsp-dai.2",
+               .codec_dai_name = "twl4030-voice",
+               .platform_name = "omap-pcm-audio",
+               .codec_name = "twl4030-codec",
                .init = zoom2_twl4030_voice_init,
                .ops = &zoom2_voice_ops,
        },
@@ -227,42 +235,18 @@ static struct snd_soc_dai_link zoom2_dai[] = {
 /* 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");
+       if (!machine_is_omap_zoom2())
                return -ENODEV;
-       }
        printk(KERN_INFO "Zoom2 SoC init\n");
 
        zoom2_snd_device = platform_device_alloc("soc-audio", -1);
@@ -271,11 +255,7 @@ static int __init zoom2_soc_init(void)
                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 */
-
+       platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2);
        ret = platform_device_add(zoom2_snd_device);
        if (ret)
                goto err1;
index e30c832..37f191b 100644 (file)
@@ -117,6 +117,24 @@ config SND_PXA2XX_SOC_PALM27X
          Say Y if you want to add support for SoC audio on
          Palm T|X, T5, E2 or LifeDrive handheld computer.
 
+config SND_SOC_SAARB
+       tristate "SoC Audio support for Marvell Saarb"
+       depends on SND_PXA2XX_SOC && MACH_SAARB
+       select SND_PXA_SOC_SSP
+       select SND_SOC_88PM860X
+       help
+         Say Y if you want to add support for SoC audio on the
+         Marvell Saarb reference platform.
+
+config SND_SOC_TAVOREVB3
+       tristate "SoC Audio support for Marvell Tavor EVB3"
+       depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
+       select SND_PXA_SOC_SSP
+       select SND_SOC_88PM860X
+       help
+         Say Y if you want to add support for SoC audio on the
+         Marvell Saarb reference platform.
+
 config SND_SOC_ZYLONITE
        tristate "SoC Audio support for Marvell Zylonite"
        depends on SND_PXA2XX_SOC && MACH_ZYLONITE
index caa03d8..0766016 100644 (file)
@@ -19,6 +19,8 @@ snd-soc-e800-objs := e800_wm9712.o
 snd-soc-spitz-objs := spitz.o
 snd-soc-em-x270-objs := em-x270.o
 snd-soc-palm27x-objs := palm27x.o
+snd-soc-saarb-objs := saarb.o
+snd-soc-tavorevb3-objs := tavorevb3.o
 snd-soc-zylonite-objs := zylonite.o
 snd-soc-magician-objs := magician.o
 snd-soc-mioa701-objs := mioa701_wm9713.o
@@ -38,6 +40,8 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
 obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
 obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
 obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o
+obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o
+obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
 obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
 obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
 obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
index fefe1a5..97e9423 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/audio.h>
 
 #include "../codecs/wm8731.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
 #define CORGI_HP        0
@@ -99,7 +98,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
 static int corgi_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* check the jack status at stream startup */
        corgi_ext_control(codec);
@@ -118,8 +117,8 @@ static int corgi_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -150,7 +149,7 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -272,8 +271,9 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
 /*
  * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
  */
-static int corgi_wm8731_init(struct snd_soc_codec *codec)
+static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        snd_soc_dapm_nc_pin(codec, "LLINEIN");
@@ -300,8 +300,10 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link corgi_dai = {
        .name = "WM8731",
        .stream_name = "WM8731",
-       .cpu_dai = &pxa_i2s_dai,
-       .codec_dai = &wm8731_dai,
+       .cpu_dai_name = "pxa-is2-dai",
+       .codec_dai_name = "wm8731-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm8731-codec-0.001a",
        .init = corgi_wm8731_init,
        .ops = &corgi_ops,
 };
@@ -309,17 +311,10 @@ static struct snd_soc_dai_link corgi_dai = {
 /* corgi audio machine driver */
 static struct snd_soc_card snd_soc_corgi = {
        .name = "Corgi",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = &corgi_dai,
        .num_links = 1,
 };
 
-/* corgi audio subsystem */
-static struct snd_soc_device corgi_snd_devdata = {
-       .card = &snd_soc_corgi,
-       .codec_dev = &soc_codec_dev_wm8731,
-};
-
 static struct platform_device *corgi_snd_device;
 
 static int __init corgi_init(void)
@@ -334,8 +329,7 @@ static int __init corgi_init(void)
        if (!corgi_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata);
-       corgi_snd_devdata.dev = &corgi_snd_device->dev;
+       platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);
        ret = platform_device_add(corgi_snd_device);
 
        if (ret)
index 7cd2f89..c82cedb 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/mach-types.h>
 
 #include "../codecs/wm9705.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 
@@ -90,8 +89,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Mic Amp", NULL, "Mic (Internal)"},
 };
 
-static int e740_ac97_init(struct snd_soc_codec *codec)
+static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_nc_pin(codec, "HPOUTL");
        snd_soc_dapm_nc_pin(codec, "HPOUTR");
        snd_soc_dapm_nc_pin(codec, "PHONE");
@@ -116,30 +117,28 @@ static struct snd_soc_dai_link e740_dai[] = {
        {
                .name = "AC97",
                .stream_name = "AC97 HiFi",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-               .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+               .cpu_dai_name = "pxa-ac97.0",
+               .codec_dai_name = "wm9705-hifi",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9705-codec",
                .init = e740_ac97_init,
        },
        {
                .name = "AC97 Aux",
                .stream_name = "AC97 Aux",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-               .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+               .cpu_dai_name = "pxa-ac97.1",
+               .codec_dai_name = "wm9705-aux",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9705-codec",
        },
 };
 
 static struct snd_soc_card e740 = {
        .name = "Toshiba e740",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = e740_dai,
        .num_links = ARRAY_SIZE(e740_dai),
 };
 
-static struct snd_soc_device e740_snd_devdata = {
-       .card = &e740,
-       .codec_dev = &soc_codec_dev_wm9705,
-};
-
 static struct platform_device *e740_snd_device;
 
 static int __init e740_init(void)
@@ -178,8 +177,7 @@ static int __init e740_init(void)
                goto free_apwr_gpio;
        }
 
-       platform_set_drvdata(e740_snd_device, &e740_snd_devdata);
-       e740_snd_devdata.dev = &e740_snd_device->dev;
+       platform_set_drvdata(e740_snd_device, &e740);
        ret = platform_device_add(e740_snd_device);
 
        if (!ret)
@@ -200,6 +198,9 @@ free_mic_amp_gpio:
 static void __exit e740_exit(void)
 {
        platform_device_unregister(e740_snd_device);
+       gpio_free(GPIO_E740_WM9705_nAVDD2);
+       gpio_free(GPIO_E740_AMP_ON);
+       gpio_free(GPIO_E740_MIC_ON);
 }
 
 module_init(e740_init);
index 8dceccc..4c14380 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/mach-types.h>
 
 #include "../codecs/wm9705.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
@@ -72,8 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MIC1", NULL, "Mic (Internal)"},
 };
 
-static int e750_ac97_init(struct snd_soc_codec *codec)
+static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_nc_pin(codec, "LOUT");
        snd_soc_dapm_nc_pin(codec, "ROUT");
        snd_soc_dapm_nc_pin(codec, "PHONE");
@@ -98,31 +99,29 @@ static struct snd_soc_dai_link e750_dai[] = {
        {
                .name = "AC97",
                .stream_name = "AC97 HiFi",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-               .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI],
+               .cpu_dai_name = "pxa-ac97.0",
+               .codec_dai_name = "wm9705-hifi",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9705-codec",
                .init = e750_ac97_init,
                /* use ops to check startup state */
        },
        {
                .name = "AC97 Aux",
                .stream_name = "AC97 Aux",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-               .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX],
+               .cpu_dai_name = "pxa-ac97.1",
+               .codec_dai_name ="wm9705-aux",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9705-codec",
        },
 };
 
 static struct snd_soc_card e750 = {
        .name = "Toshiba e750",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = e750_dai,
        .num_links = ARRAY_SIZE(e750_dai),
 };
 
-static struct snd_soc_device e750_snd_devdata = {
-       .card = &e750,
-       .codec_dev = &soc_codec_dev_wm9705,
-};
-
 static struct platform_device *e750_snd_device;
 
 static int __init e750_init(void)
@@ -154,8 +153,7 @@ static int __init e750_init(void)
                goto free_spk_amp_gpio;
        }
 
-       platform_set_drvdata(e750_snd_device, &e750_snd_devdata);
-       e750_snd_devdata.dev = &e750_snd_device->dev;
+       platform_set_drvdata(e750_snd_device, &e750);
        ret = platform_device_add(e750_snd_device);
 
        if (!ret)
index bc019cd..d42e5fe 100644 (file)
@@ -23,7 +23,6 @@
 #include <mach/eseries-gpio.h>
 
 #include "../codecs/wm9712.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
@@ -73,8 +72,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"MIC2", NULL, "Mic (Internal2)"},
 };
 
-static int e800_ac97_init(struct snd_soc_codec *codec)
+static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_new_controls(codec, e800_dapm_widgets,
                                        ARRAY_SIZE(e800_dapm_widgets));
 
@@ -88,30 +89,28 @@ static struct snd_soc_dai_link e800_dai[] = {
        {
                .name = "AC97",
                .stream_name = "AC97 HiFi",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+               .cpu_dai_name = "pxa-ac97.0",
+               .codec_dai_name = "wm9712-hifi",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9712-codec",
                .init = e800_ac97_init,
        },
        {
                .name = "AC97 Aux",
                .stream_name = "AC97 Aux",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+               .cpu_dai_name = "pxa-ac97.1",
+               .codec_dai_name ="wm9712-aux",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9712-codec",
        },
 };
 
 static struct snd_soc_card e800 = {
        .name = "Toshiba e800",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = e800_dai,
        .num_links = ARRAY_SIZE(e800_dai),
 };
 
-static struct snd_soc_device e800_snd_devdata = {
-       .card = &e800,
-       .codec_dev = &soc_codec_dev_wm9712,
-};
-
 static struct platform_device *e800_snd_device;
 
 static int __init e800_init(void)
@@ -141,8 +140,7 @@ static int __init e800_init(void)
        if (!e800_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(e800_snd_device, &e800_snd_devdata);
-       e800_snd_devdata.dev = &e800_snd_device->dev;
+       platform_set_drvdata(e800_snd_device, &e800);
        ret = platform_device_add(e800_snd_device);
 
        if (!ret)
index f4756e4..eadf9d3 100644 (file)
 #include <mach/audio.h>
 
 #include "../codecs/wm9712.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static struct snd_soc_dai_link em_x270_dai[] = {
        {
                .name = "AC97",
                .stream_name = "AC97 HiFi",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+               .cpu_dai_name = "pxa-ac97.0",
+               .codec_dai_name = "wm9712-hifi",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9712-codec",
        },
        {
                .name = "AC97 Aux",
                .stream_name = "AC97 Aux",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-               .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+               .cpu_dai_name = "pxa-ac97.1",
+               .codec_dai_name ="wm9712-aux",
+               .platform_name = "pxa-pcm-audio",
+               .codec_name = "wm9712-codec",
        },
 };
 
 static struct snd_soc_card em_x270 = {
        .name = "EM-X270",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = em_x270_dai,
        .num_links = ARRAY_SIZE(em_x270_dai),
 };
 
-static struct snd_soc_device em_x270_snd_devdata = {
-       .card = &em_x270,
-       .codec_dev = &soc_codec_dev_wm9712,
-};
-
 static struct platform_device *em_x270_snd_device;
 
 static int __init em_x270_init(void)
@@ -76,8 +73,7 @@ static int __init em_x270_init(void)
        if (!em_x270_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata);
-       em_x270_snd_devdata.dev = &em_x270_snd_device->dev;
+       platform_set_drvdata(em_x270_snd_device, &em_x270);
        ret = platform_device_add(em_x270_snd_device);
 
        if (ret)
index 405587a..154fc6f 100644 (file)
@@ -6,14 +6,13 @@
 
 #include "../codecs/wm8940.h"
 #include "pxa2xx-i2s.h"
-#include "pxa2xx-pcm.h"
 
 static int imote2_asoc_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret;
 
@@ -64,23 +63,19 @@ static struct snd_soc_ops imote2_asoc_ops = {
 static struct snd_soc_dai_link imote2_dai = {
        .name = "WM8940",
        .stream_name = "WM8940",
-       .cpu_dai = &pxa_i2s_dai,
-       .codec_dai = &wm8940_dai,
+       .cpu_dai_name = "pxa2xx-i2s",
+       .codec_dai_name = "wm8940-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm8940-codec.0-0034",
        .ops = &imote2_asoc_ops,
 };
 
 static struct snd_soc_card snd_soc_imote2 = {
        .name = "Imote2",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = &imote2_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device imote2_snd_devdata = {
-       .card = &snd_soc_imote2,
-       .codec_dev = &soc_codec_dev_wm8940,
-};
-
 static struct platform_device *imote2_snd_device;
 
 static int __init imote2_asoc_init(void)
@@ -93,8 +88,7 @@ static int __init imote2_asoc_init(void)
        if (!imote2_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata);
-       imote2_snd_devdata.dev = &imote2_snd_device->dev;
+       platform_set_drvdata(imote2_snd_device, &snd_soc_imote2);
        ret = platform_device_add(imote2_snd_device);
        if (ret)
                platform_device_put(imote2_snd_device);
index 4c8d99a..b8207ce 100644 (file)
@@ -32,7 +32,6 @@
 #include <mach/magician.h>
 #include <asm/mach-types.h>
 #include "../codecs/uda1380.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 #include "pxa-ssp.h"
 
@@ -71,7 +70,7 @@ static void magician_ext_control(struct snd_soc_codec *codec)
 static int magician_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* check the jack status at stream startup */
        magician_ext_control(codec);
@@ -86,8 +85,8 @@ static int magician_playback_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int acps, acds, width, rate;
        unsigned int div4 = PXA_SSP_CLK_SCDB_4;
        int ret = 0;
@@ -227,8 +226,8 @@ static int magician_capture_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret = 0;
 
        /* set codec DAI configuration */
@@ -393,8 +392,9 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = {
 /*
  * Logic for a uda1380 as connected on a HTC Magician
  */
-static int magician_uda1380_init(struct snd_soc_codec *codec)
+static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* NC codec pins */
@@ -427,16 +427,20 @@ static struct snd_soc_dai_link magician_dai[] = {
 {
        .name = "uda1380",
        .stream_name = "UDA1380 Playback",
-       .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
-       .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK],
+       .cpu_dai_name = "pxa-ssp-dai.0",
+       .codec_dai_name = "uda1380-hifi-playback",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "uda1380-codec.0-0018",
        .init = magician_uda1380_init,
        .ops = &magician_playback_ops,
 },
 {
        .name = "uda1380",
        .stream_name = "UDA1380 Capture",
-       .cpu_dai = &pxa_i2s_dai,
-       .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE],
+       .cpu_dai_name = "pxa2xx-i2s",
+       .codec_dai_name = "uda1380-hifi-capture",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "uda1380-codec.0-0018",
        .ops = &magician_capture_ops,
 }
 };
@@ -446,13 +450,7 @@ static struct snd_soc_card snd_soc_card_magician = {
        .name = "Magician",
        .dai_link = magician_dai,
        .num_links = ARRAY_SIZE(magician_dai),
-       .platform = &pxa2xx_soc_platform,
-};
 
-/* magician audio subsystem */
-static struct snd_soc_device magician_snd_devdata = {
-       .card = &snd_soc_card_magician,
-       .codec_dev = &soc_codec_dev_uda1380,
 };
 
 static struct platform_device *magician_snd_device;
@@ -514,8 +512,7 @@ static int __init magician_init(void)
                goto err_pdev;
        }
 
-       platform_set_drvdata(magician_snd_device, &magician_snd_devdata);
-       magician_snd_devdata.dev = &magician_snd_device->dev;
+       platform_set_drvdata(magician_snd_device, &snd_soc_card_magician);
        ret = platform_device_add(magician_snd_device);
        if (ret) {
                platform_device_put(magician_snd_device);
index 19eda8b..f284cc5 100644 (file)
@@ -54,7 +54,6 @@
 #include <sound/initval.h>
 #include <sound/ac97_codec.h>
 
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 #include "../codecs/wm9713.h"
 
@@ -128,8 +127,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Rear Speaker", NULL, "SPKR"},
 };
 
-static int mioa701_wm9713_init(struct snd_soc_codec *codec)
+static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        unsigned short reg;
 
        /* Add mioa701 specific widgets */
@@ -139,12 +139,12 @@ static int mioa701_wm9713_init(struct snd_soc_codec *codec)
        snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map));
 
        /* Prepare GPIO8 for rear speaker amplifier */
-       reg = codec->read(codec, AC97_GPIO_CFG);
-       codec->write(codec, AC97_GPIO_CFG, reg | 0x0100);
+       reg = codec->driver->read(codec, AC97_GPIO_CFG);
+       codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100);
 
        /* Prepare MIC input */
-       reg = codec->read(codec, AC97_3D_CONTROL);
-       codec->write(codec, AC97_3D_CONTROL, reg | 0xc000);
+       reg = codec->driver->read(codec, AC97_3D_CONTROL);
+       codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000);
 
        snd_soc_dapm_enable_pin(codec, "Front Speaker");
        snd_soc_dapm_enable_pin(codec, "Rear Speaker");
@@ -162,32 +162,30 @@ static struct snd_soc_dai_link mioa701_dai[] = {
        {
                .name = "AC97",
                .stream_name = "AC97 HiFi",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-               .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+               .cpu_dai_name = "pxa-ac97.0",
+               .codec_dai_name = "wm9713-hifi",
+               .codec_name = "wm9713-codec",
                .init = mioa701_wm9713_init,
+               .platform_name = "pxa-pcm-audio",
                .ops = &mioa701_ops,
        },
        {
                .name = "AC97 Aux",
                .stream_name = "AC97 Aux",
-               .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-               .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+               .cpu_dai_name = "pxa-ac97.1",
+               .codec_dai_name ="wm9713-aux",
+               .codec_name = "wm9713-codec",
+               .platform_name = "pxa-pcm-audio",
                .ops = &mioa701_ops,
        },
 };
 
 static struct snd_soc_card mioa701 = {
        .name = "MioA701",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = mioa701_dai,
        .num_links = ARRAY_SIZE(mioa701_dai),
 };
 
-static struct snd_soc_device mioa701_snd_devdata = {
-       .card = &mioa701,
-       .codec_dev = &soc_codec_dev_wm9713,
-};
-
 static struct platform_device *mioa701_snd_device;
 
 static int mioa701_wm9713_probe(struct platform_device *pdev)
@@ -205,8 +203,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
        if (!mioa701_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata);
-       mioa701_snd_devdata.dev = &mioa701_snd_device->dev;
+       platform_set_drvdata(mioa701_snd_device, &mioa701);
 
        ret = platform_device_add(mioa701_snd_device);
        if (!ret)
index 1f96e32..13f6d48 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/palmasoc.h>
 
 #include "../codecs/wm9712.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static struct snd_soc_jack hs_jack;
@@ -75,8 +74,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
 
 static struct snd_soc_card palm27x_asoc;
 
-static int palm27x_ac97_init(struct snd_soc_codec *codec)
+static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* add palm27x specific widgets */
@@ -112,7 +112,7 @@ static int palm27x_ac97_init(struct snd_soc_codec *codec)
                return err;
 
        /* Jack detection API stuff */
-       err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack",
+       err = snd_soc_jack_new(codec, "Headphone Jack",
                                SND_JACK_HEADPHONE, &hs_jack);
        if (err)
                return err;
@@ -132,30 +132,28 @@ static struct snd_soc_dai_link palm27x_dai[] = {
 {
        .name = "AC97 HiFi",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-       .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+       .cpu_dai_name = "pxa-ac97.0",
+       .codec_dai_name =  "wm9712-hifi",
+       .codec_name = "wm9712-codec",
+       .platform_name = "pxa-pcm-audio",
        .init = palm27x_ac97_init,
 },
 {
        .name = "AC97 Aux",
        .stream_name = "AC97 Aux",
-       .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-       .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
+       .cpu_dai_name = "pxa-ac97.1",
+       .codec_dai_name = "wm9712-aux",
+       .codec_name = "wm9712-codec",
+       .platform_name = "pxa-pcm-audio",
 },
 };
 
 static struct snd_soc_card palm27x_asoc = {
        .name = "Palm/PXA27x",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = palm27x_dai,
        .num_links = ARRAY_SIZE(palm27x_dai),
 };
 
-static struct snd_soc_device palm27x_snd_devdata = {
-       .card = &palm27x_asoc,
-       .codec_dev = &soc_codec_dev_wm9712,
-};
-
 static struct platform_device *palm27x_snd_device;
 
 static int palm27x_asoc_probe(struct platform_device *pdev)
@@ -178,8 +176,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
        if (!palm27x_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
-       palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
+       platform_set_drvdata(palm27x_snd_device, &palm27x_asoc);
        ret = platform_device_add(palm27x_snd_device);
 
        if (ret != 0)
index c5f36e0..af84ee9 100644 (file)
@@ -31,7 +31,6 @@
 #include <mach/audio.h>
 
 #include "../codecs/wm8731.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
 #define POODLE_HP        1
@@ -76,7 +75,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec)
 static int poodle_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* check the jack status at stream startup */
        poodle_ext_control(codec);
@@ -97,8 +96,8 @@ static int poodle_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -129,7 +128,7 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
                return ret;
 
        /* set the codec system clock for DAC and ADC */
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk,
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
                SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
@@ -237,8 +236,9 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
 /*
  * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
  */
-static int poodle_wm8731_init(struct snd_soc_codec *codec)
+static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        snd_soc_dapm_nc_pin(codec, "LLINEIN");
@@ -266,8 +266,10 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link poodle_dai = {
        .name = "WM8731",
        .stream_name = "WM8731",
-       .cpu_dai = &pxa_i2s_dai,
-       .codec_dai = &wm8731_dai,
+       .cpu_dai_name = "pxa2xx-i2s",
+       .codec_dai_name = "wm8731-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm8731-codec.0-001a",
        .init = poodle_wm8731_init,
        .ops = &poodle_ops,
 };
@@ -275,15 +277,9 @@ static struct snd_soc_dai_link poodle_dai = {
 /* poodle audio machine driver */
 static struct snd_soc_card snd_soc_poodle = {
        .name = "Poodle",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = &poodle_dai,
        .num_links = 1,
-};
-
-/* poodle audio subsystem */
-static struct snd_soc_device poodle_snd_devdata = {
-       .card = &snd_soc_poodle,
-       .codec_dev = &soc_codec_dev_wm8731,
+       .owner = THIS_MODULE,
 };
 
 static struct platform_device *poodle_snd_device;
@@ -307,8 +303,7 @@ static int __init poodle_init(void)
        if (!poodle_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata);
-       poodle_snd_devdata.dev = &poodle_snd_device->dev;
+       platform_set_drvdata(poodle_snd_device, &snd_soc_poodle);
        ret = platform_device_add(poodle_snd_device);
 
        if (ret)
index a1fd23e..b439eee 100644 (file)
@@ -35,7 +35,7 @@
 #include <mach/audio.h>
 #include <plat/ssp.h>
 
-#include "pxa2xx-pcm.h"
+#include "../../arm/pxa2xx-pcm.h"
 #include "pxa-ssp.h"
 
 /*
@@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
 }
 
 static int pxa_ssp_startup(struct snd_pcm_substream *substream,
-                          struct snd_soc_dai *dai)
+                          struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        int ret = 0;
 
@@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
 }
 
 static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
-                            struct snd_soc_dai *dai)
+                            struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
 
        if (!cpu_dai->active) {
@@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
 
 static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
 
        if (!cpu_dai->active)
@@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
 
 static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
 
@@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp)
 static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        int clk_id, unsigned int freq, int dir)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        int val;
 
@@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
        int div_id, int div)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        int val;
 
@@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
 static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
        int source, unsigned int freq_in, unsigned int freq_out)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70;
 
@@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
 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)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        u32 sscr0;
 
@@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
 static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
        int tristate)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        u32 sscr1;
 
@@ -464,11 +460,9 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
 static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                unsigned int fmt)
 {
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
-       u32 sscr0;
-       u32 sscr1;
-       u32 sspsp;
+       u32 sscr0, sscr1, sspsp, scfr;
 
        /* check if we need to change anything at all */
        if (priv->dai_fmt == fmt)
@@ -483,16 +477,16 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
        /* reset port settings */
        sscr0 = pxa_ssp_read_reg(ssp, SSCR0) &
-               (SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
+               ~(SSCR0_ECS |  SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
        sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
        sspsp = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
-               sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
+               sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR;
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
-               sscr1 |= SSCR1_SCLKDIR;
+               sscr1 |= SSCR1_SCLKDIR | SSCR1_SCFR;
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
                break;
@@ -538,6 +532,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        pxa_ssp_write_reg(ssp, SSCR1, sscr1);
        pxa_ssp_write_reg(ssp, SSPSP, sspsp);
 
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+       case SND_SOC_DAIFMT_CBM_CFS:
+               scfr = pxa_ssp_read_reg(ssp, SSCR1) | SSCR1_SCFR;
+               pxa_ssp_write_reg(ssp, SSCR1, scfr);
+
+               while (pxa_ssp_read_reg(ssp, SSSR) & SSSR_BSY)
+                       cpu_relax();
+               break;
+       }
+
        dump_registers(ssp);
 
        /* Since we are configuring the timings for the format by hand
@@ -555,11 +560,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
  */
 static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai)
+                               struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        int chn = params_channels(params);
        u32 sscr0;
@@ -568,7 +571,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
        int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;
        struct pxa2xx_pcm_dma_params *dma_data;
 
-       dma_data = snd_soc_dai_get_dma_data(dai, substream);
+       dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
 
        /* generate correct DMA params */
        kfree(dma_data);
@@ -581,7 +584,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
                        ((chn == 2) && (ttsa != 1)) || (width == 32),
                        substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
-       snd_soc_dai_set_dma_data(dai, substream, dma_data);
+       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
 
        /* we can only change the settings if the port is not in use */
        if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
@@ -589,10 +592,8 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
 
        /* clear selected SSP bits */
        sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
-       pxa_ssp_write_reg(ssp, SSCR0, sscr0);
 
        /* bit size */
-       sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
 #ifdef CONFIG_PXA3xx
@@ -668,12 +669,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
 }
 
 static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
-                          struct snd_soc_dai *dai)
+                          struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        int ret = 0;
-       struct ssp_priv *priv = cpu_dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
        struct ssp_device *ssp = priv->ssp;
        int val;
 
@@ -729,8 +728,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
        return ret;
 }
 
-static int pxa_ssp_probe(struct platform_device *pdev,
-                           struct snd_soc_dai *dai)
+static int pxa_ssp_probe(struct snd_soc_dai *dai)
 {
        struct ssp_priv *priv;
        int ret;
@@ -746,7 +744,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
        }
 
        priv->dai_fmt = (unsigned int) -1;
-       dai->private_data = priv;
+       snd_soc_dai_set_drvdata(dai, priv);
 
        return 0;
 
@@ -755,11 +753,13 @@ err_priv:
        return ret;
 }
 
-static void pxa_ssp_remove(struct platform_device *pdev,
-                             struct snd_soc_dai *dai)
+static int pxa_ssp_remove(struct snd_soc_dai *dai)
 {
-       struct ssp_priv *priv = dai->private_data;
+       struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai);
+
        pxa_ssp_free(priv->ssp);
+       kfree(priv);
+       return 0;
 }
 
 #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -784,10 +784,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
        .set_tristate   = pxa_ssp_set_dai_tristate,
 };
 
-struct snd_soc_dai pxa_ssp_dai[] = {
-       {
-               .name = "pxa2xx-ssp1",
-               .id = 0,
+static struct snd_soc_dai_driver pxa_ssp_dai = {
                .probe = pxa_ssp_probe,
                .remove = pxa_ssp_remove,
                .suspend = pxa_ssp_suspend,
@@ -805,81 +802,38 @@ struct snd_soc_dai pxa_ssp_dai[] = {
                        .formats = PXA_SSP_FORMATS,
                 },
                .ops = &pxa_ssp_dai_ops,
+};
+
+static __devinit int asoc_ssp_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
+}
+
+static int __devexit asoc_ssp_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver asoc_ssp_driver = {
+       .driver = {
+                       .name = "pxa-ssp-dai",
+                       .owner = THIS_MODULE,
        },
-       {       .name = "pxa2xx-ssp2",
-               .id = 1,
-               .probe = pxa_ssp_probe,
-               .remove = pxa_ssp_remove,
-               .suspend = pxa_ssp_suspend,
-               .resume = pxa_ssp_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-               },
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-                },
-               .ops = &pxa_ssp_dai_ops,
-       },
-       {
-               .name = "pxa2xx-ssp3",
-               .id = 2,
-               .probe = pxa_ssp_probe,
-               .remove = pxa_ssp_remove,
-               .suspend = pxa_ssp_suspend,
-               .resume = pxa_ssp_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-               },
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-                },
-               .ops = &pxa_ssp_dai_ops,
-       },
-       {
-               .name = "pxa2xx-ssp4",
-               .id = 3,
-               .probe = pxa_ssp_probe,
-               .remove = pxa_ssp_remove,
-               .suspend = pxa_ssp_suspend,
-               .resume = pxa_ssp_resume,
-               .playback = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-               },
-               .capture = {
-                       .channels_min = 1,
-                       .channels_max = 8,
-                       .rates = PXA_SSP_RATES,
-                       .formats = PXA_SSP_FORMATS,
-                },
-               .ops = &pxa_ssp_dai_ops,
-       },
+
+       .probe = asoc_ssp_probe,
+       .remove = __devexit_p(asoc_ssp_remove),
 };
-EXPORT_SYMBOL_GPL(pxa_ssp_dai);
 
 static int __init pxa_ssp_init(void)
 {
-       return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+       return platform_driver_register(&asoc_ssp_driver);
 }
 module_init(pxa_ssp_init);
 
 static void __exit pxa_ssp_exit(void)
 {
-       snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
+       platform_driver_unregister(&asoc_ssp_driver);
 }
 module_exit(pxa_ssp_exit);
 
index 91deadd..bc79da2 100644 (file)
@@ -42,6 +42,4 @@
 
 #define PXA_SSP_PLL_OUT  0
 
-extern struct snd_soc_dai pxa_ssp_dai[4];
-
 #endif
index d314115..ac51c6d 100644 (file)
@@ -24,7 +24,6 @@
 #include <mach/dma.h>
 #include <mach/audio.h>
 
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -104,24 +103,21 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
 #define pxa2xx_ac97_resume     NULL
 #endif
 
-static int pxa2xx_ac97_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
 {
        return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
 }
 
-static void pxa2xx_ac97_remove(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+static int pxa2xx_ac97_remove(struct snd_soc_dai *dai)
 {
        pxa2xx_ac97_hw_remove(to_platform_device(dai->dev));
+       return 0;
 }
 
 static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
-                                struct snd_soc_dai *dai)
+                                struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct pxa2xx_pcm_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -136,10 +132,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
 
 static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
                                     struct snd_pcm_hw_params *params,
-                                    struct snd_soc_dai *dai)
+                                    struct snd_soc_dai *cpu_dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct pxa2xx_pcm_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -154,11 +148,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
 
 static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
                                     struct snd_pcm_hw_params *params,
-                                    struct snd_soc_dai *dai)
+                                    struct snd_soc_dai *cpu_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)
                return -ENODEV;
        else
@@ -188,10 +179,9 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
  * There is only 1 physical AC97 interface for pxa2xx, but it
  * has extra fifo's that can be used for aux DACs and ADCs.
  */
-struct snd_soc_dai pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai[] = {
 {
        .name = "pxa2xx-ac97",
-       .id = 0,
        .ac97_control = 1,
        .probe = pxa2xx_ac97_probe,
        .remove = pxa2xx_ac97_remove,
@@ -213,7 +203,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {
 },
 {
        .name = "pxa2xx-ac97-aux",
-       .id = 1,
        .ac97_control = 1,
        .playback = {
                .stream_name = "AC97 Aux Playback",
@@ -231,7 +220,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {
 },
 {
        .name = "pxa2xx-ac97-mic",
-       .id = 2,
        .ac97_control = 1,
        .capture = {
                .stream_name = "AC97 Mic Capture",
@@ -243,36 +231,26 @@ struct snd_soc_dai pxa_ac97_dai[] = {
 },
 };
 
-EXPORT_SYMBOL_GPL(pxa_ac97_dai);
 EXPORT_SYMBOL_GPL(soc_ac97_ops);
 
-static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev)
+static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 {
-       int i;
-       pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data;
-
-       if (pdev->id >= 0) {
+       if (pdev->id != -1) {
                dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
                return -ENXIO;
        }
 
-       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
         * and running.
         */
-       return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
+       return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
+                       ARRAY_SIZE(pxa_ac97_dai));
 }
 
 static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
-
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
        return 0;
 }
 
index e390de8..eda891e 100644 (file)
@@ -14,8 +14,6 @@
 #define PXA2XX_DAI_AC97_AUX            1
 #define PXA2XX_DAI_AC97_MIC            2
 
-extern struct snd_soc_dai pxa_ac97_dai[3];
-
 /* platform data */
 extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
 
index c1a5275..11be595 100644 (file)
@@ -27,7 +27,6 @@
 #include <mach/dma.h>
 #include <mach/audio.h>
 
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
 /*
@@ -80,6 +79,7 @@ struct pxa_i2s_port {
 };
 static struct pxa_i2s_port pxa_i2s;
 static struct clk *clk_i2s;
+static int clk_ena = 0;
 
 static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
        .name                   = "I2S PCM Stereo out",
@@ -101,7 +101,7 @@ static int pxa2xx_i2s_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 snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        if (IS_ERR(clk_i2s))
                return PTR_ERR(clk_i2s);
@@ -162,13 +162,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct pxa2xx_pcm_dma_params *dma_data;
 
        BUG_ON(IS_ERR(clk_i2s));
        clk_enable(clk_i2s);
-       dai->private_data = dai;
+       clk_ena = 1;
        pxa_i2s_wait();
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -176,7 +174,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
        else
                dma_data = &pxa2xx_i2s_pcm_stereo_in;
 
-       snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
 
        /* is port used by another stream */
        if (!(SACR0 & SACR0_ENB)) {
@@ -259,9 +257,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
        if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
                SACR0 &= ~SACR0_ENB;
                pxa_i2s_wait();
-               if (dai->private_data != NULL) {
+               if (clk_ena) {
                        clk_disable(clk_i2s);
-                       dai->private_data = NULL;
+                       clk_ena = 0;
                }
        }
 }
@@ -300,6 +298,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
 #define pxa2xx_i2s_resume      NULL
 #endif
 
+static int pxa2xx_i2s_probe(struct snd_soc_dai *dai)
+{
+       clk_i2s = clk_get(dai->dev, "I2SCLK");
+       if (IS_ERR(clk_i2s))
+               return PTR_ERR(clk_i2s);
+
+       /*
+        * PXA Developer's Manual:
+        * If SACR0[ENB] is toggled in the middle of a normal operation,
+        * the SACR0[RST] bit must also be set and cleared to reset all
+        * I2S controller registers.
+        */
+       SACR0 = SACR0_RST;
+       SACR0 = 0;
+       /* Make sure RPL and REC are disabled */
+       SACR1 = SACR1_DRPL | SACR1_DREC;
+       /* Along with FIFO servicing */
+       SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
+
+       return 0;
+}
+
+static int  pxa2xx_i2s_remove(struct snd_soc_dai *dai)
+{
+       clk_put(clk_i2s);
+       clk_i2s = ERR_PTR(-ENOENT);
+       return 0;
+}
+
 #define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
                SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
                SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
@@ -313,9 +340,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
        .set_sysclk     = pxa2xx_i2s_set_dai_sysclk,
 };
 
-struct snd_soc_dai pxa_i2s_dai = {
-       .name = "pxa2xx-i2s",
-       .id = 0,
+static struct snd_soc_dai_driver pxa_i2s_dai = {
+       .probe = pxa2xx_i2s_probe,
+       .remove = pxa2xx_i2s_remove,
        .suspend = pxa2xx_i2s_suspend,
        .resume = pxa2xx_i2s_resume,
        .playback = {
@@ -332,49 +359,20 @@ struct snd_soc_dai pxa_i2s_dai = {
        .symmetric_rates = 1,
 };
 
-EXPORT_SYMBOL_GPL(pxa_i2s_dai);
-
-static int pxa2xx_i2s_probe(struct platform_device *dev)
+static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
 {
-       int ret;
-
-       clk_i2s = clk_get(&dev->dev, "I2SCLK");
-       if (IS_ERR(clk_i2s))
-               return PTR_ERR(clk_i2s);
-
-       pxa_i2s_dai.dev = &dev->dev;
-       pxa_i2s_dai.private_data = NULL;
-       ret = snd_soc_register_dai(&pxa_i2s_dai);
-       if (ret != 0)
-               clk_put(clk_i2s);
-
-       /*
-        * PXA Developer's Manual:
-        * If SACR0[ENB] is toggled in the middle of a normal operation,
-        * the SACR0[RST] bit must also be set and cleared to reset all
-        * I2S controller registers.
-        */
-       SACR0 = SACR0_RST;
-       SACR0 = 0;
-       /* Make sure RPL and REC are disabled */
-       SACR1 = SACR1_DRPL | SACR1_DREC;
-       /* Along with FIFO servicing */
-       SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
-
-       return ret;
+       return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
 }
 
-static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
+static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&pxa_i2s_dai);
-       clk_put(clk_i2s);
-       clk_i2s = ERR_PTR(-ENOENT);
+       snd_soc_unregister_dai(&pdev->dev);
        return 0;
 }
 
 static struct platform_driver pxa2xx_i2s_driver = {
-       .probe = pxa2xx_i2s_probe,
-       .remove = __devexit_p(pxa2xx_i2s_remove),
+       .probe = pxa2xx_i2s_drv_probe,
+       .remove = __devexit_p(pxa2xx_i2s_drv_remove),
 
        .driver = {
                .name = "pxa2xx-i2s",
@@ -400,3 +398,4 @@ module_exit(pxa2xx_i2s_exit);
 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa2xx-i2s");
index e2def44..070f3c6 100644 (file)
@@ -15,6 +15,4 @@
 /* I2S clock */
 #define PXA2XX_I2S_SYSCLK              0
 
-extern struct snd_soc_dai pxa_i2s_dai;
-
 #endif
index adc7e6f..02fb664 100644 (file)
@@ -16,7 +16,6 @@
 #include <sound/soc.h>
 #include <sound/pxa2xx-lib.h>
 
-#include "pxa2xx-pcm.h"
 #include "../../arm/pxa2xx-pcm.h"
 
 static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -28,7 +27,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
        struct pxa2xx_pcm_dma_params *dma;
        int ret;
 
-       dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+       dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        /* return if this is a bufferless transfer e.g.
         * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -95,14 +94,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -112,25 +111,44 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        return ret;
 }
 
-struct snd_soc_platform pxa2xx_soc_platform = {
-       .name           = "pxa2xx-audio",
-       .pcm_ops        = &pxa2xx_pcm_ops,
+static struct snd_soc_platform_driver pxa2xx_soc_platform = {
+       .ops    = &pxa2xx_pcm_ops,
        .pcm_new        = pxa2xx_soc_pcm_new,
        .pcm_free       = pxa2xx_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
 
-static int __init pxa2xx_soc_platform_init(void)
+static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&pxa2xx_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
 }
-module_init(pxa2xx_soc_platform_init);
 
-static void __exit pxa2xx_soc_platform_exit(void)
+static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&pxa2xx_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver pxa_pcm_driver = {
+       .driver = {
+                       .name = "pxa-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = pxa2xx_soc_platform_probe,
+       .remove = __devexit_p(pxa2xx_soc_platform_remove),
+};
+
+static int __init snd_pxa_pcm_init(void)
+{
+       return platform_driver_register(&pxa_pcm_driver);
+}
+module_init(snd_pxa_pcm_init);
+
+static void __exit snd_pxa_pcm_exit(void)
+{
+       platform_driver_unregister(&pxa_pcm_driver);
 }
-module_exit(pxa2xx_soc_platform_exit);
+module_exit(snd_pxa_pcm_exit);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
deleted file mode 100644 (file)
index 60c3b20..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
- *
- * Author:     Nicolas Pitre
- * Created:    Nov 30, 2004
- * Copyright:  MontaVista Software, 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 _PXA2XX_PCM_H
-#define _PXA2XX_PCM_H
-
-/* platform data */
-extern struct snd_soc_platform pxa2xx_soc_platform;
-
-#endif
index 7e3f416..2cda82b 100644 (file)
@@ -26,9 +26,6 @@
 
 #include <asm/mach-types.h>
 
-#include "../codecs/cs4270.h"
-#include "../codecs/ak4104.h"
-#include "pxa2xx-pcm.h"
 #include "pxa-ssp.h"
 
 #define GPIO_SPDIF_RESET       (38)
@@ -71,7 +68,7 @@ static void raumfeld_enable_audio(bool en)
 static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        /* set freq to 0 to enable all possible codec sample rates */
        return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
@@ -80,7 +77,7 @@ static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
 static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        /* set freq to 0 to enable all possible codec sample rates */
        snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
@@ -90,8 +87,8 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream,
                                     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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int fmt, clk = 0;
        int ret = 0;
 
@@ -167,32 +164,14 @@ static int raumfeld_line_resume(struct platform_device *pdev)
        return 0;
 }
 
-static struct snd_soc_dai_link raumfeld_line_dai = {
-       .name           = "CS4270",
-       .stream_name    = "CS4270",
-       .cpu_dai        = &pxa_ssp_dai[PXA_DAI_SSP1],
-       .codec_dai      = &cs4270_dai,
-       .ops            = &raumfeld_cs4270_ops,
-};
-
-static struct snd_soc_card snd_soc_line_raumfeld = {
-       .name           = "Raumfeld analog",
-       .platform       = &pxa2xx_soc_platform,
-       .dai_link       = &raumfeld_line_dai,
-       .suspend_post   = raumfeld_line_suspend,
-       .resume_pre     = raumfeld_line_resume,
-       .num_links      = 1,
-};
-
-
 /* AK4104 */
 
 static int raumfeld_ak4104_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int fmt, ret = 0, clk = 0;
 
        switch (params_rate(params)) {
@@ -247,34 +226,35 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
        .hw_params = raumfeld_ak4104_hw_params,
 };
 
-static struct snd_soc_dai_link raumfeld_spdif_dai = {
+static struct snd_soc_dai_link raumfeld_dai[] = {
+{
        .name           = "ak4104",
        .stream_name    = "Playback",
-       .cpu_dai        = &pxa_ssp_dai[PXA_DAI_SSP2],
-       .codec_dai      = &ak4104_dai,
+       .cpu_dai_name = "pxa-ssp-dai.1",
+       .codec_dai_name = "ak4104-hifi",
+       .platform_name = "pxa-pcm-audio",
        .ops            = &raumfeld_ak4104_ops,
-};
-
-static struct snd_soc_card snd_soc_spdif_raumfeld = {
-       .name           = "Raumfeld S/PDIF",
-       .platform       = &pxa2xx_soc_platform,
-       .dai_link       = &raumfeld_spdif_dai,
-       .num_links      = 1
-};
-
-/* raumfeld_audio audio subsystem */
-static struct snd_soc_device raumfeld_line_devdata = {
-       .card = &snd_soc_line_raumfeld,
-       .codec_dev = &soc_codec_device_cs4270,
-};
+       .codec_name = "ak4104-codec.0",
+},
+{
+       .name           = "CS4270",
+       .stream_name    = "CS4270",
+       .cpu_dai_name = "pxa-ssp-dai.0",
+       .platform_name = "pxa-pcm-audio",
+       .codec_dai_name = "cs4270-hifi",
+       .codec_name = "cs4270-codec.0-0048",
+       .ops            = &raumfeld_cs4270_ops,
+},};
 
-static struct snd_soc_device raumfeld_spdif_devdata = {
-       .card = &snd_soc_spdif_raumfeld,
-       .codec_dev = &soc_codec_device_ak4104,
+static struct snd_soc_card snd_soc_raumfeld = {
+       .name           = "Raumfeld",
+       .dai_link       = raumfeld_dai,
+       .suspend_post   = raumfeld_line_suspend,
+       .resume_pre     = raumfeld_line_resume,
+       .num_links      = ARRAY_SIZE(raumfeld_dai),
 };
 
-static struct platform_device *raumfeld_audio_line_device;
-static struct platform_device *raumfeld_audio_spdif_device;
+static struct platform_device *raumfeld_audio_device;
 
 static int __init raumfeld_audio_init(void)
 {
@@ -292,38 +272,19 @@ static int __init raumfeld_audio_init(void)
 
        set_max9485_clk(MAX9485_MCLK_FREQ_122880);
 
-       /* LINE */
-       raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0);
-       if (!raumfeld_audio_line_device)
+       /* Register LINE and SPDIF */
+       raumfeld_audio_device = platform_device_alloc("soc-audio", 0);
+       if (!raumfeld_audio_device)
                return -ENOMEM;
 
-       platform_set_drvdata(raumfeld_audio_line_device,
-                            &raumfeld_line_devdata);
-       raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev;
-       ret = platform_device_add(raumfeld_audio_line_device);
-       if (ret)
-               platform_device_put(raumfeld_audio_line_device);
+       platform_set_drvdata(raumfeld_audio_device,
+                            &snd_soc_raumfeld);
+       ret = platform_device_add(raumfeld_audio_device);
 
        /* no S/PDIF on Speakers */
        if (machine_is_raumfeld_speaker())
                return ret;
 
-       /* S/PDIF */
-       raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1);
-       if (!raumfeld_audio_spdif_device) {
-               platform_device_put(raumfeld_audio_line_device);
-               return -ENOMEM;
-       }
-
-       platform_set_drvdata(raumfeld_audio_spdif_device,
-                            &raumfeld_spdif_devdata);
-       raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev;
-       ret = platform_device_add(raumfeld_audio_spdif_device);
-       if (ret) {
-               platform_device_put(raumfeld_audio_line_device);
-               platform_device_put(raumfeld_audio_spdif_device);
-       }
-
        raumfeld_enable_audio(true);
 
        return ret;
@@ -333,10 +294,7 @@ static void __exit raumfeld_audio_exit(void)
 {
        raumfeld_enable_audio(false);
 
-       platform_device_unregister(raumfeld_audio_line_device);
-
-       if (machine_is_raumfeld_connector())
-               platform_device_unregister(raumfeld_audio_spdif_device);
+       platform_device_unregister(raumfeld_audio_device);
 
        i2c_unregister_device(max9486_client);
 
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
new file mode 100644 (file)
index 0000000..d63cb47
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * saarb.c -- SoC audio for saarb
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ *     Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/88pm860x-codec.h"
+#include "pxa-ssp.h"
+
+static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
+
+static struct platform_device *saarb_snd_device;
+
+static struct snd_soc_jack hs_jack, mic_jack;
+
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+       { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
+};
+
+static struct snd_soc_jack_pin mic_jack_pins[] = {
+       { .pin = "Headset Mic 2",       .mask = SND_JACK_MICROPHONE, },
+};
+
+/* saarb machine dapm widgets */
+static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Stereophone", NULL),
+       SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
+       SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
+       SND_SOC_DAPM_SPK("Ext Speaker", NULL),
+       SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
+};
+
+/* saarb machine audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+       {"Headset Stereophone", NULL, "HS1"},
+       {"Headset Stereophone", NULL, "HS2"},
+
+       {"Ext Speaker", NULL, "LSP"},
+       {"Ext Speaker", NULL, "LSN"},
+
+       {"Lineout Out 1", NULL, "LINEOUT1"},
+       {"Lineout Out 2", NULL, "LINEOUT2"},
+
+       {"MIC1P", NULL, "Mic1 Bias"},
+       {"MIC1N", NULL, "Mic1 Bias"},
+       {"Mic1 Bias", NULL, "Ext Mic 1"},
+
+       {"MIC2P", NULL, "Mic1 Bias"},
+       {"MIC2N", NULL, "Mic1 Bias"},
+       {"Mic1 Bias", NULL, "Headset Mic 2"},
+
+       {"MIC3P", NULL, "Mic3 Bias"},
+       {"MIC3N", NULL, "Mic3 Bias"},
+       {"Mic3 Bias", NULL, "Ext Mic 3"},
+};
+
+static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       int width = snd_pcm_format_physical_width(params_format(params));
+       int ret;
+
+       ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
+                                    PM860X_CLK_DIR_OUT);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
+       if (ret < 0)
+               return ret;
+
+       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;
+       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;
+
+       ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
+
+       return ret;
+}
+
+static struct snd_soc_ops saarb_i2s_ops = {
+       .hw_params      = saarb_i2s_hw_params,
+};
+
+static struct snd_soc_dai_link saarb_dai[] = {
+       {
+               .name           = "88PM860x I2S",
+               .stream_name    = "I2S Audio",
+               .cpu_dai_name   = "pxa-ssp-dai.1",
+               .codec_dai_name = "88pm860x-i2s",
+               .platform_name  = "pxa-pcm-audio",
+               .codec_name     = "88pm860x-codec",
+               .init           = saarb_pm860x_init,
+               .ops            = &saarb_i2s_ops,
+       },
+};
+
+static struct snd_soc_card snd_soc_card_saarb = {
+       .name = "Saarb",
+       .dai_link = saarb_dai,
+       .num_links = ARRAY_SIZE(saarb_dai),
+};
+
+static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int ret;
+
+       snd_soc_dapm_new_controls(codec, saarb_dapm_widgets,
+                                 ARRAY_SIZE(saarb_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       /* connected pins */
+       snd_soc_dapm_enable_pin(codec, "Ext Speaker");
+       snd_soc_dapm_enable_pin(codec, "Ext Mic 1");
+       snd_soc_dapm_enable_pin(codec, "Ext Mic 3");
+       snd_soc_dapm_disable_pin(codec, "Headset Mic 2");
+       snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
+
+       ret = snd_soc_dapm_sync(codec);
+       if (ret)
+               return ret;
+
+       /* Headset jack detection */
+       snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
+                       | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
+                       &hs_jack);
+       snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+                             hs_jack_pins);
+       snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
+                        &mic_jack);
+       snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
+                             mic_jack_pins);
+
+       /* headphone, microphone detection & headset short detection */
+       pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
+                             SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
+       pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
+       return 0;
+}
+
+static int __init saarb_init(void)
+{
+       int ret;
+
+       if (!machine_is_saarb())
+               return -ENODEV;
+       saarb_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!saarb_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
+
+       ret = platform_device_add(saarb_snd_device);
+       if (ret)
+               platform_device_put(saarb_snd_device);
+
+       return ret;
+}
+
+static void __exit saarb_exit(void)
+{
+       platform_device_unregister(saarb_snd_device);
+}
+
+module_init(saarb_init);
+module_exit(saarb_exit);
+
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
+MODULE_LICENSE("GPL");
index d256f5f..f470f36 100644 (file)
@@ -28,7 +28,6 @@
 #include <asm/mach-types.h>
 #include <mach/spitz.h>
 #include "../codecs/wm8750.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
 #define SPITZ_HP        0
@@ -107,7 +106,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
 static int spitz_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->codec;
 
        /* check the jack status at stream startup */
        spitz_ext_control(codec);
@@ -118,8 +117,8 @@ static int spitz_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -274,8 +273,9 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
 /*
  * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
  */
-static int spitz_wm8750_init(struct snd_soc_codec *codec)
+static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* NC codec pins */
@@ -308,8 +308,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link spitz_dai = {
        .name = "wm8750",
        .stream_name = "WM8750",
-       .cpu_dai = &pxa_i2s_dai,
-       .codec_dai = &wm8750_dai,
+       .cpu_dai_name = "pxa-is2",
+       .codec_dai_name = "wm8750-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm8750-codec.0-001a",
        .init = spitz_wm8750_init,
        .ops = &spitz_ops,
 };
@@ -317,17 +319,10 @@ static struct snd_soc_dai_link spitz_dai = {
 /* spitz audio machine driver */
 static struct snd_soc_card snd_soc_spitz = {
        .name = "Spitz",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = &spitz_dai,
        .num_links = 1,
 };
 
-/* spitz audio subsystem */
-static struct snd_soc_device spitz_snd_devdata = {
-       .card = &snd_soc_spitz,
-       .codec_dev = &soc_codec_dev_wm8750,
-};
-
 static struct platform_device *spitz_snd_device;
 
 static int __init spitz_init(void)
@@ -341,8 +336,7 @@ static int __init spitz_init(void)
        if (!spitz_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata);
-       spitz_snd_devdata.dev = &spitz_snd_device->dev;
+       platform_set_drvdata(spitz_snd_device, &snd_soc_spitz);
        ret = platform_device_add(spitz_snd_device);
 
        if (ret)
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
new file mode 100644 (file)
index 0000000..248c283
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * tavorevb3.c -- SoC audio for Tavor EVB3
+ *
+ * Copyright (C) 2010 Marvell International Ltd.
+ *     Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include "../codecs/88pm860x-codec.h"
+#include "pxa-ssp.h"
+
+static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd);
+
+static struct platform_device *evb3_snd_device;
+
+static struct snd_soc_jack hs_jack, mic_jack;
+
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+       { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
+};
+
+static struct snd_soc_jack_pin mic_jack_pins[] = {
+       { .pin = "Headset Mic 2",       .mask = SND_JACK_MICROPHONE, },
+};
+
+/* tavorevb3 machine dapm widgets */
+static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+       SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
+       SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
+       SND_SOC_DAPM_SPK("Ext Speaker", NULL),
+       SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
+       SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
+};
+
+/* tavorevb3 machine audio map */
+static const struct snd_soc_dapm_route audio_map[] = {
+       {"Headset Stereophone", NULL, "HS1"},
+       {"Headset Stereophone", NULL, "HS2"},
+
+       {"Ext Speaker", NULL, "LSP"},
+       {"Ext Speaker", NULL, "LSN"},
+
+       {"Lineout Out 1", NULL, "LINEOUT1"},
+       {"Lineout Out 2", NULL, "LINEOUT2"},
+
+       {"MIC1P", NULL, "Mic1 Bias"},
+       {"MIC1N", NULL, "Mic1 Bias"},
+       {"Mic1 Bias", NULL, "Ext Mic 1"},
+
+       {"MIC2P", NULL, "Mic1 Bias"},
+       {"MIC2N", NULL, "Mic1 Bias"},
+       {"Mic1 Bias", NULL, "Headset Mic 2"},
+
+       {"MIC3P", NULL, "Mic3 Bias"},
+       {"MIC3N", NULL, "Mic3 Bias"},
+       {"Mic3 Bias", NULL, "Ext Mic 3"},
+};
+
+static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       int width = snd_pcm_format_physical_width(params_format(params));
+       int ret;
+
+       ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
+                                    PM860X_CLK_DIR_OUT);
+       if (ret < 0)
+               return ret;
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
+       if (ret < 0)
+               return ret;
+
+       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;
+
+       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;
+
+       ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
+       return ret;
+}
+
+static struct snd_soc_ops evb3_i2s_ops = {
+       .hw_params      = evb3_i2s_hw_params,
+};
+
+static struct snd_soc_dai_link evb3_dai[] = {
+       {
+               .name           = "88PM860x I2S",
+               .stream_name    = "I2S Audio",
+               .cpu_dai_name   = "pxa-ssp-dai.1",
+               .codec_dai_name = "88pm860x-i2s",
+               .platform_name  = "pxa-pcm-audio",
+               .codec_name     = "88pm860x-codec",
+               .init           = evb3_pm860x_init,
+               .ops            = &evb3_i2s_ops,
+       },
+};
+
+static struct snd_soc_card snd_soc_card_evb3 = {
+       .name = "Tavor EVB3",
+       .dai_link = evb3_dai,
+       .num_links = ARRAY_SIZE(evb3_dai),
+};
+
+static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int ret;
+
+       snd_soc_dapm_new_controls(codec, evb3_dapm_widgets,
+                                 ARRAY_SIZE(evb3_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       /* connected pins */
+       snd_soc_dapm_enable_pin(codec, "Ext Speaker");
+       snd_soc_dapm_enable_pin(codec, "Ext Mic 1");
+       snd_soc_dapm_enable_pin(codec, "Ext Mic 3");
+       snd_soc_dapm_disable_pin(codec, "Headset Mic 2");
+       snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
+
+       ret = snd_soc_dapm_sync(codec);
+       if (ret)
+               return ret;
+
+       /* Headset jack detection */
+       snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
+                       | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
+                       &hs_jack);
+       snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+                             hs_jack_pins);
+       snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
+                        &mic_jack);
+       snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
+                             mic_jack_pins);
+
+       /* headphone, microphone detection & headset short detection */
+       pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
+                             SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
+       pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
+       return 0;
+}
+
+static int __init tavorevb3_init(void)
+{
+       int ret;
+
+       if (!machine_is_tavorevb3())
+               return -ENODEV;
+       evb3_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!evb3_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3);
+
+       ret = platform_device_add(evb3_snd_device);
+       if (ret)
+               platform_device_put(evb3_snd_device);
+
+       return ret;
+}
+
+static void __exit tavorevb3_exit(void)
+{
+       platform_device_unregister(evb3_snd_device);
+}
+
+module_init(tavorevb3_init);
+module_exit(tavorevb3_exit);
+
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3");
+MODULE_LICENSE("GPL");
index dbbd3e9..a3bfb2e 100644 (file)
@@ -33,7 +33,6 @@
 #include <mach/audio.h>
 
 #include "../codecs/wm9712.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
 static struct snd_soc_card tosa;
@@ -80,7 +79,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec)
 static int tosa_startup(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
+       struct snd_soc_codec *codec = rtd->card->codec;
 
        /* check the jack status at stream startup */
        tosa_ext_control(codec);
@@ -184,8 +183,9 @@ static const struct snd_kcontrol_new tosa_controls[] = {
                tosa_set_spk),
 };
 
-static int tosa_ac97_init(struct snd_soc_codec *codec)
+static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        snd_soc_dapm_nc_pin(codec, "OUT3");
@@ -212,16 +212,20 @@ static struct snd_soc_dai_link tosa_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-       .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
+       .cpu_dai_name = "pxa-ac97.0",
+       .codec_dai_name = "wm9712-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm9712-codec",
        .init = tosa_ac97_init,
        .ops = &tosa_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],
+       .cpu_dai_name = "pxa-ac97.1",
+       .codec_dai_name = "wm9712-aux",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name = "wm9712-codec",
        .ops = &tosa_ops,
 },
 };
@@ -248,18 +252,12 @@ static int tosa_remove(struct platform_device *dev)
 
 static struct snd_soc_card tosa = {
        .name = "Tosa",
-       .platform = &pxa2xx_soc_platform,
        .dai_link = tosa_dai,
        .num_links = ARRAY_SIZE(tosa_dai),
        .probe = tosa_probe,
        .remove = tosa_remove,
 };
 
-static struct snd_soc_device tosa_snd_devdata = {
-       .card = &tosa,
-       .codec_dev = &soc_codec_dev_wm9712,
-};
-
 static struct platform_device *tosa_snd_device;
 
 static int __init tosa_init(void)
@@ -275,8 +273,7 @@ static int __init tosa_init(void)
                goto err_alloc;
        }
 
-       platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
-       tosa_snd_devdata.dev = &tosa_snd_device->dev;
+       platform_set_drvdata(tosa_snd_device, &tosa);
        ret = platform_device_add(tosa_snd_device);
 
        if (!ret)
index 4e4d2fa..4cc841b 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/z2.h>
 
 #include "../codecs/wm8750.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-i2s.h"
 
 static struct snd_soc_card snd_soc_z2;
@@ -39,8 +38,8 @@ static int z2_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
 
@@ -138,8 +137,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
 /*
  * Logic for a wm8750 as connected on a Z2 Device
  */
-static int z2_wm8750_init(struct snd_soc_codec *codec)
+static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int ret;
 
        /* NC codec pins */
@@ -160,7 +160,7 @@ static int z2_wm8750_init(struct snd_soc_codec *codec)
                goto err;
 
        /* Jack detection API stuff */
-       ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET,
+       ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
                                &hs_jack);
        if (ret)
                goto err;
@@ -189,8 +189,10 @@ static struct snd_soc_ops z2_ops = {
 static struct snd_soc_dai_link z2_dai = {
        .name           = "wm8750",
        .stream_name    = "WM8750",
-       .cpu_dai        = &pxa_i2s_dai,
-       .codec_dai      = &wm8750_dai,
+       .cpu_dai_name   = "pxa2xx-i2s",
+       .codec_dai_name = "wm8750-hifi",
+       .platform_name = "pxa-pcm-audio",
+       .codec_name     = "wm8750-codec.0-001a",
        .init           = z2_wm8750_init,
        .ops            = &z2_ops,
 };
@@ -198,17 +200,10 @@ static struct snd_soc_dai_link z2_dai = {
 /* z2 audio machine driver */
 static struct snd_soc_card snd_soc_z2 = {
        .name           = "Z2",
-       .platform       = &pxa2xx_soc_platform,
        .dai_link       = &z2_dai,
        .num_links      = 1,
 };
 
-/* z2 audio subsystem */
-static struct snd_soc_device z2_snd_devdata = {
-       .card           = &snd_soc_z2,
-       .codec_dev      = &soc_codec_dev_wm8750,
-};
-
 static struct platform_device *z2_snd_device;
 
 static int __init z2_init(void)
@@ -222,8 +217,7 @@ static int __init z2_init(void)
        if (!z2_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(z2_snd_device, &z2_snd_devdata);
-       z2_snd_devdata.dev = &z2_snd_device->dev;
+       platform_set_drvdata(z2_snd_device, &snd_soc_z2);
        ret = platform_device_add(z2_snd_device);
 
        if (ret)
index dd678ae..d27e05a 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/soc-dapm.h>
 
 #include "../codecs/wm9713.h"
-#include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 #include "pxa-ssp.h"
 
@@ -71,10 +70,12 @@ static const struct snd_soc_dapm_route audio_map[] = {
        { "Multiactor", NULL, "SPKR" },
 };
 
-static int zylonite_wm9713_init(struct snd_soc_codec *codec)
+static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        if (clk_pout)
-               snd_soc_dai_set_pll(&codec->dai[0], 0, 0,
+               snd_soc_dai_set_pll(rtd->codec_dai, 0, 0,
                                    clk_get_rate(pout), 0);
 
        snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
@@ -94,8 +95,8 @@ static int zylonite_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;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int pll_out = 0;
        unsigned int wm9713_div = 0;
        int ret = 0;
@@ -163,21 +164,27 @@ static struct snd_soc_dai_link zylonite_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
-       .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+       .codec_name = "wm9713-codec",
+       .platform_name = "pxa-pcm-audio",
+       .cpu_dai_name = "pxa-ac97.0",
+       .codec_name = "wm9713-hifi",
        .init = zylonite_wm9713_init,
 },
 {
        .name = "AC97 Aux",
        .stream_name = "AC97 Aux",
-       .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
-       .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
+       .codec_name = "wm9713-codec",
+       .platform_name = "pxa-pcm-audio",
+       .cpu_dai_name = "pxa-ac97.1",
+       .codec_name = "wm9713-aux",
 },
 {
        .name = "WM9713 Voice",
        .stream_name = "WM9713 Voice",
-       .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3],
-       .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
+       .codec_name = "wm9713-codec",
+       .platform_name = "pxa-pcm-audio",
+       .cpu_dai_name = "pxa-ssp-dai.2",
+       .codec_name = "wm9713-voice",
        .ops = &zylonite_voice_ops,
 },
 };
@@ -248,14 +255,9 @@ static struct snd_soc_card zylonite = {
        .remove = &zylonite_remove,
        .suspend_post = &zylonite_suspend_post,
        .resume_pre = &zylonite_resume_pre,
-       .platform = &pxa2xx_soc_platform,
        .dai_link = zylonite_dai,
        .num_links = ARRAY_SIZE(zylonite_dai),
-};
-
-static struct snd_soc_device zylonite_snd_ac97_devdata = {
-       .card = &zylonite,
-       .codec_dev = &soc_codec_dev_wm9713,
+       .owner = THIS_MODULE,
 };
 
 static struct platform_device *zylonite_snd_ac97_device;
@@ -268,9 +270,7 @@ static int __init zylonite_init(void)
        if (!zylonite_snd_ac97_device)
                return -ENOMEM;
 
-       platform_set_drvdata(zylonite_snd_ac97_device,
-                            &zylonite_snd_ac97_devdata);
-       zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
+       platform_set_drvdata(zylonite_snd_ac97_device, &zylonite);
 
        ret = platform_device_add(zylonite_snd_ac97_device);
        if (ret != 0)
index 213963a..8a6b53c 100644 (file)
@@ -36,6 +36,10 @@ config SND_S3C_SOC_AC97
        tristate
        select SND_SOC_AC97_BUS
 
+config SND_S5P_SOC_SPDIF
+       tristate
+       select SND_SOC_SPDIF
+
 config SND_S3C24XX_SOC_NEO1973_WM8753
        tristate "SoC I2S Audio support for NEO1973 - WM8753"
        depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01
@@ -118,6 +122,14 @@ config SND_S3C24XX_SOC_SIMTEC_HERMES
        select SND_SOC_TLV320AIC3X
        select SND_S3C24XX_SOC_SIMTEC
 
+config SND_S3C24XX_SOC_RX1950_UDA1380
+       tristate "Audio support for the HP iPAQ RX1950"
+       depends on SND_S3C24XX_SOC && MACH_RX1950
+       select SND_S3C24XX_SOC_I2S
+       select SND_SOC_UDA1380
+       help
+         This driver provides audio support for HP iPAQ RX1950 PDA.
+
 config SND_SOC_SMDK_WM9713
        tristate "SoC AC97 Audio support for SMDK with WM9713"
        depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
@@ -131,3 +143,28 @@ config SND_S3C64XX_SOC_SMARTQ
        depends on SND_S3C24XX_SOC && MACH_SMARTQ
        select SND_S3C64XX_SOC_I2S
        select SND_SOC_WM8750
+
+config SND_S5PC110_SOC_AQUILA_WM8994
+       tristate "SoC I2S Audio support for AQUILA - WM8994"
+       depends on SND_S3C24XX_SOC && MACH_AQUILA
+       select SND_S3C64XX_SOC_I2S_V4
+       select SND_SOC_WM8994
+       help
+         Say Y if you want to add support for SoC audio on aquila
+         with the WM8994.
+
+config SND_S5PV210_SOC_GONI_WM8994
+       tristate "SoC I2S Audio support for GONI - WM8994"
+       depends on SND_S3C24XX_SOC && MACH_GONI
+       select SND_S3C64XX_SOC_I2S_V4
+       select SND_SOC_WM8994
+       help
+         Say Y if you want to add support for SoC audio on goni
+         with the WM8994.
+
+config SND_SOC_SMDK_SPDIF
+       tristate "SoC S/PDIF Audio support for SMDK"
+       depends on SND_S3C24XX_SOC && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210)
+       select SND_S5P_SOC_SPDIF
+       help
+         Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
index 50172c3..ee8f41d 100644 (file)
@@ -7,6 +7,7 @@ snd-soc-s3c-ac97-objs := s3c-ac97.o
 snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o
 snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
 snd-soc-s3c-pcm-objs := s3c-pcm.o
+snd-soc-samsung-spdif-objs := spdif.o
 
 obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
 obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
 obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o
 obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
 obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o
+obj-$(CONFIG_SND_S5P_SOC_SPDIF) += snd-soc-samsung-spdif.o
 
 # S3C24XX Machine Support
 snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -27,9 +29,13 @@ 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
+snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o
 snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
 snd-soc-smdk-wm9713-objs := smdk_wm9713.o
 snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
+snd-soc-aquila-wm8994-objs := aquila_wm8994.o
+snd-soc-goni-wm8994-objs := goni_wm8994.o
+snd-soc-smdk-spdif-objs := smdk_spdif.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
@@ -40,6 +46,10 @@ 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
+obj-$(CONFIG_SND_S3C24XX_SOC_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o
 obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
 obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o
 obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
+obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o
+obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o
+obj-$(CONFIG_SND_SOC_SMDK_SPDIF) += snd-soc-smdk-spdif.o
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c
new file mode 100644 (file)
index 0000000..235d197
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * aquila_wm8994.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Chanwoo Choi <cw00.choi@samsung.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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/gpio.h>
+#include <mach/regs-clock.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/registers.h>
+#include "../codecs/wm8994.h"
+#include "s3c-dma.h"
+#include "s3c64xx-i2s.h"
+
+static struct snd_soc_card aquila;
+static struct platform_device *aquila_snd_device;
+
+/* 3.5 pie jack */
+static struct snd_soc_jack jack;
+
+/* 3.5 pie jack detection DAPM pins */
+static struct snd_soc_jack_pin jack_pins[] = {
+       {
+               .pin = "Headset Mic",
+               .mask = SND_JACK_MICROPHONE,
+       }, {
+               .pin = "Headset Stereophone",
+               .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
+                       SND_JACK_AVOUT,
+       },
+};
+
+/* 3.5 pie jack detection gpios */
+static struct snd_soc_jack_gpio jack_gpios[] = {
+       {
+               .gpio = S5PV210_GPH0(6),
+               .name = "DET_3.5",
+               .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+                       SND_JACK_AVOUT,
+               .debounce_time = 200,
+       },
+};
+
+static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = {
+       SND_SOC_DAPM_SPK("Ext Spk", NULL),
+       SND_SOC_DAPM_SPK("Ext Rcv", NULL),
+       SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_MIC("Main Mic", NULL),
+       SND_SOC_DAPM_MIC("2nd Mic", NULL),
+       SND_SOC_DAPM_LINE("Radio In", NULL),
+};
+
+static const struct snd_soc_dapm_route aquila_dapm_routes[] = {
+       {"Ext Spk", NULL, "SPKOUTLP"},
+       {"Ext Spk", NULL, "SPKOUTLN"},
+
+       {"Ext Rcv", NULL, "HPOUT2N"},
+       {"Ext Rcv", NULL, "HPOUT2P"},
+
+       {"Headset Stereophone", NULL, "HPOUT1L"},
+       {"Headset Stereophone", NULL, "HPOUT1R"},
+
+       {"IN1RN", NULL, "Headset Mic"},
+       {"IN1RP", NULL, "Headset Mic"},
+
+       {"IN1RN", NULL, "2nd Mic"},
+       {"IN1RP", NULL, "2nd Mic"},
+
+       {"IN1LN", NULL, "Main Mic"},
+       {"IN1LP", NULL, "Main Mic"},
+
+       {"IN2LN", NULL, "Radio In"},
+       {"IN2RN", NULL, "Radio In"},
+};
+
+static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int ret;
+
+       /* add aquila specific widgets */
+       snd_soc_dapm_new_controls(codec, aquila_dapm_widgets,
+                       ARRAY_SIZE(aquila_dapm_widgets));
+
+       /* set up aquila specific audio routes */
+       snd_soc_dapm_add_routes(codec, aquila_dapm_routes,
+                       ARRAY_SIZE(aquila_dapm_routes));
+
+       /* set endpoints to not connected */
+       snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
+       snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
+       snd_soc_dapm_nc_pin(codec, "SPKOUTRN");
+       snd_soc_dapm_nc_pin(codec, "SPKOUTRP");
+
+       snd_soc_dapm_sync(codec);
+
+       /* Headset jack detection */
+       ret = snd_soc_jack_new(&aquila, "Headset Jack",
+                       SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
+                       &jack);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int aquila_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->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int pll_out = 24000000;
+       int ret = 0;
+
+       /* set the 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 cpu system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
+                       0, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return 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)
+               return ret;
+
+       /* set the codec FLL */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
+                       params_rate(params) * 256);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
+                       params_rate(params) * 256, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops aquila_hifi_ops = {
+       .hw_params = aquila_hifi_hw_params,
+};
+
+static int aquila_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->codec_dai;
+       unsigned int pll_out = 24000000;
+       int ret = 0;
+
+       if (params_rate(params) != 8000)
+               return -EINVAL;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
+                       SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec FLL */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
+                       params_rate(params) * 256);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
+                       params_rate(params) * 256, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver voice_dai = {
+       .name = "aquila-voice-dai",
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+};
+
+static struct snd_soc_ops aquila_voice_ops = {
+       .hw_params = aquila_voice_hw_params,
+};
+
+static struct snd_soc_dai_link aquila_dai[] = {
+{
+       .name = "WM8994",
+       .stream_name = "WM8994 HiFi",
+       .cpu_dai_name = "s3c64xx-i2s-v4",
+       .codec_dai_name = "wm8994-hifi",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8994-codec.0-0x1a",
+       .init = aquila_wm8994_init,
+       .ops = &aquila_hifi_ops,
+}, {
+       .name = "WM8994 Voice",
+       .stream_name = "Voice",
+       .cpu_dai_name = "aquila-voice-dai",
+       .codec_dai_name = "wm8994-voice",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8994-codec.0-0x1a",
+       .ops = &aquila_voice_ops,
+},
+};
+
+static struct snd_soc_card aquila = {
+       .name = "aquila",
+       .dai_link = aquila_dai,
+       .num_links = ARRAY_SIZE(aquila_dai),
+};
+
+static int __init aquila_init(void)
+{
+       int ret;
+
+       if (!machine_is_aquila())
+               return -ENODEV;
+
+       aquila_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!aquila_snd_device)
+               return -ENOMEM;
+
+       /* register voice DAI here */
+       ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai);
+       if (ret)
+               return ret;
+
+       platform_set_drvdata(aquila_snd_device, &aquila);
+       ret = platform_device_add(aquila_snd_device);
+
+       if (ret)
+               platform_device_put(aquila_snd_device);
+
+       return ret;
+}
+
+static void __exit aquila_exit(void)
+{
+       platform_device_unregister(aquila_snd_device);
+}
+
+module_init(aquila_init);
+module_exit(aquila_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c
new file mode 100644 (file)
index 0000000..694f702
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * goni_wm8994.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Chanwoo Choi <cw00.choi@samsung.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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/gpio.h>
+#include <mach/regs-clock.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/registers.h>
+#include "../codecs/wm8994.h"
+#include "s3c-dma.h"
+#include "s3c64xx-i2s.h"
+
+static struct snd_soc_card goni;
+static struct platform_device *goni_snd_device;
+
+/* 3.5 pie jack */
+static struct snd_soc_jack jack;
+
+/* 3.5 pie jack detection DAPM pins */
+static struct snd_soc_jack_pin jack_pins[] = {
+       {
+               .pin = "Headset Mic",
+               .mask = SND_JACK_MICROPHONE,
+       }, {
+               .pin = "Headset Stereophone",
+               .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
+                       SND_JACK_AVOUT,
+       },
+};
+
+/* 3.5 pie jack detection gpios */
+static struct snd_soc_jack_gpio jack_gpios[] = {
+       {
+               .gpio = S5PV210_GPH0(6),
+               .name = "DET_3.5",
+               .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+                       SND_JACK_AVOUT,
+               .debounce_time = 200,
+       },
+};
+
+static const struct snd_soc_dapm_widget goni_dapm_widgets[] = {
+       SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
+       SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
+       SND_SOC_DAPM_SPK("Ext Rcv", NULL),
+       SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_MIC("Main Mic", NULL),
+       SND_SOC_DAPM_MIC("2nd Mic", NULL),
+       SND_SOC_DAPM_LINE("Radio In", NULL),
+};
+
+static const struct snd_soc_dapm_route goni_dapm_routes[] = {
+       {"Ext Left Spk", NULL, "SPKOUTLP"},
+       {"Ext Left Spk", NULL, "SPKOUTLN"},
+
+       {"Ext Right Spk", NULL, "SPKOUTRP"},
+       {"Ext Right Spk", NULL, "SPKOUTRN"},
+
+       {"Ext Rcv", NULL, "HPOUT2N"},
+       {"Ext Rcv", NULL, "HPOUT2P"},
+
+       {"Headset Stereophone", NULL, "HPOUT1L"},
+       {"Headset Stereophone", NULL, "HPOUT1R"},
+
+       {"IN1RN", NULL, "Headset Mic"},
+       {"IN1RP", NULL, "Headset Mic"},
+
+       {"IN1RN", NULL, "2nd Mic"},
+       {"IN1RP", NULL, "2nd Mic"},
+
+       {"IN1LN", NULL, "Main Mic"},
+       {"IN1LP", NULL, "Main Mic"},
+
+       {"IN2LN", NULL, "Radio In"},
+       {"IN2RN", NULL, "Radio In"},
+};
+
+static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int ret;
+
+       /* add goni specific widgets */
+       snd_soc_dapm_new_controls(codec, goni_dapm_widgets,
+                       ARRAY_SIZE(goni_dapm_widgets));
+
+       /* set up goni specific audio routes */
+       snd_soc_dapm_add_routes(codec, goni_dapm_routes,
+                       ARRAY_SIZE(goni_dapm_routes));
+
+       /* set endpoints to not connected */
+       snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
+       snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
+       snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
+
+       snd_soc_dapm_sync(codec);
+
+       /* Headset jack detection */
+       ret = snd_soc_jack_new(&goni, "Headset Jack",
+                       SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
+                       &jack);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
+       if (ret)
+               return ret;
+
+       ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int goni_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->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int pll_out = 24000000;
+       int ret = 0;
+
+       /* set the 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 cpu system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
+                       0, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return 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)
+               return ret;
+
+       /* set the codec FLL */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
+                       params_rate(params) * 256);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
+                       params_rate(params) * 256, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops goni_hifi_ops = {
+       .hw_params = goni_hifi_hw_params,
+};
+
+static int goni_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->codec_dai;
+       unsigned int pll_out = 24000000;
+       int ret = 0;
+
+       if (params_rate(params) != 8000)
+               return -EINVAL;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
+                       SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec FLL */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
+                       params_rate(params) * 256);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
+                       params_rate(params) * 256, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_dai_driver voice_dai = {
+       .name = "goni-voice-dai",
+       .id = 0,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+};
+
+static struct snd_soc_ops goni_voice_ops = {
+       .hw_params = goni_voice_hw_params,
+};
+
+static struct snd_soc_dai_link goni_dai[] = {
+{
+       .name = "WM8994",
+       .stream_name = "WM8994 HiFi",
+       .cpu_dai_name = "s3c64xx-i2s-v4",
+       .codec_dai_name = "wm8994-hifi",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8994-codec.0-0x1a",
+       .init = goni_wm8994_init,
+       .ops = &goni_hifi_ops,
+}, {
+       .name = "WM8994 Voice",
+       .stream_name = "Voice",
+       .cpu_dai_name = "goni-voice-dai",
+       .codec_dai_name = "wm8994-voice",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8994-codec.0-0x1a",
+       .ops = &goni_voice_ops,
+},
+};
+
+static struct snd_soc_card goni = {
+       .name = "goni",
+       .dai_link = goni_dai,
+       .num_links = ARRAY_SIZE(goni_dai),
+};
+
+static int __init goni_init(void)
+{
+       int ret;
+
+       if (!machine_is_goni())
+               return -ENODEV;
+
+       goni_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!goni_snd_device)
+               return -ENOMEM;
+
+       /* register voice DAI here */
+       ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai);
+       if (ret)
+               return ret;
+
+       platform_set_drvdata(goni_snd_device, &goni);
+       ret = platform_device_add(goni_snd_device);
+
+       if (ret)
+               platform_device_put(goni_snd_device);
+
+       return ret;
+}
+
+static void __exit goni_exit(void)
+{
+       platform_device_unregister(goni_snd_device);
+}
+
+module_init(goni_init);
+module_exit(goni_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
index 8c108b1..49605cd 100644 (file)
@@ -49,8 +49,8 @@ static int jive_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct s3c_i2sv2_rate_calc div;
        unsigned int clk = 0;
        int ret = 0;
@@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = {
        .hw_params      = jive_hw_params,
 };
 
-static int jive_wm8750_init(struct snd_soc_codec *codec)
+static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* These endpoints are not being used. */
@@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link jive_dai = {
        .name           = "wm8750",
        .stream_name    = "WM8750",
-       .cpu_dai        = &s3c2412_i2s_dai,
-       .codec_dai      = &wm8750_dai,
+       .cpu_dai_name   = "s3c2412-i2s",
+       .codec_dai_name = "wm8750-hifi",
+       .platform_name  = "s3c24xx-pcm-audio",
+       .codec_name     = "wm8750-codec.0-0x1a",
        .init           = jive_wm8750_init,
        .ops            = &jive_ops,
 };
@@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = {
 /* jive audio machine driver */
 static struct snd_soc_card snd_soc_machine_jive = {
        .name           = "Jive",
-       .platform       = &s3c24xx_soc_platform,
        .dai_link       = &jive_dai,
        .num_links      = 1,
 };
 
-/* jive audio subsystem */
-static struct snd_soc_device jive_snd_devdata = {
-       .card           = &snd_soc_machine_jive,
-       .codec_dev      = &soc_codec_dev_wm8750,
-};
-
 static struct platform_device *jive_snd_device;
 
 static int __init jive_init(void)
@@ -173,8 +169,7 @@ static int __init jive_init(void)
        if (!jive_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(jive_snd_device, &jive_snd_devdata);
-       jive_snd_devdata.dev = &jive_snd_device->dev;
+       platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive);
        ret = platform_device_add(jive_snd_device);
 
        if (ret)
index ffa954f..abe64ab 100644 (file)
@@ -23,7 +23,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
-#include "../codecs/ac97.h"
 #include "s3c-dma.h"
 #include "s3c-ac97.h"
 
@@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM],
-       .codec_dai = &ac97_dai,
+       .cpu_dai_name = "s3c-ac97",
+       .codec_dai_name = "ac97-hifi",
+       .codec_name = "ac97-codec",
+       .platform_name = "s3c24xx-pcm-audio",
 },
 };
 
 static struct snd_soc_card ln2440sbc = {
        .name = "LN2440SBC",
-       .platform = &s3c24xx_soc_platform,
        .dai_link = ln2440sbc_dai,
        .num_links = ARRAY_SIZE(ln2440sbc_dai),
 };
 
-static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
-       .card = &ln2440sbc,
-       .codec_dev = &soc_codec_dev_ac97,
-};
-
 static struct platform_device *ln2440sbc_snd_ac97_device;
 
 static int __init ln2440sbc_init(void)
@@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void)
        if (!ln2440sbc_snd_ac97_device)
                return -ENOMEM;
 
-       platform_set_drvdata(ln2440sbc_snd_ac97_device,
-                               &ln2440sbc_snd_ac97_devdata);
-       ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev;
+       platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc);
        ret = platform_device_add(ln2440sbc_snd_ac97_device);
 
        if (ret)
index 4719558..e97bdf1 100644 (file)
@@ -41,8 +41,8 @@ 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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int pll_out = 0, bclk = 0;
        int ret = 0;
        unsigned long iis_clkrate;
@@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
 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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        /* disable the PLL */
        return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
@@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params(
        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 *codec_dai = rtd->codec_dai;
        unsigned int pcmdiv = 0;
        int ret = 0;
        unsigned long iis_clkrate;
@@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params(
 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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        /* disable the PLL */
        return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
@@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w,
                        struct snd_kcontrol *k,
                        int event)
 {
-       gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value));
+       gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
 
        return 0;
 }
@@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
  * 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)
+static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        /* set up NC codec pins */
@@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
 /*
  * BT Codec DAI
  */
-static struct snd_soc_dai bt_dai = {
-       .name = "Bluetooth",
-       .id = 0,
+static struct snd_soc_dai_driver bt_dai = {
+       .name = "bluetooth-dai",
        .playback = {
                .channels_min = 1,
                .channels_max = 1,
@@ -397,32 +397,30 @@ 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],
+       .cpu_dai_name = "s3c24xx-i2s",
+       .codec_dai_name = "wm8753-hifi",
        .init = neo1973_gta02_wm8753_init,
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8753-codec.0-0x1a",
        .ops = &neo1973_gta02_hifi_ops,
 },
 { /* Voice via BT */
        .name = "Bluetooth",
        .stream_name = "Voice",
-       .cpu_dai = &bt_dai,
-       .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
+       .cpu_dai_name = "bluetooth-dai",
+       .codec_dai_name = "wm8753-voice",
        .ops = &neo1973_gta02_voice_ops,
+       .codec_name = "wm8753-codec.0-0x1a",
+       .platform_name = "s3c24xx-pcm-audio",
 },
 };
 
 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)
@@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void)
                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;
+       /* register bluetooth DAI here */
+       ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai);
+       if (ret) {
+               platform_device_put(neo1973_gta02_snd_device);
+               return ret;
+       }
+
+       platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);
        ret = platform_device_add(neo1973_gta02_snd_device);
 
        if (ret) {
@@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void)
                goto err_unregister_device;
        }
 
-       ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1);
+       ret = gpio_direction_output(GTA02_GPIO_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;
@@ -493,7 +491,7 @@ module_init(neo1973_gta02_init);
 
 static void __exit neo1973_gta02_exit(void)
 {
-       snd_soc_unregister_dai(&bt_dai);
+       snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1);
        platform_device_unregister(neo1973_gta02_snd_device);
        gpio_free(GTA02_GPIO_HP_IN);
        gpio_free(GTA02_GPIO_AMP_SHUT);
index 4ac6209..f4f2ee7 100644 (file)
@@ -57,8 +57,8 @@ static int neo1973_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int pll_out = 0, bclk = 0;
        int ret = 0;
        unsigned long iis_clkrate;
@@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
 static int neo1973_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -167,7 +167,7 @@ static int neo1973_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        unsigned int pcmdiv = 0;
        int ret = 0;
        unsigned long iis_clkrate;
@@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 static int neo1973_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
  * neo1973 II. It is missing logic to detect hp/mic insertions and logic
  * to re-route the audio in such an event.
  */
-static int neo1973_wm8753_init(struct snd_soc_codec *codec)
+static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        int err;
 
        pr_debug("Entered %s\n", __func__);
@@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
  * BT Codec DAI
  */
 static struct snd_soc_dai bt_dai = {
-       .name = "Bluetooth",
-       .id = 0,
+       .name = "bluetooth-dai",
        .playback = {
                .channels_min = 1,
                .channels_max = 1,
@@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_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],
+       .platform_name = "s3c24xx-pcm-audio",
+       .cpu_dai_name = "s3c24xx-i2s",
+       .codec_dai_name = "wm8753-hifi",
+       .codec_name = "wm8753-codec.0-0x1a",
        .init = neo1973_wm8753_init,
        .ops = &neo1973_hifi_ops,
 },
 { /* Voice via BT */
        .name = "Bluetooth",
        .stream_name = "Voice",
-       .cpu_dai = &bt_dai,
-       .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
+       .platform_name = "s3c24xx-pcm-audio",
+       .cpu_dai_name = "bluetooth-dai",
+       .codec_dai_name = "wm8753-voice",
+       .codec_name = "wm8753-codec.0-0x1a",
        .ops = &neo1973_voice_ops,
 },
 };
 
 static struct snd_soc_card neo1973 = {
        .name = "neo1973",
-       .platform = &s3c24xx_soc_platform,
        .dai_link = neo1973_dai,
        .num_links = ARRAY_SIZE(neo1973_dai),
 };
 
-static struct snd_soc_device neo1973_snd_devdata = {
-       .card = &neo1973,
-       .codec_dev = &soc_codec_dev_wm8753,
-};
-
 static int lm4857_i2c_probe(struct i2c_client *client,
                            const struct i2c_device_id *id)
 {
@@ -673,8 +671,7 @@ static int __init neo1973_init(void)
        if (!neo1973_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata);
-       neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
+       platform_set_drvdata(neo1973_snd_device, &neo1973);
        ret = platform_device_add(neo1973_snd_device);
 
        if (ret) {
diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c
new file mode 100644 (file)
index 0000000..ffd5cf2
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * rx1950.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ * Based on smdk2440.c and magician.c
+ *
+ * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com
+ *          Philipp Zabel <philipp.zabel@gmail.com>
+ *          Denis Grigoriev <dgreenday@gmail.com>
+ *          Vasily Khoruzhick <anarsoul@gmail.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 <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/uda1380.h>
+#include <sound/jack.h>
+
+#include <plat/regs-iis.h>
+
+#include <mach/regs-clock.h>
+
+#include <asm/mach-types.h>
+
+#include "s3c-dma.h"
+#include "s3c24xx-i2s.h"
+#include "../codecs/uda1380.h"
+
+static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
+static int rx1950_startup(struct snd_pcm_substream *substream);
+static int rx1950_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params);
+static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event);
+
+static unsigned int rates[] = {
+       16000,
+       44100,
+       48000,
+       88200,
+};
+
+static struct snd_pcm_hw_constraint_list hw_rates = {
+       .count = ARRAY_SIZE(rates),
+       .list = rates,
+       .mask = 0,
+};
+
+static struct snd_soc_jack hp_jack;
+
+static struct snd_soc_jack_pin hp_jack_pins[] = {
+       {
+               .pin    = "Headphone Jack",
+               .mask   = SND_JACK_HEADPHONE,
+       },
+       {
+               .pin    = "Speaker",
+               .mask   = SND_JACK_HEADPHONE,
+               .invert = 1,
+       },
+};
+
+static struct snd_soc_jack_gpio hp_jack_gpios[] = {
+       [0] = {
+               .gpio                   = S3C2410_GPG(12),
+               .name                   = "hp-gpio",
+               .report                 = SND_JACK_HEADPHONE,
+               .invert                 = 1,
+               .debounce_time          = 200,
+       },
+};
+
+static struct snd_soc_ops rx1950_ops = {
+       .startup        = rx1950_startup,
+       .hw_params      = rx1950_hw_params,
+};
+
+/* s3c24xx digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
+       {
+               .name           = "uda1380",
+               .stream_name    = "UDA1380 Duplex",
+               .cpu_dai_name   = "s3c24xx-iis",
+               .codec_dai_name = "uda1380-hifi",
+               .init           = rx1950_uda1380_init,
+               .platform_name  = "s3c24xx-pcm-audio",
+               .codec_name     = "uda1380-codec.0-001a",
+               .ops            = &rx1950_ops,
+       },
+};
+
+static struct snd_soc_card rx1950_asoc = {
+       .name = "rx1950",
+       .dai_link = rx1950_uda1380_dai,
+       .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
+};
+
+/* rx1950 machine dapm widgets */
+static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+       SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power),
+};
+
+/* rx1950 machine audio_map */
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* headphone connected to VOUTLHP, VOUTRHP */
+       {"Headphone Jack", NULL, "VOUTLHP"},
+       {"Headphone Jack", NULL, "VOUTRHP"},
+
+       /* ext speaker connected to VOUTL, VOUTR  */
+       {"Speaker", NULL, "VOUTL"},
+       {"Speaker", NULL, "VOUTR"},
+
+       /* mic is connected to VINM */
+       {"VINM", NULL, "Mic Jack"},
+};
+
+static struct platform_device *s3c24xx_snd_device;
+static struct clk *xtal;
+
+static int rx1950_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       runtime->hw.rate_min = hw_rates.list[0];
+       runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1];
+       runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+
+       return snd_pcm_hw_constraint_list(runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_RATE,
+                                       &hw_rates);
+}
+
+static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
+                               struct snd_kcontrol *kcontrol, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               gpio_set_value(S3C2410_GPA(1), 1);
+       else
+               gpio_set_value(S3C2410_GPA(1), 0);
+
+       return 0;
+}
+
+static int rx1950_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->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       int div;
+       int ret;
+       unsigned int rate = params_rate(params);
+       int clk_source, fs_mode;
+
+       switch (rate) {
+       case 16000:
+       case 48000:
+               clk_source = S3C24XX_CLKSRC_PCLK;
+               fs_mode = S3C2410_IISMOD_256FS;
+               div = s3c24xx_i2s_get_clockrate() / (256 * rate);
+               if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate))
+                       div++;
+               break;
+       case 44100:
+       case 88200:
+               clk_source = S3C24XX_CLKSRC_MPLL;
+               fs_mode = S3C2410_IISMOD_256FS;
+               div = clk_get_rate(xtal) / (256 * rate);
+               if (clk_get_rate(xtal) % (256 * rate) > (128 * rate))
+                       div++;
+               break;
+       default:
+               printk(KERN_ERR "%s: rate %d is not supported\n",
+                       __func__, rate);
+               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_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_CBS_CFS);
+       if (ret < 0)
+               return ret;
+
+       /* select clock source */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate,
+                       SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
+       /* set MCLK division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+               S3C2410_IISMOD_384FS);
+       if (ret < 0)
+               return ret;
+
+       /* set BCLK division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
+               S3C2410_IISMOD_32FS);
+       if (ret < 0)
+               return ret;
+
+       /* set prescaler division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+               S3C24XX_PRESCALE(div, div));
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       int err;
+
+       /* Add rx1950 specific widgets */
+       err = snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
+                                 ARRAY_SIZE(uda1380_dapm_widgets));
+
+       if (err)
+               return err;
+
+       /* Set up rx1950 specific audio path audio_mapnects */
+       err = snd_soc_dapm_add_routes(codec, audio_map,
+                                     ARRAY_SIZE(audio_map));
+
+       if (err)
+               return err;
+
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Speaker");
+
+       snd_soc_dapm_sync(codec);
+
+       snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
+               &hp_jack);
+
+       snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
+               hp_jack_pins);
+
+       snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
+               hp_jack_gpios);
+
+       return 0;
+}
+
+static int __init rx1950_init(void)
+{
+       int ret;
+
+       if (!machine_is_rx1950())
+               return -ENODEV;
+
+       /* configure some gpios */
+       ret = gpio_request(S3C2410_GPA(1), "speaker-power");
+       if (ret)
+               goto err_gpio;
+
+       ret = gpio_direction_output(S3C2410_GPA(1), 0);
+       if (ret)
+               goto err_gpio_conf;
+
+       s3c24xx_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!s3c24xx_snd_device) {
+               ret = -ENOMEM;
+               goto err_plat_alloc;
+       }
+
+       platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc);
+       ret = platform_device_add(s3c24xx_snd_device);
+
+       if (ret) {
+               platform_device_put(s3c24xx_snd_device);
+               goto err_plat_add;
+       }
+
+       xtal = clk_get(&s3c24xx_snd_device->dev, "xtal");
+
+       if (IS_ERR(xtal)) {
+               ret = PTR_ERR(xtal);
+               platform_device_unregister(s3c24xx_snd_device);
+               goto err_clk;
+       }
+
+       return 0;
+
+err_clk:
+err_plat_add:
+err_plat_alloc:
+err_gpio_conf:
+       gpio_free(S3C2410_GPA(1));
+
+err_gpio:
+       return ret;
+}
+
+static void __exit rx1950_exit(void)
+{
+       platform_device_unregister(s3c24xx_snd_device);
+       snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
+               hp_jack_gpios);
+       clk_put(xtal);
+       gpio_free(S3C2410_GPA(1));
+}
+
+module_init(rx1950_init);
+module_exit(rx1950_exit);
+
+/* Module information */
+MODULE_AUTHOR("Vasily Khoruzhick");
+MODULE_DESCRIPTION("ALSA SoC RX1950");
+MODULE_LICENSE("GPL");
index 31f6d45..f891eb7 100644 (file)
@@ -89,7 +89,7 @@ static void s3c_ac97_activate(struct snd_ac97 *ac97)
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
        if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
-               printk(KERN_ERR "AC97: Unable to activate!");
+               pr_err("AC97: Unable to activate!");
 }
 
 static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
@@ -115,14 +115,15 @@ static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
        if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
-               printk(KERN_ERR "AC97: Unable to read!");
+               pr_err("AC97: Unable to read!");
 
        stat = readl(s3c_ac97.regs + S3C_AC97_STAT);
        addr = (stat >> 16) & 0x7f;
        data = (stat & 0xffff);
 
        if (addr != reg)
-               printk(KERN_ERR "s3c-ac97: req addr = %02x, rep addr = %02x\n", reg, addr);
+               pr_err("s3c-ac97: req addr = %02x, rep addr = %02x\n",
+                       reg, addr);
 
        mutex_unlock(&s3c_ac97.lock);
 
@@ -151,7 +152,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
 
        if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
-               printk(KERN_ERR "AC97: Unable to write!");
+               pr_err("AC97: Unable to write!");
 
        ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
        ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
@@ -162,6 +163,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 
 static void s3c_ac97_cold_reset(struct snd_ac97 *ac97)
 {
+       pr_debug("AC97: Cold reset\n");
        writel(S3C_AC97_GLBCTRL_COLDRESET,
                        s3c_ac97.regs + S3C_AC97_GLBCTRL);
        msleep(1);
@@ -178,6 +180,8 @@ static void s3c_ac97_warm_reset(struct snd_ac97 *ac97)
        if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE)
                return; /* Return if already active */
 
+       pr_debug("AC97: Warm reset\n");
+
        writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL);
        msleep(1);
 
@@ -222,7 +226,7 @@ static int s3c_ac97_hw_params(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 snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct s3c_dma_params *dma_data;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -241,7 +245,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
        u32 ac_glbctrl;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct s3c_dma_params *dma_data =
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -277,7 +281,7 @@ static int s3c_ac97_hw_mic_params(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 snd_soc_dai *cpu_dai = rtd->cpu_dai;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                return -ENODEV;
@@ -293,7 +297,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
        u32 ac_glbctrl;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct s3c_dma_params *dma_data =
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
        ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
@@ -328,10 +332,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
        .trigger        = s3c_ac97_mic_trigger,
 };
 
-struct snd_soc_dai s3c_ac97_dai[] = {
+static struct snd_soc_dai_driver s3c_ac97_dai[] = {
        [S3C_AC97_DAI_PCM] = {
                .name = "s3c-ac97",
-               .id = S3C_AC97_DAI_PCM,
                .ac97_control = 1,
                .playback = {
                        .stream_name = "AC97 Playback",
@@ -349,7 +352,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {
        },
        [S3C_AC97_DAI_MIC] = {
                .name = "s3c-ac97-mic",
-               .id = S3C_AC97_DAI_MIC,
                .ac97_control = 1,
                .capture = {
                        .stream_name = "AC97 Mic Capture",
@@ -360,7 +362,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {
                .ops = &s3c_ac97_mic_dai_ops,
        },
 };
-EXPORT_SYMBOL_GPL(s3c_ac97_dai);
 
 static __devinit int s3c_ac97_probe(struct platform_device *pdev)
 {
@@ -445,14 +446,12 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
        ret = request_irq(irq_res->start, s3c_ac97_irq,
                                        IRQF_DISABLED, "AC97", NULL);
        if (ret < 0) {
-               printk(KERN_ERR "s3c-ac97: interrupt request failed.\n");
+               dev_err(&pdev->dev, "s3c-ac97: interrupt request failed.\n");
                goto err4;
        }
 
-       s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev;
-       s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev;
-
-       ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
+       ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai,
+                       ARRAY_SIZE(s3c_ac97_dai));
        if (ret)
                goto err5;
 
@@ -476,7 +475,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
 {
        struct resource *mem_res, *irq_res;
 
-       snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
 
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (irq_res)
@@ -518,3 +517,4 @@ module_exit(s3c_ac97_exit);
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c-ac97");
index 2781983..5dcedd0 100644 (file)
@@ -18,6 +18,4 @@
 #define S3C_AC97_DAI_PCM 0
 #define S3C_AC97_DAI_MIC 1
 
-extern struct snd_soc_dai s3c_ac97_dai[];
-
 #endif /* __S3C_AC97_H_ */
index f1b1bc4..243f79b 100644 (file)
@@ -146,7 +146,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        unsigned long totbytes = params_buffer_bytes(params);
        struct s3c_dma_params *dma =
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
        int ret = 0;
 
 
@@ -440,14 +440,14 @@ static int s3c_dma_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = 0xffffffff;
 
-       if (dai->playback.channels_min) {
+       if (dai->driver->playback.channels_min) {
                ret = s3c_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->capture.channels_min) {
+       if (dai->driver->capture.channels_min) {
                ret = s3c_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
@@ -457,26 +457,46 @@ static int s3c_dma_new(struct snd_card *card,
        return ret;
 }
 
-struct snd_soc_platform s3c24xx_soc_platform = {
-       .name           = "s3c24xx-audio",
-       .pcm_ops        = &s3c_dma_ops,
+static struct snd_soc_platform_driver s3c24xx_soc_platform = {
+       .ops            = &s3c_dma_ops,
        .pcm_new        = s3c_dma_new,
        .pcm_free       = s3c_dma_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
 
-static int __init s3c24xx_soc_platform_init(void)
+static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&s3c24xx_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform);
 }
-module_init(s3c24xx_soc_platform_init);
 
-static void __exit s3c24xx_soc_platform_exit(void)
+static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&s3c24xx_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver s3c24xx_pcm_driver = {
+       .driver = {
+               .name = "s3c24xx-pcm-audio",
+               .owner = THIS_MODULE,
+       },
+
+       .probe = s3c24xx_soc_platform_probe,
+       .remove = __devexit_p(s3c24xx_soc_platform_remove),
+};
+
+static int __init snd_s3c24xx_pcm_init(void)
+{
+       return platform_driver_register(&s3c24xx_pcm_driver);
+}
+module_init(snd_s3c24xx_pcm_init);
+
+static void __exit snd_s3c24xx_pcm_exit(void)
+{
+       platform_driver_unregister(&s3c24xx_pcm_driver);
 }
-module_exit(s3c24xx_soc_platform_exit);
+module_exit(snd_s3c24xx_pcm_exit);
 
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c24xx-pcm-audio");
index 69bb6bf..748c07d 100644 (file)
@@ -25,7 +25,6 @@ struct s3c_dma_params {
 #define S3C24XX_DAI_I2S                        0
 
 /* platform data */
-extern struct snd_soc_platform s3c24xx_soc_platform;
 extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
 
 #endif
index 64376b2..b3866d5 100644 (file)
@@ -49,7 +49,7 @@
 
 static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
 {
-       return cpu_dai->private_data;
+       return snd_soc_dai_get_drvdata(cpu_dai);
 }
 
 #define bit_set(v, b) (((v) & (b)) ? 1 : 0)
@@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
 
 static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
-                                struct snd_soc_dai *socdai)
+                                struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai_link *dai = rtd->dai;
-       struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
+       struct s3c_i2sv2_info *i2s = to_info(dai);
        struct s3c_dma_params *dma_data;
        u32 iismod;
 
@@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
        else
                dma_data = i2s->dma_capture;
 
-       snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
+       snd_soc_dai_set_dma_data(dai, substream, dma_data);
 
        /* Working copies of register */
        iismod = readl(i2s->regs + S3C2412_IISMOD);
@@ -396,12 +394,12 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai);
+       struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai);
        int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
        unsigned long irqs;
        int ret = 0;
        struct s3c_dma_params *dma_data =
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
        pr_debug("Entered %s\n", __func__);
 
@@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate);
 
-int s3c_i2sv2_probe(struct platform_device *pdev,
-                   struct snd_soc_dai *dai,
+int s3c_i2sv2_probe(struct snd_soc_dai *dai,
                    struct s3c_i2sv2_info *i2s,
                    unsigned long base)
 {
-       struct device *dev = &pdev->dev;
+       struct device *dev = dai->dev;
        unsigned int iismod;
 
        i2s->dev = dev;
 
        /* record our i2s structure for later use in the callbacks */
-       dai->private_data = i2s;
-
-       if (!base) {
-               struct resource *res = platform_get_resource(pdev,
-                                                            IORESOURCE_MEM,
-                                                            0);
-               if (!res) {
-                       dev_err(dev, "Unable to get register resource\n");
-                       return -ENXIO;
-               }
-
-               if (!request_mem_region(res->start, resource_size(res),
-                                       "s3c64xx-i2s-v4")) {
-                       dev_err(dev, "Unable to request register region\n");
-                       return -EBUSY;
-               }
-
-               base = res->start;
-       }
+       snd_soc_dai_set_drvdata(dai, i2s);
 
        i2s->regs = ioremap(base, 0x100);
        if (i2s->regs == NULL) {
@@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
 #define s3c2412_i2s_resume  NULL
 #endif
 
-int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
+int s3c_i2sv2_register_dai(struct device *dev, int id,
+               struct snd_soc_dai_driver *drv)
 {
-       struct snd_soc_dai_ops *ops = dai->ops;
+       struct snd_soc_dai_ops *ops = drv->ops;
 
        ops->trigger = s3c2412_i2s_trigger;
        if (!ops->hw_params)
@@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
        if (!ops->delay)
                ops->delay = s3c2412_i2s_delay;
 
-       dai->suspend = s3c2412_i2s_suspend;
-       dai->resume = s3c2412_i2s_resume;
+       drv->suspend = s3c2412_i2s_suspend;
+       drv->resume = s3c2412_i2s_resume;
 
-       return snd_soc_register_dai(dai);
+       return snd_soc_register_dai(dev, drv);
 }
 EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
 
index 766f43a..d458301 100644 (file)
@@ -66,6 +66,8 @@ struct s3c_i2sv2_info {
        u32              suspend_iismod;
        u32              suspend_iiscon;
        u32              suspend_iispsr;
+
+       unsigned long   base;
 };
 
 extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai);
@@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
 
 /**
  * s3c_i2sv2_probe - probe for i2s device helper
- * @pdev: The platform device supplied to the original probe.
  * @dai: The ASoC DAI structure supplied to the original probe.
  * @i2s: Our local i2s structure to fill in.
  * @base: The base address for the registers.
  */
-extern int s3c_i2sv2_probe(struct platform_device *pdev,
-                          struct snd_soc_dai *dai,
+extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
                           struct s3c_i2sv2_info *i2s,
                           unsigned long base);
 
 /**
  * s3c_i2sv2_register_dai - register dai with soc core
- * @dai: The snd_soc_dai structure to register
+ * @dev: DAI device
+ * @id: DAI ID
+ * @drv: The driver structure to register
  *
  * Fill in any missing fields and then register the given dai with the
  * soc core.
  */
-extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
+extern int s3c_i2sv2_register_dai(struct device *dev, int id,
+               struct snd_soc_dai_driver *drv);
 
 #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
index 326f0a9..2e020e1 100644 (file)
@@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = {
 
 static struct s3c_pcm_info s3c_pcm[2];
 
-static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai)
-{
-       return cpu_dai->private_data;
-}
-
 static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
 {
        void __iomem *regs = pcm->regs;
@@ -83,7 +78,7 @@ static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
                ctl |= S3C_PCM_CTL_TXDMA_EN;
                ctl |= S3C_PCM_CTL_TXFIFO_EN;
                ctl |= S3C_PCM_CTL_ENABLE;
-               ctl |= (0x20<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
+               ctl |= (0x4<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
                clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
        } else {
                ctl &= ~S3C_PCM_CTL_TXDMA_EN;
@@ -107,11 +102,14 @@ static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on)
 
        ctl = readl(regs + S3C_PCM_CTL);
        clkctl = readl(regs + S3C_PCM_CLKCTL);
+       ctl &= ~(S3C_PCM_CTL_RXDIPSTICK_MASK
+                        << S3C_PCM_CTL_RXDIPSTICK_SHIFT);
 
        if (on) {
                ctl |= S3C_PCM_CTL_RXDMA_EN;
                ctl |= S3C_PCM_CTL_RXFIFO_EN;
                ctl |= S3C_PCM_CTL_ENABLE;
+               ctl |= (0x20<<S3C_PCM_CTL_RXDIPSTICK_SHIFT);
                clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
        } else {
                ctl &= ~S3C_PCM_CTL_RXDMA_EN;
@@ -132,7 +130,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai);
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        unsigned long flags;
 
        dev_dbg(pcm->dev, "Entered %s\n", __func__);
@@ -176,8 +174,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_soc_dai *socdai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai_link *dai = rtd->dai;
-       struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        struct s3c_dma_params *dma_data;
        void __iomem *regs = pcm->regs;
        struct clk *clk;
@@ -192,7 +189,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
        else
                dma_data = pcm->dma_capture;
 
-       snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data);
+       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
 
        /* Strictly check for sample size */
        switch (params_format(params)) {
@@ -242,7 +239,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
 static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
                               unsigned int fmt)
 {
-       struct s3c_pcm_info *pcm = to_info(cpu_dai);
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *regs = pcm->regs;
        unsigned long flags;
        int ret = 0;
@@ -313,7 +310,7 @@ exit:
 static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
                                                int div_id, int div)
 {
-       struct s3c_pcm_info *pcm = to_info(cpu_dai);
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
 
        switch (div_id) {
        case S3C_PCM_SCLK_PER_FS:
@@ -330,7 +327,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
 static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
                                  int clk_id, unsigned int freq, int dir)
 {
-       struct s3c_pcm_info *pcm = to_info(cpu_dai);
+       struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *regs = pcm->regs;
        u32 clkctl = readl(regs + S3C_PCM_CLKCTL);
 
@@ -366,10 +363,7 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
 
 #define S3C_PCM_RATES  SNDRV_PCM_RATE_8000_96000
 
-#define S3C_PCM_DECLARE(n)                     \
-{                                                              \
-       .name            = "samsung-pcm",                       \
-       .id              = (n),                         \
+#define S3C_PCM_DAI_DECLARE                    \
        .symmetric_rates = 1,                                   \
        .ops = &s3c_pcm_dai_ops,                                \
        .playback = {                                           \
@@ -383,19 +377,23 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
                .channels_max   = 2,                            \
                .rates          = S3C_PCM_RATES,                \
                .formats        = SNDRV_PCM_FMTBIT_S16_LE,      \
-       },                                                      \
-}
+       }
 
-struct snd_soc_dai s3c_pcm_dai[] = {
-       S3C_PCM_DECLARE(0),
-       S3C_PCM_DECLARE(1),
+struct snd_soc_dai_driver s3c_pcm_dai[] = {
+       [0] = {
+               .name   = "samsung-pcm.0",
+               S3C_PCM_DAI_DECLARE,
+       },
+       [1] = {
+               .name   = "samsung-pcm.1",
+               S3C_PCM_DAI_DECLARE,
+       },
 };
 EXPORT_SYMBOL_GPL(s3c_pcm_dai);
 
 static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
 {
        struct s3c_pcm_info *pcm;
-       struct snd_soc_dai *dai;
        struct resource *mem_res, *dmatx_res, *dmarx_res;
        struct s3c_audio_pdata *pcm_pdata;
        int ret;
@@ -437,9 +435,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
 
        spin_lock_init(&pcm->lock);
 
-       dai = &s3c_pcm_dai[pdev->id];
-       dai->dev = &pdev->dev;
-
        /* Default is 128fs */
        pcm->sclk_per_fs = 128;
 
@@ -452,7 +447,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
        clk_enable(pcm->cclk);
 
        /* record our pcm structure for later use in the callbacks */
-       dai->private_data = pcm;
+       dev_set_drvdata(&pdev->dev, pcm);
 
        if (!request_mem_region(mem_res->start,
                                resource_size(mem_res), "samsung-pcm")) {
@@ -476,7 +471,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
        }
        clk_enable(pcm->pclk);
 
-       ret = snd_soc_register_dai(dai);
+       ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
        if (ret != 0) {
                dev_err(&pdev->dev, "failed to get pcm_clock\n");
                goto err5;
@@ -514,6 +509,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
        struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
        struct resource *mem_res;
 
+       snd_soc_unregister_dai(&pdev->dev);
+
        iounmap(pcm->regs);
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -552,3 +549,4 @@ module_exit(s3c_pcm_exit);
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("S3C PCM Controller Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-pcm");
index 69ff997..f60baa1 100644 (file)
@@ -22,7 +22,8 @@
 /* PCM_CTL Bit-Fields */
 #define S3C_PCM_CTL_TXDIPSTICK_MASK            (0x3f)
 #define S3C_PCM_CTL_TXDIPSTICK_SHIFT   (13)
-#define S3C_PCM_CTL_RXDIPSTICK_MSK             (0x3f<<7)
+#define S3C_PCM_CTL_RXDIPSTICK_MASK            (0x3f)
+#define S3C_PCM_CTL_RXDIPSTICK_SHIFT   (7)
 #define S3C_PCM_CTL_TXDMA_EN           (0x1<<6)
 #define S3C_PCM_CTL_RXDMA_EN           (0x1<<5)
 #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC  (0x1<<4)
index 709adef..4a861cf 100644 (file)
@@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
 
 static struct s3c_i2sv2_info s3c2412_i2s;
 
-static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
-{
-       return cpu_dai->private_data;
-}
-
-static int s3c2412_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
 {
        int ret;
 
        pr_debug("Entered %s\n", __func__);
 
-       ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS);
+       ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);
        if (ret)
                return ret;
 
        s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
        s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
 
-       s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
+       s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
        if (s3c2412_i2s.iis_cclk == NULL) {
                pr_err("failed to get i2sclk clock\n");
                iounmap(s3c2412_i2s.regs);
@@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
        return 0;
 }
 
+static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
+{
+       clk_disable(s3c2412_i2s.iis_cclk);
+       clk_put(s3c2412_i2s.iis_cclk);
+       iounmap(s3c2412_i2s.regs);
+
+       return 0;
+}
+
 static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *cpu_dai)
 {
-       struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+       struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
        struct s3c_dma_params *dma_data;
        u32 iismod;
 
@@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
        .hw_params      = s3c2412_i2s_hw_params,
 };
 
-struct snd_soc_dai s3c2412_i2s_dai = {
-       .name           = "s3c2412-i2s",
-       .id             = 0,
+static struct snd_soc_dai_driver s3c2412_i2s_dai = {
        .probe          = s3c2412_i2s_probe,
+       .remove = s3c2412_i2s_remove,
        .playback = {
                .channels_min   = 2,
                .channels_max   = 2,
@@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = {
        },
        .ops = &s3c2412_i2s_dai_ops,
 };
-EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
+
+static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai);
+}
+
+static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver s3c2412_iis_driver = {
+       .probe  = s3c2412_iis_dev_probe,
+       .remove = s3c2412_iis_dev_remove,
+       .driver = {
+               .name = "s3c2412-iis",
+               .owner = THIS_MODULE,
+       },
+};
 
 static int __init s3c2412_i2s_init(void)
 {
-       return  s3c_i2sv2_register_dai(&s3c2412_i2s_dai);
+       return platform_driver_register(&s3c2412_iis_driver);
 }
 module_init(s3c2412_i2s_init);
 
 static void __exit s3c2412_i2s_exit(void)
 {
-       snd_soc_unregister_dai(&s3c2412_i2s_dai);
+       platform_driver_unregister(&s3c2412_iis_driver);
 }
 module_exit(s3c2412_i2s_exit);
 
@@ -188,3 +209,4 @@ module_exit(s3c2412_i2s_exit);
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c2412-iis");
index 0b5686b..01a0471 100644 (file)
@@ -24,6 +24,4 @@
 #define S3C2412_CLKSRC_PCLK    S3C_I2SV2_CLKSRC_PCLK
 #define S3C2412_CLKSRC_I2SCLK  S3C_I2SV2_CLKSRC_AUDIOBUS
 
-extern struct snd_soc_dai s3c2412_i2s_dai;
-
 #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */
index c3ac890..e060daa 100644 (file)
@@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
        else
                dma_data = &s3c24xx_i2s_pcm_stereo_in;
 
-       snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data);
+       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
 
        /* Working copies of register */
        iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -280,9 +280,8 @@ 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;
        struct s3c_dma_params *dma_data =
-               snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(dai, substream);
 
        pr_debug("Entered %s\n", __func__);
 
@@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void)
 }
 EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
 
-static int s3c24xx_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
 {
        pr_debug("Entered %s\n", __func__);
 
@@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,
        if (s3c24xx_i2s.regs == NULL)
                return -ENXIO;
 
-       s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis");
+       s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
        if (s3c24xx_i2s.iis_clk == NULL) {
                pr_err("failed to get iis_clock\n");
                iounmap(s3c24xx_i2s.regs);
@@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
        .set_sysclk     = s3c24xx_i2s_set_sysclk,
 };
 
-struct snd_soc_dai s3c24xx_i2s_dai = {
-       .name = "s3c24xx-i2s",
-       .id = 0,
+static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
        .probe = s3c24xx_i2s_probe,
        .suspend = s3c24xx_i2s_suspend,
        .resume = s3c24xx_i2s_resume,
@@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
                .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
        .ops = &s3c24xx_i2s_dai_ops,
 };
-EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
+
+static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
+}
+
+static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver s3c24xx_iis_driver = {
+       .probe  = s3c24xx_iis_dev_probe,
+       .remove = s3c24xx_iis_dev_remove,
+       .driver = {
+               .name = "s3c24xx-iis",
+               .owner = THIS_MODULE,
+       },
+};
 
 static int __init s3c24xx_i2s_init(void)
 {
-       return snd_soc_register_dai(&s3c24xx_i2s_dai);
+       return platform_driver_register(&s3c24xx_iis_driver);
 }
 module_init(s3c24xx_i2s_init);
 
 static void __exit s3c24xx_i2s_exit(void)
 {
-       snd_soc_unregister_dai(&s3c24xx_i2s_dai);
+       platform_driver_unregister(&s3c24xx_iis_driver);
 }
 module_exit(s3c24xx_i2s_exit);
 
@@ -501,3 +516,4 @@ module_exit(s3c24xx_i2s_exit);
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c24xx-iis");
index 726d91c..f9ca04e 100644 (file)
@@ -32,6 +32,4 @@
 
 u32 s3c24xx_i2s_get_clockrate(void);
 
-extern struct snd_soc_dai s3c24xx_i2s_dai;
-
 #endif /*S3C24XXI2S_H_*/
index 4984754..c4c1114 100644 (file)
@@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
                       speaker_unmute_get, speaker_unmute_put),
 };
 
-void simtec_audio_init(struct snd_soc_codec *codec)
+void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        if (pdata->amp_gpio > 0) {
                pr_debug("%s: adding amp routes\n", __func__);
 
@@ -170,8 +172,8 @@ 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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret;
 
        /* Set the CODEC as the bus clock master, I2S */
@@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops);
 #endif
 
 int __devinit simtec_audio_core_probe(struct platform_device *pdev,
-                                     struct snd_soc_device *socdev)
+                                     struct snd_soc_card *card)
 {
        struct platform_device *snd_dev;
        int ret;
 
-       socdev->card->dai_link->ops = &simtec_snd_ops;
+       card->dai_link->ops = &simtec_snd_ops;
 
        pdata = pdev->dev.platform_data;
        if (!pdata) {
@@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev,
                goto err_gpio;
        }
 
-       platform_set_drvdata(snd_dev, socdev);
-       socdev->dev = &snd_dev->dev;
+       platform_set_drvdata(snd_dev, card);
 
        ret = platform_device_add(snd_dev);
        if (ret) {
index e18faee..e63d5ff 100644 (file)
@@ -7,10 +7,10 @@
  * published by the Free Software Foundation.
 */
 
-extern void simtec_audio_init(struct snd_soc_codec *codec);
+extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd);
 
 extern int simtec_audio_core_probe(struct platform_device *pdev,
-                                  struct snd_soc_device *socdev);
+                                  struct snd_soc_card *card);
 
 extern int simtec_audio_remove(struct platform_device *pdev);
 
index bdf8951..f884537 100644 (file)
@@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = {
  * Attach our controls and configure the necessary codec
  * mappings for our sound card instance.
 */
-static int simtec_hermes_init(struct snd_soc_codec *codec)
+static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_new_controls(codec, dapm_widgets,
                                  ARRAY_SIZE(dapm_widgets));
 
@@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec)
        snd_soc_dapm_enable_pin(codec, "Line Out");
        snd_soc_dapm_enable_pin(codec, "Mic Jack");
 
-       simtec_audio_init(codec);
+       simtec_audio_init(rtd);
        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,
+       .codec_name     = "tlv320aic3x-codec.0-0x1a",
+       .cpu_dai_name   = "s3c24xx-i2s",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .platform_name  = "s3c24xx-pcm-audio",
        .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);
+       return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
 }
 
 static struct platform_driver simtec_audio_hermes_platdrv = {
index 185c0ac..c096759 100644 (file)
@@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = {
  * Attach our controls and configure the necessary codec
  * mappings for our sound card instance.
 */
-static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
+static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_new_controls(codec, dapm_widgets,
                                  ARRAY_SIZE(dapm_widgets));
 
@@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
        snd_soc_dapm_enable_pin(codec, "Line Out");
        snd_soc_dapm_enable_pin(codec, "Mic Jack");
 
-       simtec_audio_init(codec);
+       simtec_audio_init(rtd);
        snd_soc_dapm_sync(codec);
 
        return 0;
@@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link simtec_dai_aic23 = {
        .name           = "tlv320aic23",
        .stream_name    = "TLV320AIC23",
-       .cpu_dai        = &s3c24xx_i2s_dai,
-       .codec_dai      = &tlv320aic23_dai,
+       .codec_name     = "tlv320aic3x-codec.0-0x1a",
+       .cpu_dai_name   = "s3c24xx-i2s",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .platform_name  = "s3c24xx-pcm-audio",
        .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);
+       return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
 }
 
 static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
index 052d596..bd48ffb 100644 (file)
@@ -133,8 +133,8 @@ static int s3c24xx_uda134x_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        unsigned int clk = 0;
        int ret = 0;
        int clk_source, fs_mode;
@@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = {
 static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
        .name = "UDA134X",
        .stream_name = "UDA134X",
-       .codec_dai = &uda134x_dai,
-       .cpu_dai = &s3c24xx_i2s_dai,
+       .codec_name = "uda134x-hifi",
+       .codec_dai_name = "uda134x-hifi",
+       .cpu_dai_name = "s3c24xx-i2s",
        .ops = &s3c24xx_uda134x_ops,
+       .platform_name  = "s3c24xx-pcm-audio",
 };
 
 static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
        .name = "S3C24XX_UDA134X",
-       .platform = &s3c24xx_soc_platform,
        .dai_link = &s3c24xx_uda134x_dai_link,
        .num_links = 1,
 };
@@ -256,6 +257,7 @@ static void setmode(int v)
        gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
 }
 
+/* FIXME - This must be codec platform data but in which board file ?? */
 static struct uda134x_platform_data s3c24xx_uda134x = {
        .l3 = {
                .setdat = setdat,
@@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = {
        },
 };
 
-static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
-       .card = &snd_soc_s3c24xx_uda134x,
-       .codec_dev = &soc_codec_dev_uda134x,
-       .codec_data = &s3c24xx_uda134x,
-};
-
 static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
 {
        if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
@@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(s3c24xx_uda134x_snd_device,
-                            &s3c24xx_uda134x_snd_devdata);
-       s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
+                            &snd_soc_s3c24xx_uda134x);
        ret = platform_device_add(s3c24xx_uda134x_snd_device);
        if (ret) {
                printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
index 06db130..a962847 100644 (file)
@@ -16,9 +16,7 @@
 #include <sound/soc.h>
 #include <sound/pcm_params.h>
 
-#include <mach/gpio-bank-c.h>
-#include <mach/gpio-bank-h.h>
-#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out;
 static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in;
 static struct s3c_i2sv2_info s3c64xx_i2sv4;
 
-struct snd_soc_dai s3c64xx_i2s_v4_dai;
-EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai);
-
-static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai)
 {
-       return cpu_dai->private_data;
-}
+       struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
+       int ret = 0;
 
-static int s3c64xx_i2sv4_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
-{
-       /* configure GPIO for i2s port */
-       s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0);
-       s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1);
-       s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2);
-       s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK);
-       s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
-       s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
-       s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
+       snd_soc_dai_set_drvdata(dai, i2s);
 
-       return 0;
+       ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
+
+       return ret;
 }
 
 static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *cpu_dai)
 {
-       struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+       struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
        struct s3c_dma_params *dma_data;
        u32 iismod;
 
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = {
        .hw_params      = s3c_i2sv4_hw_params,
 };
 
+static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = {
+       .symmetric_rates = 1,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,
+       },
+       .probe = s3c64xx_i2sv4_probe,
+       .ops = &s3c64xx_i2sv4_dai_ops,
+};
+
 static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
 {
+       struct s3c_audio_pdata *i2s_pdata;
        struct s3c_i2sv2_info *i2s;
-       struct snd_soc_dai *dai;
+       struct resource *res;
        int ret;
 
        i2s = &s3c64xx_i2sv4;
-       dai = &s3c64xx_i2s_v4_dai;
-
-       if (dai->dev) {
-               dev_dbg(dai->dev, "%s: \
-                       I2Sv4 instance already registered!\n", __func__);
-               return -EBUSY;
-       }
-
-       dai->dev = &pdev->dev;
-       dai->name = "s3c64xx-i2s-v4";
-       dai->id = 0;
-       dai->symmetric_rates = 1;
-       dai->playback.channels_min = 2;
-       dai->playback.channels_max = 2;
-       dai->playback.rates = S3C64XX_I2S_RATES;
-       dai->playback.formats = S3C64XX_I2S_FMTS;
-       dai->capture.channels_min = 2;
-       dai->capture.channels_max = 2;
-       dai->capture.rates = S3C64XX_I2S_RATES;
-       dai->capture.formats = S3C64XX_I2S_FMTS;
-       dai->probe = s3c64xx_i2sv4_probe;
-       dai->ops = &s3c64xx_i2sv4_dai_ops;
 
        i2s->feature |= S3C_FEATURE_CDCLKCON;
 
        i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in;
        i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out;
 
-       i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX;
-       i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD;
-       i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX;
-       i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD;
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
+               return -ENXIO;
+       }
+       i2s->dma_playback->channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
+               return -ENXIO;
+       }
+       i2s->dma_capture->channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
+               return -ENXIO;
+       }
+
+       if (!request_mem_region(res->start, resource_size(res),
+                               "s3c64xx-i2s-v4")) {
+               dev_err(&pdev->dev, "Unable to request SFR region\n");
+               return -EBUSY;
+       }
+       i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
+       i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
 
        i2s->dma_capture->client = &s3c64xx_dma_client_in;
        i2s->dma_capture->dma_size = 4;
        i2s->dma_playback->client = &s3c64xx_dma_client_out;
        i2s->dma_playback->dma_size = 4;
 
+       i2s->base = res->start;
+
+       i2s_pdata = pdev->dev.platform_data;
+       if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
+               dev_err(&pdev->dev, "Unable to configure gpio\n");
+               return -EINVAL;
+       }
+
        i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
        if (IS_ERR(i2s->iis_cclk)) {
                dev_err(&pdev->dev, "failed to get audio-bus\n");
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
 
        clk_enable(i2s->iis_cclk);
 
-       ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
-       if (ret)
-               goto err_clk;
-
-       ret = s3c_i2sv2_register_dai(dai);
+       ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai);
        if (ret != 0)
                goto err_i2sv2;
 
        return 0;
 
 err_i2sv2:
-       /* Not implemented for I2Sv2 core yet */
-err_clk:
        clk_put(i2s->iis_cclk);
 err:
        return ret;
@@ -178,7 +187,18 @@ err:
 
 static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev)
 {
-       dev_err(&pdev->dev, "Device removal not yet supported\n");
+       struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
+       struct resource *res;
+
+       snd_soc_unregister_dai(&pdev->dev);
+       clk_put(i2s->iis_cclk);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res)
+               release_mem_region(res->start, resource_size(res));
+       else
+               dev_warn(&pdev->dev, "Unable to get I2S SFR address\n");
+               
        return 0;
 }
 
@@ -207,3 +227,4 @@ module_exit(s3c64xx_i2sv4_exit);
 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
 MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c64xx-iis-v4");
index 1d85cb8..ae7acb6 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 
 #include <sound/soc.h>
 
-#include <mach/gpio-bank-d.h>
-#include <mach/gpio-bank-e.h>
-#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
@@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];
 static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];
 static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3];
 
-struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3];
-EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
-
-static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
+struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
 {
-       return cpu_dai->private_data;
+       struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
+       u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+       if (iismod & S3C2412_IISMOD_IMS_SYSMUX)
+               return i2s->iis_cclk;
+       else
+               return i2s->iis_pclk;
 }
+EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
 
-static int s3c64xx_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static int s3c64xx_i2s_probe(struct snd_soc_dai *dai)
 {
-       /* configure GPIO for i2s port */
-       switch (dai->id) {
-       case 0:
-               s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
-               s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
-               s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
-               s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
-               s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
-               break;
-       case 1:
-               s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK);
-               s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
-               s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
-               s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
-               s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
+       struct s3c_i2sv2_info *i2s;
+       int ret;
+
+       if (dai->id >= MAX_I2SV3) {
+               dev_err(dai->dev, "id %d out of range\n", dai->id);
+               return -EINVAL;
+       }
+
+       i2s = &s3c64xx_i2s[dai->id];
+       snd_soc_dai_set_drvdata(dai, i2s);
+
+       i2s->iis_cclk = clk_get(dai->dev, "audio-bus");
+       if (IS_ERR(i2s->iis_cclk)) {
+               dev_err(dai->dev, "failed to get audio-bus\n");
+               ret = PTR_ERR(i2s->iis_cclk);
+               goto err;
        }
 
+       clk_enable(i2s->iis_cclk);
+
+       ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
+       if (ret)
+               goto err_clk;
+
        return 0;
+
+err_clk:
+       clk_disable(i2s->iis_cclk);
+       clk_put(i2s->iis_cclk);
+err:
+       kfree(i2s);
+       return ret;
 }
 
+static int s3c64xx_i2s_remove(struct snd_soc_dai *dai)
+{
+       struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
+
+       clk_disable(i2s->iis_cclk);
+       clk_put(i2s->iis_cclk);
+       kfree(i2s);
+       return 0;
+}
 
 static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops;
 
+static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = {
+{
+       .name = "s3c64xx-i2s-0",
+       .probe = s3c64xx_i2s_probe,
+       .remove = s3c64xx_i2s_remove,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,},
+       .ops = &s3c64xx_i2s_dai_ops,
+       .symmetric_rates = 1,
+}, {
+       .name = "s3c64xx-i2s-1",
+       .probe = s3c64xx_i2s_probe,
+       .remove = s3c64xx_i2s_remove,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = S3C64XX_I2S_RATES,
+               .formats = S3C64XX_I2S_FMTS,},
+       .ops = &s3c64xx_i2s_dai_ops,
+       .symmetric_rates = 1,
+},};
+
 static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
 {
+       struct s3c_audio_pdata *i2s_pdata;
        struct s3c_i2sv2_info *i2s;
-       struct snd_soc_dai *dai;
-       int ret;
+       struct resource *res;
+       int i, ret;
 
        if (pdev->id >= MAX_I2SV3) {
                dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
@@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
        }
 
        i2s = &s3c64xx_i2s[pdev->id];
-       dai = &s3c64xx_i2s_dai[pdev->id];
-       dai->dev = &pdev->dev;
-       dai->name = "s3c64xx-i2s";
-       dai->id = pdev->id;
-       dai->symmetric_rates = 1;
-       dai->playback.channels_min = 2;
-       dai->playback.channels_max = 2;
-       dai->playback.rates = S3C64XX_I2S_RATES;
-       dai->playback.formats = S3C64XX_I2S_FMTS;
-       dai->capture.channels_min = 2;
-       dai->capture.channels_max = 2;
-       dai->capture.rates = S3C64XX_I2S_RATES;
-       dai->capture.formats = S3C64XX_I2S_FMTS;
-       dai->probe = s3c64xx_i2s_probe;
-       dai->ops = &s3c64xx_i2s_dai_ops;
-
-       i2s->feature |= S3C_FEATURE_CDCLKCON;
 
        i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
        i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
 
-       if (pdev->id == 0) {
-               i2s->dma_capture->channel = DMACH_I2S0_IN;
-               i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD;
-               i2s->dma_playback->channel = DMACH_I2S0_OUT;
-               i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD;
-       } else {
-               i2s->dma_capture->channel = DMACH_I2S1_IN;
-               i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD;
-               i2s->dma_playback->channel = DMACH_I2S1_OUT;
-               i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD;
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
+               return -ENXIO;
+       }
+       i2s->dma_playback->channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
+               return -ENXIO;
+       }
+       i2s->dma_capture->channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
+               return -ENXIO;
        }
 
+       if (!request_mem_region(res->start, resource_size(res),
+                               "s3c64xx-i2s")) {
+               dev_err(&pdev->dev, "Unable to request SFR region\n");
+               return -EBUSY;
+       }
+       i2s->base = res->start;
+
+       i2s_pdata = pdev->dev.platform_data;
+       if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
+               dev_err(&pdev->dev, "Unable to configure gpio\n");
+               return -EINVAL;
+       }
+       i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
+       i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
+
        i2s->dma_capture->client = &s3c64xx_dma_client_in;
        i2s->dma_capture->dma_size = 4;
        i2s->dma_playback->client = &s3c64xx_dma_client_out;
        i2s->dma_playback->dma_size = 4;
 
-       i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
-       if (IS_ERR(i2s->iis_cclk)) {
-               dev_err(&pdev->dev, "failed to get audio-bus\n");
-               ret = PTR_ERR(i2s->iis_cclk);
-               goto err;
+       for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) {
+               ret = s3c_i2sv2_register_dai(&pdev->dev, i,
+                                               &s3c64xx_i2s_dai[i]);
+               if (ret != 0)
+                       return ret;
        }
 
-       clk_enable(i2s->iis_cclk);
-
-       ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
-       if (ret)
-               goto err_clk;
-
-       ret = s3c_i2sv2_register_dai(dai);
-       if (ret != 0)
-               goto err_i2sv2;
-
        return 0;
-
-err_i2sv2:
-       /* Not implemented for I2Sv2 core yet */
-err_clk:
-       clk_put(i2s->iis_cclk);
-err:
-       return ret;
 }
 
 static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
 {
-       dev_err(&pdev->dev, "Device removal not yet supported\n");
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai));
        return 0;
 }
 
@@ -188,3 +239,4 @@ module_exit(s3c64xx_i2s_exit);
 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:s3c64xx-iis");
index 7a40f43..de4075d 100644 (file)
@@ -36,7 +36,6 @@ struct clk;
        (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
         SNDRV_PCM_FMTBIT_S24_LE)
 
-extern struct snd_soc_dai s3c64xx_i2s_dai[];
-extern struct snd_soc_dai s3c64xx_i2s_v4_dai;
+struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
 
 #endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
index b480348..dd20ca7 100644 (file)
@@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = {
        {
                .name           = "wm8987",
                .stream_name    = "SmartQ Hi-Fi",
-               .cpu_dai        = &s3c64xx_i2s_dai[0],
-               .codec_dai      = &wm8750_dai,
+               .cpu_dai_name   = "s3c64xx-i2s.0",
+               .codec_dai_name = "wm8750-hifi",
+               .platform_name  = "s3c24xx-pcm-audio",
+               .codec_name     = "wm8750-codec.0-0x1a",
                .init           = smartq_wm8987_init,
                .ops            = &smartq_hifi_ops,
        },
@@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = {
 
 static struct snd_soc_card snd_soc_smartq = {
        .name = "SmartQ",
-       .platform = &s3c24xx_soc_platform,
        .dai_link = smartq_dai,
        .num_links = ARRAY_SIZE(smartq_dai),
 };
 
-static struct snd_soc_device smartq_snd_devdata = {
-       .card = &snd_soc_smartq,
-       .codec_dev = &soc_codec_dev_wm8750,
-};
-
 static struct platform_device *smartq_snd_device;
 
 static int __init smartq_init(void)
@@ -245,8 +241,7 @@ static int __init smartq_init(void)
        if (!smartq_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata);
-       smartq_snd_devdata.dev = &smartq_snd_device->dev;
+       platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);
 
        ret = platform_device_add(smartq_snd_device);
        if (ret) {
index 3622588..4613288 100644 (file)
@@ -19,7 +19,6 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 
-#include "../codecs/ac97.h"
 #include "s3c-dma.h"
 #include "s3c-ac97.h"
 
@@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
 {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM],
-       .codec_dai = &ac97_dai,
+       .cpu_dai_name = "s3c-ac97",
+       .codec_dai_name = "ac97-hifi",
+       .codec_name = "ac97-codec",
+       .platform_name = "s3c24xx-pcm-audio",
 },
 };
 
 static struct snd_soc_card smdk2443 = {
        .name = "SMDK2443",
-       .platform = &s3c24xx_soc_platform,
        .dai_link = smdk2443_dai,
        .num_links = ARRAY_SIZE(smdk2443_dai),
 };
 
-static struct snd_soc_device smdk2443_snd_ac97_devdata = {
-       .card = &smdk2443,
-       .codec_dev = &soc_codec_dev_ac97,
-};
-
 static struct platform_device *smdk2443_snd_ac97_device;
 
 static int __init smdk2443_init(void)
@@ -56,9 +51,7 @@ static int __init smdk2443_init(void)
        if (!smdk2443_snd_ac97_device)
                return -ENOMEM;
 
-       platform_set_drvdata(smdk2443_snd_ac97_device,
-                               &smdk2443_snd_ac97_devdata);
-       smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev;
+       platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443);
        ret = platform_device_add(smdk2443_snd_ac97_device);
 
        if (ret)
index 07e8e51..052e499 100644 (file)
 #include "s3c-dma.h"
 #include "s3c64xx-i2s.h"
 
+/*
+ * Default CFG switch settings to use this driver:
+ *
+ *   SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On
+ */
+
 /* SMDK64XX has a 12MHZ crystal attached to WM8580 */
 #define SMDK64XX_WM8580_FREQ 12000000
 
@@ -29,8 +35,8 @@ static int smdk64xx_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;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        unsigned int pll_out;
        int bfs, rfs, ret;
 
@@ -107,14 +113,13 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       /* Explicitly set WM8580-DAC to source from MCLK */
-       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL,
-                                       WM8580_CLKSRC_MCLK);
+       ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
+                                       SMDK64XX_WM8580_FREQ, pll_out);
        if (ret < 0)
                return ret;
 
-       ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
-                                       SMDK64XX_WM8580_FREQ, pll_out);
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
+                                    pll_out, SND_SOC_CLOCK_IN);
        if (ret < 0)
                return ret;
 
@@ -138,9 +143,9 @@ static struct snd_soc_ops smdk64xx_ops = {
 
 /* SMDK64xx Playback widgets */
 static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
-       SND_SOC_DAPM_HP("Front-L/R", NULL),
-       SND_SOC_DAPM_HP("Center/Sub", NULL),
-       SND_SOC_DAPM_HP("Rear-L/R", NULL),
+       SND_SOC_DAPM_HP("Front", NULL),
+       SND_SOC_DAPM_HP("Center+Sub", NULL),
+       SND_SOC_DAPM_HP("Rear", NULL),
 };
 
 /* SMDK64xx Capture widgets */
@@ -162,20 +167,22 @@ static const struct snd_soc_dapm_route audio_map_tx[] = {
 /* SMDK-PAIFRX connections */
 static const struct snd_soc_dapm_route audio_map_rx[] = {
        /* Front Left/Right are fed VOUT1L/R */
-       {"Front-L/R", NULL, "VOUT1L"},
-       {"Front-L/R", NULL, "VOUT1R"},
+       {"Front", NULL, "VOUT1L"},
+       {"Front", NULL, "VOUT1R"},
 
        /* Center/Sub are fed VOUT2L/R */
-       {"Center/Sub", NULL, "VOUT2L"},
-       {"Center/Sub", NULL, "VOUT2R"},
+       {"Center+Sub", NULL, "VOUT2L"},
+       {"Center+Sub", NULL, "VOUT2R"},
 
        /* Rear Left/Right are fed VOUT3L/R */
-       {"Rear-L/R", NULL, "VOUT3L"},
-       {"Rear-L/R", NULL, "VOUT3R"},
+       {"Rear", NULL, "VOUT3L"},
+       {"Rear", NULL, "VOUT3R"},
 };
 
-static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
+static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        /* Add smdk64xx specific Capture widgets */
        snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
                                  ARRAY_SIZE(wm8580_dapm_widgets_cpt));
@@ -194,8 +201,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
        return 0;
 }
 
-static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec)
+static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        /* Add smdk64xx specific Playback widgets */
        snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
                                  ARRAY_SIZE(wm8580_dapm_widgets_pbk));
@@ -213,33 +222,31 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {
 { /* Primary Playback i/f */
        .name = "WM8580 PAIF RX",
        .stream_name = "Playback",
-       .cpu_dai = &s3c64xx_i2s_v4_dai,
-       .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX],
+       .cpu_dai_name = "s3c64xx-iis-v4",
+       .codec_dai_name = "wm8580-hifi-playback",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8580-codec.0-001b",
        .init = smdk64xx_wm8580_init_paifrx,
        .ops = &smdk64xx_ops,
 },
 { /* Primary Capture i/f */
        .name = "WM8580 PAIF TX",
        .stream_name = "Capture",
-       .cpu_dai = &s3c64xx_i2s_v4_dai,
-       .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX],
+       .cpu_dai_name = "s3c64xx-iis-v4",
+       .codec_dai_name = "wm8580-hifi-capture",
+       .platform_name = "s3c24xx-pcm-audio",
+       .codec_name = "wm8580-codec.0-001b",
        .init = smdk64xx_wm8580_init_paiftx,
        .ops = &smdk64xx_ops,
 },
 };
 
 static struct snd_soc_card smdk64xx = {
-       .name = "smdk64xx",
-       .platform = &s3c24xx_soc_platform,
+       .name = "SMDK64xx 5.1",
        .dai_link = smdk64xx_dai,
        .num_links = ARRAY_SIZE(smdk64xx_dai),
 };
 
-static struct snd_soc_device smdk64xx_snd_devdata = {
-       .card = &smdk64xx,
-       .codec_dev = &soc_codec_dev_wm8580,
-};
-
 static struct platform_device *smdk64xx_snd_device;
 
 static int __init smdk64xx_audio_init(void)
@@ -250,8 +257,7 @@ static int __init smdk64xx_audio_init(void)
        if (!smdk64xx_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata);
-       smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev;
+       platform_set_drvdata(smdk64xx_snd_device, &smdk64xx);
        ret = platform_device_add(smdk64xx_snd_device);
 
        if (ret)
diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c
new file mode 100644 (file)
index 0000000..f31d22a
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * smdk_spdif.c  --  S/PDIF audio for SMDK
+ *
+ * Copyright 2010 Samsung Electronics Co. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+
+#include <plat/devs.h>
+
+#include <sound/soc.h>
+
+#include "s3c-dma.h"
+#include "spdif.h"
+
+/* Audio clock settings are belonged to board specific part. Every
+ * board can set audio source clock setting which is matched with H/W
+ * like this function-'set_audio_clock_heirachy'.
+ */
+static int set_audio_clock_heirachy(struct platform_device *pdev)
+{
+       struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif;
+       int ret;
+
+       fout_epll = clk_get(NULL, "fout_epll");
+       if (IS_ERR(fout_epll)) {
+               printk(KERN_WARNING "%s: Cannot find fout_epll.\n",
+                               __func__);
+               return -EINVAL;
+       }
+
+       mout_epll = clk_get(NULL, "mout_epll");
+       if (IS_ERR(fout_epll)) {
+               printk(KERN_WARNING "%s: Cannot find mout_epll.\n",
+                               __func__);
+               ret = -EINVAL;
+               goto out1;
+       }
+
+       sclk_audio0 = clk_get(&pdev->dev, "sclk_audio");
+       if (IS_ERR(sclk_audio0)) {
+               printk(KERN_WARNING "%s: Cannot find sclk_audio.\n",
+                               __func__);
+               ret = -EINVAL;
+               goto out2;
+       }
+
+       sclk_spdif = clk_get(NULL, "sclk_spdif");
+       if (IS_ERR(fout_epll)) {
+               printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n",
+                               __func__);
+               ret = -EINVAL;
+               goto out3;
+       }
+
+       /* Set audio clock heirachy for S/PDIF */
+       clk_set_parent(mout_epll, fout_epll);
+       clk_set_parent(sclk_audio0, mout_epll);
+       clk_set_parent(sclk_spdif, sclk_audio0);
+
+       clk_put(sclk_spdif);
+out3:
+       clk_put(sclk_audio0);
+out2:
+       clk_put(mout_epll);
+out1:
+       clk_put(fout_epll);
+
+       return ret;
+}
+
+/* We should haved to set clock directly on this part because of clock
+ * scheme of Samsudng SoCs did not support to set rates from abstrct
+ * clock of it's heirachy.
+ */
+static int set_audio_clock_rate(unsigned long epll_rate,
+                               unsigned long audio_rate)
+{
+       struct clk *fout_epll, *sclk_spdif;
+
+       fout_epll = clk_get(NULL, "fout_epll");
+       if (IS_ERR(fout_epll)) {
+               printk(KERN_ERR "%s: failed to get fout_epll\n", __func__);
+               return -ENOENT;
+       }
+
+       clk_set_rate(fout_epll, epll_rate);
+       clk_put(fout_epll);
+
+       sclk_spdif = clk_get(NULL, "sclk_spdif");
+       if (IS_ERR(sclk_spdif)) {
+               printk(KERN_ERR "%s: failed to get sclk_spdif\n", __func__);
+               return -ENOENT;
+       }
+
+       clk_set_rate(sclk_spdif, audio_rate);
+       clk_put(sclk_spdif);
+
+       return 0;
+}
+
+static int smdk_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->cpu_dai;
+       unsigned long pll_out, rclk_rate;
+       int ret, ratio;
+
+       switch (params_rate(params)) {
+       case 44100:
+               pll_out = 45158400;
+               break;
+       case 32000:
+       case 48000:
+       case 96000:
+               pll_out = 49152000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Setting ratio to 512fs helps to use S/PDIF with HDMI without
+        * modify S/PDIF ASoC machine driver.
+        */
+       ratio = 512;
+       rclk_rate = params_rate(params) * ratio;
+
+       /* Set audio source clock rates */
+       ret = set_audio_clock_rate(pll_out, rclk_rate);
+       if (ret < 0)
+               return ret;
+
+       /* Set S/PDIF uses internal source clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
+                                       rclk_rate, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       return ret;
+}
+
+static struct snd_soc_ops smdk_spdif_ops = {
+       .hw_params = smdk_hw_params,
+};
+
+static struct snd_soc_card smdk;
+
+static struct snd_soc_dai_link smdk_dai = {
+       .name = "S/PDIF",
+       .stream_name = "S/PDIF PCM Playback",
+       .platform_name = "s3c24xx-pcm-audio",
+       .cpu_dai_name = "samsung-spdif",
+       .codec_dai_name = "dit-hifi",
+       .codec_name = "spdif-dit",
+       .ops = &smdk_spdif_ops,
+};
+
+static struct snd_soc_card smdk = {
+       .name = "SMDK-S/PDIF",
+       .dai_link = &smdk_dai,
+       .num_links = 1,
+};
+
+static struct platform_device *smdk_snd_spdif_dit_device;
+static struct platform_device *smdk_snd_spdif_device;
+
+static int __init smdk_init(void)
+{
+       int ret;
+
+       smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
+       if (!smdk_snd_spdif_dit_device)
+               return -ENOMEM;
+
+       ret = platform_device_add(smdk_snd_spdif_dit_device);
+       if (ret)
+               goto err2;
+
+       smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1);
+       if (!smdk_snd_spdif_device) {
+               ret = -ENOMEM;
+               goto err2;
+       }
+
+       platform_set_drvdata(smdk_snd_spdif_device, &smdk);
+
+       ret = platform_device_add(smdk_snd_spdif_device);
+       if (ret)
+               goto err1;
+
+       /* Set audio clock heirachy manually */
+       ret = set_audio_clock_heirachy(smdk_snd_spdif_device);
+       if (ret)
+               goto err1;
+
+       return 0;
+err1:
+       platform_device_put(smdk_snd_spdif_device);
+err2:
+       platform_device_put(smdk_snd_spdif_dit_device);
+       return ret;
+}
+
+static void __exit smdk_exit(void)
+{
+       platform_device_unregister(smdk_snd_spdif_device);
+}
+
+module_init(smdk_init);
+module_exit(smdk_exit);
+
+MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
+MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF");
+MODULE_LICENSE("GPL");
index 5527b9e..33ba8fd 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/device.h>
 #include <sound/soc.h>
 
-#include "../codecs/wm9713.h"
 #include "s3c-dma.h"
 #include "s3c-ac97.h"
 
@@ -46,46 +45,57 @@ static struct snd_soc_card smdk;
 static struct snd_soc_dai_link smdk_dai = {
        .name = "AC97",
        .stream_name = "AC97 PCM",
-       .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM],
-       .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
+       .platform_name = "s3c24xx-pcm-audio",
+       .cpu_dai_name = "s3c-ac97",
+       .codec_dai_name = "wm9713-hifi",
+       .codec_name = "wm9713-codec",
 };
 
 static struct snd_soc_card smdk = {
-       .name = "SMDK",
-       .platform = &s3c24xx_soc_platform,
+       .name = "SMDK WM9713",
        .dai_link = &smdk_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device smdk_snd_ac97_devdata = {
-       .card = &smdk,
-       .codec_dev = &soc_codec_dev_wm9713,
-};
-
+static struct platform_device *smdk_snd_wm9713_device;
 static struct platform_device *smdk_snd_ac97_device;
 
 static int __init smdk_init(void)
 {
        int ret;
 
-       smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1);
-       if (!smdk_snd_ac97_device)
+       smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1);
+       if (!smdk_snd_wm9713_device)
                return -ENOMEM;
 
-       platform_set_drvdata(smdk_snd_ac97_device,
-                            &smdk_snd_ac97_devdata);
-       smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev;
+       ret = platform_device_add(smdk_snd_wm9713_device);
+       if (ret)
+               goto err;
+
+       smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1);
+       if (!smdk_snd_ac97_device) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       platform_set_drvdata(smdk_snd_ac97_device, &smdk);
 
        ret = platform_device_add(smdk_snd_ac97_device);
-       if (ret)
+       if (ret) {
                platform_device_put(smdk_snd_ac97_device);
+               goto err;
+       }
 
+       return 0;
+err:
+       platform_device_put(smdk_snd_wm9713_device);
        return ret;
 }
 
 static void __exit smdk_exit(void)
 {
        platform_device_unregister(smdk_snd_ac97_device);
+       platform_device_unregister(smdk_snd_wm9713_device);
 }
 
 module_init(smdk_init);
diff --git a/sound/soc/s3c24xx/spdif.c b/sound/soc/s3c24xx/spdif.c
new file mode 100644 (file)
index 0000000..ce554e9
--- /dev/null
@@ -0,0 +1,501 @@
+/* sound/soc/s3c24xx/spdif.c
+ *
+ * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <plat/audio.h>
+#include <mach/dma.h>
+
+#include "s3c-dma.h"
+#include "spdif.h"
+
+/* Registers */
+#define CLKCON                         0x00
+#define CON                            0x04
+#define BSTAS                          0x08
+#define CSTAS                          0x0C
+#define DATA_OUTBUF                    0x10
+#define DCNT                           0x14
+#define BSTAS_S                                0x18
+#define DCNT_S                         0x1C
+
+#define CLKCTL_MASK                    0x7
+#define CLKCTL_MCLK_EXT                        (0x1 << 2)
+#define CLKCTL_PWR_ON                  (0x1 << 0)
+
+#define CON_MASK                       0x3ffffff
+#define CON_FIFO_TH_SHIFT              19
+#define CON_FIFO_TH_MASK               (0x7 << 19)
+#define CON_USERDATA_23RDBIT           (0x1 << 12)
+
+#define CON_SW_RESET                   (0x1 << 5)
+
+#define CON_MCLKDIV_MASK               (0x3 << 3)
+#define CON_MCLKDIV_256FS              (0x0 << 3)
+#define CON_MCLKDIV_384FS              (0x1 << 3)
+#define CON_MCLKDIV_512FS              (0x2 << 3)
+
+#define CON_PCM_MASK                   (0x3 << 1)
+#define CON_PCM_16BIT                  (0x0 << 1)
+#define CON_PCM_20BIT                  (0x1 << 1)
+#define CON_PCM_24BIT                  (0x2 << 1)
+
+#define CON_PCM_DATA                   (0x1 << 0)
+
+#define CSTAS_MASK                     0x3fffffff
+#define CSTAS_SAMP_FREQ_MASK           (0xF << 24)
+#define CSTAS_SAMP_FREQ_44             (0x0 << 24)
+#define CSTAS_SAMP_FREQ_48             (0x2 << 24)
+#define CSTAS_SAMP_FREQ_32             (0x3 << 24)
+#define CSTAS_SAMP_FREQ_96             (0xA << 24)
+
+#define CSTAS_CATEGORY_MASK            (0xFF << 8)
+#define CSTAS_CATEGORY_CODE_CDP                (0x01 << 8)
+
+#define CSTAS_NO_COPYRIGHT             (0x1 << 2)
+
+/**
+ * struct samsung_spdif_info - Samsung S/PDIF Controller information
+ * @lock: Spin lock for S/PDIF.
+ * @dev: The parent device passed to use from the probe.
+ * @regs: The pointer to the device register block.
+ * @clk_rate: Current clock rate for calcurate ratio.
+ * @pclk: The peri-clock pointer for spdif master operation.
+ * @sclk: The source clock pointer for making sync signals.
+ * @save_clkcon: Backup clkcon reg. in suspend.
+ * @save_con: Backup con reg. in suspend.
+ * @save_cstas: Backup cstas reg. in suspend.
+ * @dma_playback: DMA information for playback channel.
+ */
+struct samsung_spdif_info {
+       spinlock_t      lock;
+       struct device   *dev;
+       void __iomem    *regs;
+       unsigned long   clk_rate;
+       struct clk      *pclk;
+       struct clk      *sclk;
+       u32             saved_clkcon;
+       u32             saved_con;
+       u32             saved_cstas;
+       struct s3c_dma_params   *dma_playback;
+};
+
+static struct s3c2410_dma_client spdif_dma_client_out = {
+       .name           = "S/PDIF Stereo out",
+};
+
+static struct s3c_dma_params spdif_stereo_out;
+static struct samsung_spdif_info spdif_info;
+
+static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
+{
+       return snd_soc_dai_get_drvdata(cpu_dai);
+}
+
+static void spdif_snd_txctrl(struct samsung_spdif_info *spdif, int on)
+{
+       void __iomem *regs = spdif->regs;
+       u32 clkcon;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
+       if (on)
+               writel(clkcon | CLKCTL_PWR_ON, regs + CLKCON);
+       else
+               writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
+}
+
+static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai,
+                               int clk_id, unsigned int freq, int dir)
+{
+       struct samsung_spdif_info *spdif = to_info(cpu_dai);
+       u32 clkcon;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       clkcon = readl(spdif->regs + CLKCON);
+
+       if (clk_id == SND_SOC_SPDIF_INT_MCLK)
+               clkcon &= ~CLKCTL_MCLK_EXT;
+       else
+               clkcon |= CLKCTL_MCLK_EXT;
+
+       writel(clkcon, spdif->regs + CLKCON);
+
+       spdif->clk_rate = freq;
+
+       return 0;
+}
+
+static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
+                               struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
+       unsigned long flags;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               spin_lock_irqsave(&spdif->lock, flags);
+               spdif_snd_txctrl(spdif, 1);
+               spin_unlock_irqrestore(&spdif->lock, flags);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               spin_lock_irqsave(&spdif->lock, flags);
+               spdif_snd_txctrl(spdif, 0);
+               spin_unlock_irqrestore(&spdif->lock, flags);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int spdif_sysclk_ratios[] = {
+       512, 384, 256,
+};
+
+static int spdif_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *socdai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
+       void __iomem *regs = spdif->regs;
+       struct s3c_dma_params *dma_data;
+       u32 con, clkcon, cstas;
+       unsigned long flags;
+       int i, ratio;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               dma_data = spdif->dma_playback;
+       else {
+               dev_err(spdif->dev, "Capture is not supported\n");
+               return -EINVAL;
+       }
+
+       snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
+
+       spin_lock_irqsave(&spdif->lock, flags);
+
+       con = readl(regs + CON) & CON_MASK;
+       cstas = readl(regs + CSTAS) & CSTAS_MASK;
+       clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
+
+       con &= ~CON_FIFO_TH_MASK;
+       con |= (0x7 << CON_FIFO_TH_SHIFT);
+       con |= CON_USERDATA_23RDBIT;
+       con |= CON_PCM_DATA;
+
+       con &= ~CON_PCM_MASK;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               con |= CON_PCM_16BIT;
+               break;
+       default:
+               dev_err(spdif->dev, "Unsupported data size.\n");
+               goto err;
+       }
+
+       ratio = spdif->clk_rate / params_rate(params);
+       for (i = 0; i < ARRAY_SIZE(spdif_sysclk_ratios); i++)
+               if (ratio == spdif_sysclk_ratios[i])
+                       break;
+       if (i == ARRAY_SIZE(spdif_sysclk_ratios)) {
+               dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n",
+                               spdif->clk_rate, params_rate(params));
+               goto err;
+       }
+
+       con &= ~CON_MCLKDIV_MASK;
+       switch (ratio) {
+       case 256:
+               con |= CON_MCLKDIV_256FS;
+               break;
+       case 384:
+               con |= CON_MCLKDIV_384FS;
+               break;
+       case 512:
+               con |= CON_MCLKDIV_512FS;
+               break;
+       }
+
+       cstas &= ~CSTAS_SAMP_FREQ_MASK;
+       switch (params_rate(params)) {
+       case 44100:
+               cstas |= CSTAS_SAMP_FREQ_44;
+               break;
+       case 48000:
+               cstas |= CSTAS_SAMP_FREQ_48;
+               break;
+       case 32000:
+               cstas |= CSTAS_SAMP_FREQ_32;
+               break;
+       case 96000:
+               cstas |= CSTAS_SAMP_FREQ_96;
+               break;
+       default:
+               dev_err(spdif->dev, "Invalid sampling rate %d\n",
+                               params_rate(params));
+               goto err;
+       }
+
+       cstas &= ~CSTAS_CATEGORY_MASK;
+       cstas |= CSTAS_CATEGORY_CODE_CDP;
+       cstas |= CSTAS_NO_COPYRIGHT;
+
+       writel(con, regs + CON);
+       writel(cstas, regs + CSTAS);
+       writel(clkcon, regs + CLKCON);
+
+       spin_unlock_irqrestore(&spdif->lock, flags);
+
+       return 0;
+err:
+       spin_unlock_irqrestore(&spdif->lock, flags);
+       return -EINVAL;
+}
+
+static void spdif_shutdown(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
+       void __iomem *regs = spdif->regs;
+       u32 con, clkcon;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       con = readl(regs + CON) & CON_MASK;
+       clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
+
+       writel(con | CON_SW_RESET, regs + CON);
+       cpu_relax();
+
+       writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
+}
+
+#ifdef CONFIG_PM
+static int spdif_suspend(struct snd_soc_dai *cpu_dai)
+{
+       struct samsung_spdif_info *spdif = to_info(cpu_dai);
+       u32 con = spdif->saved_con;
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       spdif->saved_clkcon = readl(spdif->regs + CLKCON) & CLKCTL_MASK;
+       spdif->saved_con = readl(spdif->regs + CON) & CON_MASK;
+       spdif->saved_cstas = readl(spdif->regs + CSTAS) & CSTAS_MASK;
+
+       writel(con | CON_SW_RESET, spdif->regs + CON);
+       cpu_relax();
+
+       return 0;
+}
+
+static int spdif_resume(struct snd_soc_dai *cpu_dai)
+{
+       struct samsung_spdif_info *spdif = to_info(cpu_dai);
+
+       dev_dbg(spdif->dev, "Entered %s\n", __func__);
+
+       writel(spdif->saved_clkcon, spdif->regs + CLKCON);
+       writel(spdif->saved_con, spdif->regs + CON);
+       writel(spdif->saved_cstas, spdif->regs + CSTAS);
+
+       return 0;
+}
+#else
+#define spdif_suspend NULL
+#define spdif_resume NULL
+#endif
+
+static struct snd_soc_dai_ops spdif_dai_ops = {
+       .set_sysclk     = spdif_set_sysclk,
+       .trigger        = spdif_trigger,
+       .hw_params      = spdif_hw_params,
+       .shutdown       = spdif_shutdown,
+};
+
+struct snd_soc_dai_driver samsung_spdif_dai = {
+       .name = "samsung-spdif",
+       .playback = {
+               .stream_name = "S/PDIF Playback",
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = (SNDRV_PCM_RATE_32000 |
+                               SNDRV_PCM_RATE_44100 |
+                               SNDRV_PCM_RATE_48000 |
+                               SNDRV_PCM_RATE_96000),
+               .formats = SNDRV_PCM_FMTBIT_S16_LE, },
+       .ops = &spdif_dai_ops,
+       .suspend = spdif_suspend,
+       .resume = spdif_resume,
+};
+
+static __devinit int spdif_probe(struct platform_device *pdev)
+{
+       struct s3c_audio_pdata *spdif_pdata;
+       struct resource *mem_res, *dma_res;
+       struct samsung_spdif_info *spdif;
+       int ret;
+
+       spdif_pdata = pdev->dev.platform_data;
+
+       dev_dbg(&pdev->dev, "Entered %s\n", __func__);
+
+       dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!dma_res) {
+               dev_err(&pdev->dev, "Unable to get dma resource.\n");
+               return -ENXIO;
+       }
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem_res) {
+               dev_err(&pdev->dev, "Unable to get register resource.\n");
+               return -ENXIO;
+       }
+
+       if (spdif_pdata && spdif_pdata->cfg_gpio
+                       && spdif_pdata->cfg_gpio(pdev)) {
+               dev_err(&pdev->dev, "Unable to configure GPIO pins\n");
+               return -EINVAL;
+       }
+
+       spdif = &spdif_info;
+       spdif->dev = &pdev->dev;
+
+       spin_lock_init(&spdif->lock);
+
+       spdif->pclk = clk_get(&pdev->dev, "spdif");
+       if (IS_ERR(spdif->pclk)) {
+               dev_err(&pdev->dev, "failed to get peri-clock\n");
+               ret = -ENOENT;
+               goto err0;
+       }
+       clk_enable(spdif->pclk);
+
+       spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
+       if (IS_ERR(spdif->sclk)) {
+               dev_err(&pdev->dev, "failed to get internal source clock\n");
+               ret = -ENOENT;
+               goto err1;
+       }
+       clk_enable(spdif->sclk);
+
+       /* Request S/PDIF Register's memory region */
+       if (!request_mem_region(mem_res->start,
+                               resource_size(mem_res), "samsung-spdif")) {
+               dev_err(&pdev->dev, "Unable to request register region\n");
+               ret = -EBUSY;
+               goto err2;
+       }
+
+       spdif->regs = ioremap(mem_res->start, 0x100);
+       if (spdif->regs == NULL) {
+               dev_err(&pdev->dev, "Cannot ioremap registers\n");
+               ret = -ENXIO;
+               goto err3;
+       }
+
+       dev_set_drvdata(&pdev->dev, spdif);
+
+       ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "fail to register dai\n");
+               goto err4;
+       }
+
+       spdif_stereo_out.dma_size = 2;
+       spdif_stereo_out.client = &spdif_dma_client_out;
+       spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
+       spdif_stereo_out.channel = dma_res->start;
+
+       spdif->dma_playback = &spdif_stereo_out;
+
+       return 0;
+
+err4:
+       iounmap(spdif->regs);
+err3:
+       release_mem_region(mem_res->start, resource_size(mem_res));
+err2:
+       clk_disable(spdif->sclk);
+       clk_put(spdif->sclk);
+err1:
+       clk_disable(spdif->pclk);
+       clk_put(spdif->pclk);
+err0:
+       return ret;
+}
+
+static __devexit int spdif_remove(struct platform_device *pdev)
+{
+       struct samsung_spdif_info *spdif = &spdif_info;
+       struct resource *mem_res;
+
+       snd_soc_unregister_dai(&pdev->dev);
+
+       iounmap(spdif->regs);
+
+       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (mem_res)
+               release_mem_region(mem_res->start, resource_size(mem_res));
+
+       clk_disable(spdif->sclk);
+       clk_put(spdif->sclk);
+       clk_disable(spdif->pclk);
+       clk_put(spdif->pclk);
+
+       return 0;
+}
+
+static struct platform_driver samsung_spdif_driver = {
+       .probe  = spdif_probe,
+       .remove = spdif_remove,
+       .driver = {
+               .name   = "samsung-spdif",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init spdif_init(void)
+{
+       return platform_driver_register(&samsung_spdif_driver);
+}
+module_init(spdif_init);
+
+static void __exit spdif_exit(void)
+{
+       platform_driver_unregister(&samsung_spdif_driver);
+}
+module_exit(spdif_exit);
+
+MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
+MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-spdif");
diff --git a/sound/soc/s3c24xx/spdif.h b/sound/soc/s3c24xx/spdif.h
new file mode 100644 (file)
index 0000000..3ed5559
--- /dev/null
@@ -0,0 +1,19 @@
+/* sound/soc/s3c24xx/spdif.h
+ *
+ * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SND_SOC_SAMSUNG_SPDIF_H
+#define __SND_SOC_SAMSUNG_SPDIF_H      __FILE__
+
+#define SND_SOC_SPDIF_INT_MCLK         0
+#define SND_SOC_SPDIF_EXT_MCLK         1
+
+#endif /* __SND_SOC_SAMSUNG_SPDIF_H */
index 59e3fa7..8778faa 100644 (file)
@@ -140,7 +140,7 @@ static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
 static void s6000_i2s_start(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        int channel;
 
        channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -152,7 +152,7 @@ static void s6000_i2s_start(struct snd_pcm_substream *substream)
 static void s6000_i2s_stop(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
        int channel;
 
        channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -194,7 +194,7 @@ static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
 
 static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
 {
-       struct s6000_i2s_dev *dev = cpu_dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int errors;
        unsigned int ret;
 
@@ -232,7 +232,7 @@ static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
 static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                                   unsigned int fmt)
 {
-       struct s6000_i2s_dev *dev = cpu_dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        u32 w;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -273,7 +273,7 @@ static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 
 static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
 {
-       struct s6000_i2s_dev *dev = dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
 
        if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
                return -EINVAL;
@@ -287,7 +287,7 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *params,
                               struct snd_soc_dai *dai)
 {
-       struct s6000_i2s_dev *dev = dai->private_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
        int interf;
        u32 w = 0;
 
@@ -326,15 +326,17 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int s6000_i2s_dai_probe(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
 {
-       struct s6000_i2s_dev *dev = dai->private_data;
-       struct s6000_snd_platform_data *pdata = pdev->dev.platform_data;
+       struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
+       struct s6000_snd_platform_data *pdata = dai->dev->platform_data;
 
        if (!pdata)
                return -EINVAL;
 
+       dai->capture_dma_data = &dev->dma_params;
+       dai->playback_dma_data = &dev->dma_params;
+
        dev->wide = pdata->wide;
        dev->channel_in = pdata->channel_in;
        dev->channel_out = pdata->channel_out;
@@ -352,10 +354,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,
 
                dev->channel_in = 0;
                dev->channel_out = 1;
-               dai->capture.channels_min = 2 * dev->lines_in;
-               dai->capture.channels_max = dai->capture.channels_min;
-               dai->playback.channels_min = 2 * dev->lines_out;
-               dai->playback.channels_max = dai->playback.channels_min;
+               dai->driver->capture.channels_min = 2 * dev->lines_in;
+               dai->driver->capture.channels_max = dai->driver->capture.channels_min;
+               dai->driver->playback.channels_min = 2 * dev->lines_out;
+               dai->driver->playback.channels_max = dai->driver->playback.channels_min;
 
                for (i = 0; i < dev->lines_out; i++)
                        s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
@@ -372,10 +374,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,
                if (dev->lines_in > 1 || dev->lines_out > 1)
                        return -EINVAL;
 
-               dai->capture.channels_min = 2 * dev->lines_in;
-               dai->capture.channels_max = 8 * dev->lines_in;
-               dai->playback.channels_min = 2 * dev->lines_out;
-               dai->playback.channels_max = 8 * dev->lines_out;
+               dai->driver->capture.channels_min = 2 * dev->lines_in;
+               dai->driver->capture.channels_max = 8 * dev->lines_in;
+               dai->driver->playback.channels_min = 2 * dev->lines_out;
+               dai->driver->playback.channels_max = 8 * dev->lines_out;
 
                if (dev->lines_in)
                        cfg[dev->channel_in] = S6_I2S_IN;
@@ -413,9 +415,7 @@ static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
        .hw_params = s6000_i2s_hw_params,
 };
 
-struct snd_soc_dai s6000_i2s_dai = {
-       .name = "s6000-i2s",
-       .id = 0,
+static struct snd_soc_dai_driver s6000_i2s_dai = {
        .probe = s6000_i2s_dai_probe,
        .playback = {
                .channels_min = 2,
@@ -435,7 +435,6 @@ struct snd_soc_dai s6000_i2s_dai = {
        },
        .ops = &s6000_i2s_dai_ops,
 }
-EXPORT_SYMBOL_GPL(s6000_i2s_dai);
 
 static int __devinit s6000_i2s_probe(struct platform_device *pdev)
 {
@@ -513,11 +512,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
                ret = -ENOMEM;
                goto err_release_dma2;
        }
-
-       s6000_i2s_dai.dev = &pdev->dev;
-       s6000_i2s_dai.private_data = dev;
-       s6000_i2s_dai.capture.dma_data = &dev->dma_params;
-       s6000_i2s_dai.playback.dma_data = &dev->dma_params;
+       dev_set_drvdata(&pdev->dev, dev);
 
        dev->sifbase = sifmem->start;
        dev->scbbase = mmio;
@@ -548,7 +543,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
                         S6_I2S_INT_UNDERRUN |
                         S6_I2S_INT_OVERRUN);
 
-       ret = snd_soc_register_dai(&s6000_i2s_dai);
+       ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai);
        if (ret)
                goto err_release_dev;
 
@@ -573,17 +568,16 @@ err_release_none:
 
 static void __devexit s6000_i2s_remove(struct platform_device *pdev)
 {
-       struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data;
+       struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
        struct resource *region;
        void __iomem *mmio = dev->scbbase;
 
-       snd_soc_unregister_dai(&s6000_i2s_dai);
+       snd_soc_unregister_dai(&pdev->dev);
 
        s6000_i2s_stop_channel(dev, 0);
        s6000_i2s_stop_channel(dev, 1);
 
        s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
-       s6000_i2s_dai.private_data = 0;
        kfree(dev);
 
        region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
index 2375fdf..86aa192 100644 (file)
@@ -12,8 +12,6 @@
 #ifndef _S6000_I2S_H
 #define _S6000_I2S_H
 
-extern struct snd_soc_dai s6000_i2s_dai;
-
 struct s6000_snd_platform_data {
        int lines_in;
        int lines_out;
index 9c7f7f0..271fd22 100644 (file)
@@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        dma_addr_t dma_pos;
        dma_addr_t src, dst;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        period_size = snd_pcm_lib_period_bytes(substream);
        dma_offset = prtd->period * period_size;
@@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
 {
        struct snd_pcm *pcm = data;
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
-       struct s6000_pcm_dma_params *params =
-               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
        struct s6000_runtime_data *prtd;
        unsigned int has_xrun;
        int i, ret = IRQ_NONE;
-       u32 channel[2] = {
-               [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out,
-               [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in
-       };
-
-       has_xrun = params->check_xrun(runtime->dai->cpu_dai);
 
-       for (i = 0; i < ARRAY_SIZE(channel); ++i) {
+       for (i = 0; i < 2; ++i) {
                struct snd_pcm_substream *substream = pcm->streams[i].substream;
+               struct s6000_pcm_dma_params *params =
+                                       snd_soc_dai_get_dma_data(runtime->cpu_dai, substream);
+               u32 channel;
                unsigned int pending;
 
-               if (!channel[i])
+               if (substream == SNDRV_PCM_STREAM_PLAYBACK)
+                       channel = params->dma_out;
+               else
+                       channel = params->dma_in;
+
+               has_xrun = params->check_xrun(runtime->cpu_dai);
+
+               if (!channel)
                        continue;
 
                if (unlikely(has_xrun & (1 << i)) &&
@@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
                        ret = IRQ_HANDLED;
                }
 
-               pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]),
-                                            DMA_INDEX_CHNL(channel[i]));
+               pending = s6dmac_int_sources(DMA_MASK_DMAC(channel),
+                                            DMA_INDEX_CHNL(channel));
 
                if (pending & 1) {
                        ret = IRQ_HANDLED;
@@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
                                   snd_pcm_running(substream))) {
                                snd_pcm_period_elapsed(substream);
                                dev_dbg(pcm->dev, "period elapsed %x %x\n",
-                                      s6dmac_cur_src(DMA_MASK_DMAC(channel[i]),
-                                                  DMA_INDEX_CHNL(channel[i])),
-                                      s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]),
-                                                  DMA_INDEX_CHNL(channel[i])));
+                                      s6dmac_cur_src(DMA_MASK_DMAC(channel),
+                                                  DMA_INDEX_CHNL(channel)),
+                                      s6dmac_cur_dst(DMA_MASK_DMAC(channel),
+                                                  DMA_INDEX_CHNL(channel)));
                                prtd = substream->runtime->private_data;
                                spin_lock(&prtd->lock);
                                s6000_pcm_enqueue_dma(substream);
@@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
                        if (pending & (1 << 3))
                                printk(KERN_WARNING
                                       "s6000-pcm: DMA %x Underflow\n",
-                                      channel[i]);
+                                      channel);
                        if (pending & (1 << 4))
                                printk(KERN_WARNING
                                       "s6000-pcm: DMA %x Overflow\n",
-                                      channel[i]);
+                                      channel);
                        if (pending & 0x1e0)
                                printk(KERN_WARNING
                                       "s6000-pcm: DMA %x Master Error "
                                       "(mask %x)\n",
-                                      channel[i], pending >> 5);
+                                      channel, pending >> 5);
 
                }
        }
@@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream)
        int srcinc;
        u32 dma;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        spin_lock_irqsave(&prtd->lock, flags);
 
@@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
        unsigned long flags;
        u32 channel;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                channel = par->dma_out;
@@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct s6000_pcm_dma_params *par;
        int ret;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        ret = par->trigger(substream, cmd, 0);
        if (ret < 0)
@@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
        unsigned int offset;
        dma_addr_t count;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        spin_lock_irqsave(&prtd->lock, flags);
 
@@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream)
        struct s6000_runtime_data *prtd;
        int ret;
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
        snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
 
        ret = snd_pcm_hw_constraint_step(runtime, 0,
@@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
                return ret;
        }
 
-       par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        if (par->same_rate) {
                spin_lock(&par->lock);
@@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
        struct s6000_pcm_dma_params *par =
-               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
 
        spin_lock(&par->lock);
        par->in_use &= ~(1 << substream->stream);
@@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_soc_pcm_runtime *runtime = pcm->private_data;
        struct s6000_pcm_dma_params *params =
-               snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+               snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);
 
        free_irq(params->irq, pcm);
        snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card,
        struct s6000_pcm_dma_params *params;
        int res;
 
-       params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
+       params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
+                       pcm->streams[0].substream);
 
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &s6000_pcm_dmamask;
@@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card,
        return 0;
 }
 
-struct snd_soc_platform s6000_soc_platform = {
-       .name =         "s6000-audio",
-       .pcm_ops =      &s6000_pcm_ops,
+static struct snd_soc_platform_driver s6000_soc_platform = {
+       .ops =          &s6000_pcm_ops,
        .pcm_new =      s6000_pcm_new,
        .pcm_free =     s6000_pcm_free,
 };
-EXPORT_SYMBOL_GPL(s6000_soc_platform);
 
-static int __init s6000_pcm_init(void)
+static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
+}
+
+static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver s6000_pcm_driver = {
+       .driver = {
+                       .name = "s6000-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = s6000_soc_platform_probe,
+       .remove = __devexit_p(s6000_soc_platform_remove),
+};
+
+static int __init snd_s6000_pcm_init(void)
 {
-       return snd_soc_register_platform(&s6000_soc_platform);
+       return platform_driver_register(&s6000_pcm_driver);
 }
-module_init(s6000_pcm_init);
+module_init(snd_s6000_pcm_init);
 
-static void __exit s6000_pcm_exit(void)
+static void __exit snd_s6000_pcm_exit(void)
 {
-       snd_soc_unregister_platform(&s6000_soc_platform);
+       platform_driver_unregister(&s6000_pcm_driver);
 }
-module_exit(s6000_pcm_exit);
+module_exit(snd_s6000_pcm_exit);
 
 MODULE_AUTHOR("Daniel Gloeckner");
 MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
index 96f23f6..09d9b88 100644 (file)
@@ -30,6 +30,4 @@ struct s6000_pcm_dma_params {
        int rate;
 };
 
-extern struct snd_soc_platform s6000_soc_platform;
-
 #endif
index c1b40ac..96c05e1 100644 (file)
@@ -32,8 +32,8 @@ static int s6105_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 snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        int ret = 0;
 
        /* set codec DAI configuration */
@@ -134,8 +134,10 @@ static const struct snd_kcontrol_new audio_out_mux = {
 };
 
 /* Logic for a aic3x as connected on the s6105 ip camera ref design */
-static int s6105_aic3x_init(struct snd_soc_codec *codec)
+static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        /* Add s6105 specific widgets */
        snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
                                  ARRAY_SIZE(aic3x_dapm_widgets));
@@ -165,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)
 
        snd_soc_dapm_sync(codec);
 
-       snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec));
+       snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec));
 
        return 0;
 }
@@ -174,8 +176,10 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link s6105_dai = {
        .name = "TLV320AIC31",
        .stream_name = "AIC31",
-       .cpu_dai = &s6000_i2s_dai,
-       .codec_dai = &aic3x_dai,
+       .cpu_dai_name = "s6000-i2s",
+       .codec_dai_name = "tlv320aic3x-hifi",
+       .platform_name = "s6000-pcm-audio",
+       .codec_name = "tlv320aic3x-codec.0-001a",
        .init = s6105_aic3x_init,
        .ops = &s6105_ops,
 };
@@ -183,22 +187,10 @@ static struct snd_soc_dai_link s6105_dai = {
 /* s6105 audio machine driver */
 static struct snd_soc_card snd_soc_card_s6105 = {
        .name = "Stretch IP Camera",
-       .platform = &s6000_soc_platform,
        .dai_link = &s6105_dai,
        .num_links = 1,
 };
 
-/* s6105 audio private data */
-static struct aic3x_setup_data s6105_aic3x_setup = {
-};
-
-/* s6105 audio subsystem */
-static struct snd_soc_device s6105_snd_devdata = {
-       .card = &snd_soc_card_s6105,
-       .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &s6105_aic3x_setup,
-};
-
 static struct s6000_snd_platform_data __initdata s6105_snd_data = {
        .wide           = 0,
        .channel_in     = 0,
@@ -227,8 +219,7 @@ static int __init s6105_init(void)
        if (!s6105_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata);
-       s6105_snd_devdata.dev = &s6105_snd_device->dev;
+       platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);
        platform_device_add_data(s6105_snd_device, &s6105_snd_data,
                                 sizeof(s6105_snd_data));
 
index 52d7e8e..7f0a496 100644 (file)
@@ -47,7 +47,7 @@ config SND_SH7760_AC97
          AC97 unit of the SH7760.
 
 config SND_FSI_AK4642
-       bool "FSI-AK4642 sound support"
+       tristate "FSI-AK4642 sound support"
        depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
        select SND_SOC_AK4642
        help
@@ -55,13 +55,20 @@ config SND_FSI_AK4642
          FSI - AK4642 unit
 
 config SND_FSI_DA7210
-       bool "FSI-DA7210 sound support"
+       tristate "FSI-DA7210 sound support"
        depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
        select SND_SOC_DA7210
        help
          This option enables generic sound support for the
          FSI - DA7210 unit
 
+config SND_FSI_HDMI
+       tristate "FSI-HDMI sound support"
+       depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
+       help
+         This option enables generic sound support for the
+         FSI - HDMI unit
+
 config SND_SIU_MIGOR
        tristate "SIU sound support on Migo-R"
        depends on SH_MIGOR
index 8a5a192..94476d4 100644 (file)
@@ -16,9 +16,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU)        += snd-soc-siu.o
 snd-soc-sh7760-ac97-objs       := sh7760-ac97.o
 snd-soc-fsi-ak4642-objs                := fsi-ak4642.o
 snd-soc-fsi-da7210-objs                := fsi-da7210.o
+snd-soc-fsi-hdmi-objs          := fsi-hdmi.o
 snd-soc-migor-objs             := migor.o
 
 obj-$(CONFIG_SND_SH7760_AC97)  += snd-soc-sh7760-ac97.o
 obj-$(CONFIG_SND_FSI_AK4642)   += snd-soc-fsi-ak4642.o
 obj-$(CONFIG_SND_FSI_DA7210)   += snd-soc-fsi-da7210.o
+obj-$(CONFIG_SND_FSI_HDMI)     += snd-soc-fsi-hdmi.o
 obj-$(CONFIG_SND_SIU_MIGOR)    += snd-soc-migor.o
index 0d8bdf0..c326d29 100644 (file)
@@ -137,7 +137,7 @@ static void camelot_rxdma(void *data)
 static int camelot_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
        int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
        int ret, dmairq;
 
@@ -150,7 +150,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
                ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam);
                if (unlikely(ret)) {
                        pr_debug("audio unit %d irqs already taken!\n",
-                            rtd->dai->cpu_dai->id);
+                            rtd->cpu_dai->id);
                        return -EBUSY;
                }
                (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam);
@@ -159,7 +159,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
                ret = dmabrg_request_irq(dmairq, camelot_txdma, cam);
                if (unlikely(ret)) {
                        pr_debug("audio unit %d irqs already taken!\n",
-                            rtd->dai->cpu_dai->id);
+                            rtd->cpu_dai->id);
                        return -EBUSY;
                }
                (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam);
@@ -170,7 +170,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
 static int camelot_pcm_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
        int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
        int dmairq;
 
@@ -191,7 +191,7 @@ static int camelot_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *hw_params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
        int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
        int ret;
 
@@ -219,7 +219,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
 
        pr_debug("PCM data: addr 0x%08ulx len %d\n",
                 (u32)runtime->dma_addr, runtime->dma_bytes);
@@ -266,7 +266,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)
 static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
        int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
 
        switch (cmd) {
@@ -293,7 +293,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id];
+       struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
        int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
        unsigned long pos;
 
@@ -342,25 +342,44 @@ static int camelot_pcm_new(struct snd_card *card,
        return 0;
 }
 
-struct snd_soc_platform sh7760_soc_platform = {
-       .name           = "sh7760-pcm",
+static struct snd_soc_platform sh7760_soc_platform = {
        .pcm_ops        = &camelot_pcm_ops,
        .pcm_new        = camelot_pcm_new,
        .pcm_free       = camelot_pcm_free,
 };
-EXPORT_SYMBOL_GPL(sh7760_soc_platform);
 
-static int __init sh7760_soc_platform_init(void)
+static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&sh7760_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);
 }
-module_init(sh7760_soc_platform_init);
 
-static void __exit sh7760_soc_platform_exit(void)
+static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&sh7760_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
+}
+
+static struct platform_driver sh7760_pcm_driver = {
+       .driver = {
+                       .name = "sh7760-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = sh7760_soc_platform_probe,
+       .remove = __devexit_p(sh7760_soc_platform_remove),
+};
+
+static int __init snd_sh7760_pcm_init(void)
+{
+       return platform_driver_register(&sh7760_pcm_driver);
+}
+module_init(snd_sh7760_pcm_init);
+
+static void __exit snd_sh7760_pcm_exit(void)
+{
+       platform_driver_unregister(&sh7760_pcm_driver);
 }
-module_exit(sh7760_soc_platform_exit);
+module_exit(snd_sh7760_pcm_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
index dad575a..d96602d 100644 (file)
 
 #include <linux/platform_device.h>
 #include <sound/sh_fsi.h>
-#include <../sound/soc/codecs/ak4642.h>
 
-static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)
+static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_dai *dai = rtd->codec_dai;
        int ret;
 
-       ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM);
+       ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
-       ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0);
+       ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0);
 
        return ret;
 }
@@ -29,24 +29,25 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link fsi_dai_link = {
        .name           = "AK4642",
        .stream_name    = "AK4642",
-       .cpu_dai        = &fsi_soc_dai[FSI_PORT_A],
-       .codec_dai      = &ak4642_dai,
+       .cpu_dai_name   = "fsia-dai", /* fsi A */
+       .codec_dai_name = "ak4642-hifi",
+#ifdef CONFIG_MACH_AP4EVB
+       .platform_name  = "sh_fsi2",
+       .codec_name     = "ak4642-codec.0-0013",
+#else
+       .platform_name  = "sh_fsi.0",
+       .codec_name     = "ak4642-codec.0-0012",
+#endif
        .init           = fsi_ak4642_dai_init,
        .ops            = NULL,
 };
 
 static struct snd_soc_card fsi_soc_card  = {
-       .name           = "FSI",
-       .platform       = &fsi_soc_platform,
+       .name           = "FSI (AK4642)",
        .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,
-};
-
 static struct platform_device *fsi_snd_device;
 
 static int __init fsi_ak4642_init(void)
@@ -57,9 +58,7 @@ static int __init fsi_ak4642_init(void)
        if (!fsi_snd_device)
                goto out;
 
-       platform_set_drvdata(fsi_snd_device,
-                            &fsi_snd_devdata);
-       fsi_snd_devdata.dev = &fsi_snd_device->dev;
+       platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
        ret = platform_device_add(fsi_snd_device);
 
        if (ret)
index 121bbb0..a6adb6e 100644 (file)
 
 #include <linux/platform_device.h>
 #include <sound/sh_fsi.h>
-#include "../codecs/da7210.h"
 
-static int fsi_da7210_init(struct snd_soc_codec *codec)
+static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
 {
-       return snd_soc_dai_set_fmt(&da7210_dai,
+       struct snd_soc_dai *dai = rtd->codec_dai;
+
+       return snd_soc_dai_set_fmt(dai,
                                   SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
                                   SND_SOC_DAIFMT_CBM_CFM);
 }
@@ -24,23 +25,19 @@ static int fsi_da7210_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link fsi_da7210_dai = {
        .name           = "DA7210",
        .stream_name    = "DA7210",
-       .cpu_dai        = &fsi_soc_dai[FSI_PORT_B],
-       .codec_dai      = &da7210_dai,
+       .cpu_dai_name   = "fsib-dai", /* FSI B */
+       .codec_dai_name = "da7210-hifi",
+       .platform_name  = "sh_fsi.0",
+       .codec_name     = "da7210-codec.0-001a",
        .init           = fsi_da7210_init,
 };
 
 static struct snd_soc_card fsi_soc_card = {
-       .name           = "FSI",
-       .platform       = &fsi_soc_platform,
+       .name           = "FSI (DA7210)",
        .dai_link       = &fsi_da7210_dai,
        .num_links      = 1,
 };
 
-static struct snd_soc_device fsi_da7210_snd_devdata = {
-       .card           = &fsi_soc_card,
-       .codec_dev      = &soc_codec_dev_da7210,
-};
-
 static struct platform_device *fsi_da7210_snd_device;
 
 static int __init fsi_da7210_sound_init(void)
@@ -51,8 +48,7 @@ static int __init fsi_da7210_sound_init(void)
        if (!fsi_da7210_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata);
-       fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev;
+       platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
        ret = platform_device_add(fsi_da7210_snd_device);
        if (ret)
                platform_device_put(fsi_da7210_snd_device);
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
new file mode 100644 (file)
index 0000000..a52dd8e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * FSI - HDMI sound support
+ *
+ * Copyright (C) 2010 Renesas Solutions Corp.
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ *
+ * 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 <linux/platform_device.h>
+#include <sound/sh_fsi.h>
+
+static struct snd_soc_dai_link fsi_dai_link = {
+       .name           = "HDMI",
+       .stream_name    = "HDMI",
+       .cpu_dai_name   = "fsib-dai", /* fsi B */
+       .codec_dai_name = "sh_mobile_hdmi-hifi",
+       .platform_name  = "sh_fsi2",
+       .codec_name     = "sh-mobile-hdmi",
+};
+
+static struct snd_soc_card fsi_soc_card  = {
+       .name           = "FSI (SH MOBILE HDMI)",
+       .dai_link       = &fsi_dai_link,
+       .num_links      = 1,
+};
+
+static struct platform_device *fsi_snd_device;
+
+static int __init fsi_hdmi_init(void)
+{
+       int ret = -ENOMEM;
+
+       fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
+       if (!fsi_snd_device)
+               goto out;
+
+       platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
+       ret = platform_device_add(fsi_snd_device);
+
+       if (ret)
+               platform_device_put(fsi_snd_device);
+
+out:
+       return ret;
+}
+
+static void __exit fsi_hdmi_exit(void)
+{
+       platform_device_unregister(fsi_snd_device);
+}
+
+module_init(fsi_hdmi_init);
+module_exit(fsi_hdmi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
index 58c6bec..507e709 100644 (file)
 #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)
+/* IO SHIFT / MACRO */
+#define BI_SHIFT       12
+#define BO_SHIFT       8
+#define AI_SHIFT       4
+#define AO_SHIFT       0
+#define AB_IO(param, shift)    (param << shift)
 
 /* SOFT_RST */
 #define PBSR           (1 << 12) /* Port B Software Reset */
 #define FSISR          (1 <<  0) /* Software Reset */
 
 /* FIFO_SZ */
-#define OUT_SZ_MASK    0x7
-#define BO_SZ_SHIFT    8
-#define AO_SZ_SHIFT    0
+#define FIFO_SZ_MASK   0x7
 
 #define FSI_RATES SNDRV_PCM_RATE_8000_96000
 
 #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
-/************************************************************************
+/*
+ * FSI driver use below type name for variable
+ *
+ * xxx_len     : data length
+ * xxx_width   : data width
+ * xxx_offset  : data offset
+ * xxx_num     : number of data
+ */
+
+/*
+ *             struct
+ */
 
+struct fsi_stream {
+       struct snd_pcm_substream *substream;
 
-               struct
+       int fifo_max_num;
+       int chan_num;
 
+       int buff_offset;
+       int buff_len;
+       int period_len;
+       int period_num;
+};
 
-************************************************************************/
 struct fsi_priv {
        void __iomem *base;
-       struct snd_pcm_substream *substream;
        struct fsi_master *master;
 
-       int fifo_max;
-       int chan;
-
-       int byte_offset;
-       int period_len;
-       int buffer_len;
-       int periods;
+       struct fsi_stream playback;
+       struct fsi_stream capture;
 
        u32 mst_ctrl;
 };
@@ -142,13 +153,10 @@ struct fsi_master {
        spinlock_t lock;
 };
 
-/************************************************************************
-
-
-               basic read write function
-
+/*
+ *             basic read write function
+ */
 
-************************************************************************/
 static void __fsi_reg_write(u32 reg, u32 data)
 {
        /* valid data area is 24bit */
@@ -251,13 +259,10 @@ static void fsi_master_mask_set(struct fsi_master *master,
        spin_unlock_irqrestore(&master->lock, flags);
 }
 
-/************************************************************************
-
-
-               basic function
-
+/*
+ *             basic function
+ */
 
-************************************************************************/
 static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
 {
        return fsi->master;
@@ -271,16 +276,19 @@ static int fsi_is_port_a(struct fsi_priv *fsi)
 static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai_link *machine = rtd->dai;
 
-       return  machine->cpu_dai;
+       return  rtd->cpu_dai;
 }
 
 static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
 {
        struct snd_soc_dai *dai = fsi_get_dai(substream);
+       struct fsi_master *master = snd_soc_dai_get_drvdata(dai);
 
-       return dai->private_data;
+       if (dai->id == 0)
+               return &master->fsia;
+       else
+               return &master->fsib;
 }
 
 static u32 fsi_get_info_flags(struct fsi_priv *fsi)
@@ -292,6 +300,22 @@ static u32 fsi_get_info_flags(struct fsi_priv *fsi)
                master->info->portb_flags;
 }
 
+static inline int fsi_stream_is_play(int stream)
+{
+       return stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
+static inline int fsi_is_play(struct snd_pcm_substream *substream)
+{
+       return fsi_stream_is_play(substream->stream);
+}
+
+static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
+                                               int is_play)
+{
+       return is_play ? &fsi->playback : &fsi->capture;
+}
+
 static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
 {
        u32 mode;
@@ -307,63 +331,144 @@ static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
        return (mode & flags) != mode;
 }
 
-static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
 {
        int is_porta = fsi_is_port_a(fsi);
-       u32 data;
+       u32 shift;
 
        if (is_porta)
-               data = is_play ? (1 << 0) : (1 << 4);
+               shift = is_play ? AO_SHIFT : AI_SHIFT;
        else
-               data = is_play ? (1 << 8) : (1 << 12);
+               shift = is_play ? BO_SHIFT : BI_SHIFT;
 
-       return data;
+       return shift;
 }
 
 static void fsi_stream_push(struct fsi_priv *fsi,
+                           int is_play,
                            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;
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+
+       io->substream   = substream;
+       io->buff_len    = buffer_len;
+       io->buff_offset = 0;
+       io->period_len  = period_len;
+       io->period_num  = 0;
 }
 
-static void fsi_stream_pop(struct fsi_priv *fsi)
+static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
 {
-       fsi->substream          = NULL;
-       fsi->buffer_len         = 0;
-       fsi->period_len         = 0;
-       fsi->byte_offset        = 0;
-       fsi->periods            = 0;
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+
+       io->substream   = NULL;
+       io->buff_len    = 0;
+       io->buff_offset = 0;
+       io->period_len  = 0;
+       io->period_num  = 0;
 }
 
-static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
+static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play)
 {
        u32 status;
        u32 reg = is_play ? DOFF_ST : DIFF_ST;
-       int residue;
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+       int data_num;
 
        status = fsi_reg_read(fsi, reg);
-       residue = 0x1ff & (status >> 8);
-       residue *= fsi->chan;
+       data_num = 0x1ff & (status >> 8);
+       data_num *= io->chan_num;
+
+       return data_num;
+}
+
+static int fsi_len2num(int len, int width)
+{
+       return len / width;
+}
+
+#define fsi_num2offset(a, b) fsi_num2len(a, b)
+static int fsi_num2len(int num, int width)
+{
+       return num * width;
+}
+
+static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play)
+{
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+       struct snd_pcm_substream *substream = io->substream;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       return frames_to_bytes(runtime, 1) / io->chan_num;
+}
+
+/*
+ *             dma function
+ */
+
+static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
+{
+       int is_play = fsi_stream_is_play(stream);
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+
+       return io->substream->runtime->dma_area + io->buff_offset;
+}
+
+static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
+{
+       u16 *start;
+       int i;
+
+       start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+
+       for (i = 0; i < num; i++)
+               fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
+}
+
+static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
+{
+       u16 *start;
+       int i;
 
-       return residue;
+       start  = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+
+
+       for (i = 0; i < num; i++)
+               *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
 }
 
-/************************************************************************
+static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+{
+       u32 *start;
+       int i;
+
+       start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+
+
+       for (i = 0; i < num; i++)
+               fsi_reg_write(fsi, DODT, *(start + i));
+}
 
+static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
+{
+       u32 *start;
+       int i;
 
-               irq function
+       start  = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
 
+       for (i = 0; i < num; i++)
+               *(start + i) = fsi_reg_read(fsi, DIDT);
+}
+
+/*
+ *             irq function
+ */
 
-************************************************************************/
 static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
 {
-       u32 data = fsi_port_ab_io_bit(fsi, is_play);
+       u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
        struct fsi_master *master = fsi_get_master(fsi);
 
        fsi_master_mask_set(master, master->core->imsk,  data, data);
@@ -372,7 +477,7 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
 
 static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
 {
-       u32 data = fsi_port_ab_io_bit(fsi, is_play);
+       u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
        struct fsi_master *master = fsi_get_master(fsi);
 
        fsi_master_mask_set(master, master->core->imsk,  data, 0);
@@ -394,20 +499,18 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
        u32 data = 0;
        struct fsi_master *master = fsi_get_master(fsi);
 
-       data |= fsi_port_ab_io_bit(fsi, 0);
-       data |= fsi_port_ab_io_bit(fsi, 1);
+       data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
+       data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
 
        /* clear interrupt factor */
        fsi_master_mask_set(master, master->core->int_st, data, 0);
 }
 
-/************************************************************************
-
-
-               SPDIF master clock function
-
-These functions are used later FSI2
-************************************************************************/
+/*
+ *             SPDIF master clock function
+ *
+ * These functions are used later FSI2
+ */
 static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
 {
        struct fsi_master *master = fsi_get_master(fsi);
@@ -424,13 +527,10 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
                fsi_master_mask_set(master, fsi->mst_ctrl, val, 0);
 }
 
-/************************************************************************
-
-
-               ctrl function
-
+/*
+ *             ctrl function
+ */
 
-************************************************************************/
 static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
 {
        u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
@@ -447,14 +547,15 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
                          struct snd_soc_dai *dai)
 {
        struct fsi_master *master = fsi_get_master(fsi);
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
        u32 ctrl, shift, i;
 
        /* get on-chip RAM capacity */
        shift = fsi_master_read(master, FIFO_SZ);
-       shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT;
-       shift &= OUT_SZ_MASK;
-       fsi->fifo_max = 256 << shift;
-       dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max);
+       shift >>= fsi_get_port_shift(fsi, is_play);
+       shift &= FIFO_SZ_MASK;
+       io->fifo_max_num = 256 << shift;
+       dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num);
 
        /*
         * The maximum number of sample data varies depending
@@ -475,9 +576,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
         * 7 channels:  32 ( 32 x 7 = 224)
         * 8 channels:  32 ( 32 x 8 = 256)
         */
-       for (i = 1; i < fsi->chan; i <<= 1)
-               fsi->fifo_max >>= 1;
-       dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max);
+       for (i = 1; i < io->chan_num; i <<= 1)
+               io->fifo_max_num >>= 1;
+       dev_dbg(dai->dev, "%d channel %d store\n",
+               io->chan_num, io->fifo_max_num);
 
        ctrl = is_play ? DOFF_CTL : DIFF_CTL;
 
@@ -500,84 +602,114 @@ static void fsi_soft_all_reset(struct fsi_master *master)
        mdelay(10);
 }
 
-/* playback interrupt */
-static int fsi_data_push(struct fsi_priv *fsi, int startup)
+static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int stream)
 {
        struct snd_pcm_runtime *runtime;
        struct snd_pcm_substream *substream = NULL;
-       u32 status;
-       int send;
-       int fifo_free;
-       int width;
-       u8 *start;
-       int i, over_period;
+       int is_play = fsi_stream_is_play(stream);
+       struct fsi_stream *io = fsi_get_stream(fsi, is_play);
+       u32 status_reg = is_play ? DOFF_ST : DIFF_ST;
+       int data_residue_num;
+       int data_num;
+       int data_num_max;
+       int ch_width;
+       int over_period;
+       void (*fn)(struct fsi_priv *fsi, int size);
 
        if (!fsi                        ||
-           !fsi->substream             ||
-           !fsi->substream->runtime)
+           !io->substream              ||
+           !io->substream->runtime)
                return -EINVAL;
 
        over_period     = 0;
-       substream       = fsi->substream;
+       substream       = io->substream;
        runtime         = 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)) {
+       if (io->buff_offset >=
+           fsi_num2offset(io->period_num + 1, io->period_len)) {
 
                over_period = 1;
-               fsi->periods = (fsi->periods + 1) % runtime->periods;
+               io->period_num = (io->period_num + 1) % runtime->periods;
 
-               if (0 == fsi->periods)
-                       fsi->byte_offset = 0;
+               if (0 == io->period_num)
+                       io->buff_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;
+       ch_width = fsi_get_frame_width(fsi, is_play);
+
+       /* get residue data number of alsa */
+       data_residue_num = fsi_len2num(io->buff_len - io->buff_offset,
+                                      ch_width);
+
+       if (is_play) {
+               /*
+                * for play-back
+                *
+                * data_num_max : number of FSI fifo free space
+                * data_num     : number of ALSA residue data
+                */
+               data_num_max  = io->fifo_max_num * io->chan_num;
+               data_num_max -= fsi_get_fifo_data_num(fsi, is_play);
+
+               data_num = data_residue_num;
+
+               switch (ch_width) {
+               case 2:
+                       fn = fsi_dma_soft_push16;
+                       break;
+               case 4:
+                       fn = fsi_dma_soft_push32;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       } else {
+               /*
+                * for capture
+                *
+                * data_num_max : number of ALSA free space
+                * data_num     : number of data in FSI fifo
+                */
+               data_num_max = data_residue_num;
+               data_num     = fsi_get_fifo_data_num(fsi, is_play);
+
+               switch (ch_width) {
+               case 2:
+                       fn = fsi_dma_soft_pop16;
+                       break;
+               case 4:
+                       fn = fsi_dma_soft_pop32;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
 
-       start = runtime->dma_area;
-       start += fsi->byte_offset;
+       data_num = min(data_num, data_num_max);
 
-       switch (width) {
-       case 2:
-               for (i = 0; i < send; i++)
-                       fsi_reg_write(fsi, DODT,
-                                     ((u32)*((u16 *)start + i) << 8));
-               break;
-       case 4:
-               for (i = 0; i < send; i++)
-                       fsi_reg_write(fsi, DODT, *((u32 *)start + i));
-               break;
-       default:
-               return -EINVAL;
-       }
+       fn(fsi, data_num);
 
-       fsi->byte_offset += send * width;
+       /* update buff_offset */
+       io->buff_offset += fsi_num2offset(data_num, ch_width);
 
-       status = fsi_reg_read(fsi, DOFF_ST);
+       /* check fifo status */
        if (!startup) {
                struct snd_soc_dai *dai = fsi_get_dai(substream);
+               u32 status = fsi_reg_read(fsi, status_reg);
 
                if (status & ERR_OVER)
                        dev_err(dai->dev, "over run\n");
                if (status & ERR_UNDER)
                        dev_err(dai->dev, "under run\n");
        }
-       fsi_reg_write(fsi, DOFF_ST, 0);
+       fsi_reg_write(fsi, status_reg, 0);
 
-       fsi_irq_enable(fsi, 1);
+       /* re-enable irq */
+       fsi_irq_enable(fsi, is_play);
 
        if (over_period)
                snd_pcm_period_elapsed(substream);
@@ -587,85 +719,12 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup)
 
 static int fsi_data_pop(struct fsi_priv *fsi, int startup)
 {
-       struct snd_pcm_runtime *runtime;
-       struct snd_pcm_substream *substream = NULL;
-       u32 status;
-       int free;
-       int fifo_fill;
-       int width;
-       u8 *start;
-       int i, over_period;
-
-       if (!fsi                        ||
-           !fsi->substream             ||
-           !fsi->substream->runtime)
-               return -EINVAL;
-
-       over_period     = 0;
-       substream       = fsi->substream;
-       runtime         = 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)) {
-
-               over_period = 1;
-               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 free space for alsa */
-       free = (fsi->buffer_len - fsi->byte_offset) / width;
-
-       /* get recv size */
-       fifo_fill = fsi_get_fifo_residue(fsi, 0);
-
-       if (free < fifo_fill)
-               fifo_fill = free;
-
-       start = runtime->dma_area;
-       start += fsi->byte_offset;
-
-       switch (width) {
-       case 2:
-               for (i = 0; i < fifo_fill; i++)
-                       *((u16 *)start + i) =
-                               (u16)(fsi_reg_read(fsi, DIDT) >> 8);
-               break;
-       case 4:
-               for (i = 0; i < fifo_fill; i++)
-                       *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       fsi->byte_offset += fifo_fill * width;
-
-       status = fsi_reg_read(fsi, DIFF_ST);
-       if (!startup) {
-               struct snd_soc_dai *dai = fsi_get_dai(substream);
-
-               if (status & ERR_OVER)
-                       dev_err(dai->dev, "over run\n");
-               if (status & ERR_UNDER)
-                       dev_err(dai->dev, "under run\n");
-       }
-       fsi_reg_write(fsi, DIFF_ST, 0);
-
-       fsi_irq_enable(fsi, 0);
-
-       if (over_period)
-               snd_pcm_period_elapsed(substream);
+       return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_CAPTURE);
+}
 
-       return 0;
+static int fsi_data_push(struct fsi_priv *fsi, int startup)
+{
+       return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_PLAYBACK);
 }
 
 static irqreturn_t fsi_interrupt(int irq, void *data)
@@ -677,13 +736,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
        fsi_master_mask_set(master, SOFT_RST, IR, 0);
        fsi_master_mask_set(master, SOFT_RST, IR, IR);
 
-       if (int_st & INT_A_OUT)
+       if (int_st & AB_IO(1, AO_SHIFT))
                fsi_data_push(&master->fsia, 0);
-       if (int_st & INT_B_OUT)
+       if (int_st & AB_IO(1, BO_SHIFT))
                fsi_data_push(&master->fsib, 0);
-       if (int_st & INT_A_IN)
+       if (int_st & AB_IO(1, AI_SHIFT))
                fsi_data_pop(&master->fsia, 0);
-       if (int_st & INT_B_IN)
+       if (int_st & AB_IO(1, BI_SHIFT))
                fsi_data_pop(&master->fsib, 0);
 
        fsi_irq_clear_all_status(master);
@@ -691,25 +750,24 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-/************************************************************************
-
-
-               dai ops
-
+/*
+ *             dai ops
+ */
 
-************************************************************************/
 static int fsi_dai_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       u32 flags = fsi_get_info_flags(fsi);
        struct fsi_master *master = fsi_get_master(fsi);
+       struct fsi_stream *io;
+       u32 flags = fsi_get_info_flags(fsi);
        u32 fmt;
        u32 reg;
        u32 data;
-       int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int is_play = fsi_is_play(substream);
        int is_master;
-       int ret = 0;
+
+       io = fsi_get_stream(fsi, is_play);
 
        pm_runtime_get_sync(dai->dev);
 
@@ -741,29 +799,29 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
        switch (fmt) {
        case SH_FSI_FMT_MONO:
                data = CR_MONO;
-               fsi->chan = 1;
+               io->chan_num = 1;
                break;
        case SH_FSI_FMT_MONO_DELAY:
                data = CR_MONO_D;
-               fsi->chan = 1;
+               io->chan_num = 1;
                break;
        case SH_FSI_FMT_PCM:
                data = CR_PCM;
-               fsi->chan = 2;
+               io->chan_num = 2;
                break;
        case SH_FSI_FMT_I2S:
                data = CR_I2S;
-               fsi->chan = 2;
+               io->chan_num = 2;
                break;
        case SH_FSI_FMT_TDM:
-               fsi->chan = is_play ?
+               io->chan_num = is_play ?
                        SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-               data = CR_TDM | (fsi->chan - 1);
+               data = CR_TDM | (io->chan_num - 1);
                break;
        case SH_FSI_FMT_TDM_DELAY:
-               fsi->chan = is_play ?
+               io->chan_num = is_play ?
                        SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-               data = CR_TDM_D | (fsi->chan - 1);
+               data = CR_TDM_D | (io->chan_num - 1);
                break;
        case SH_FSI_FMT_SPDIF:
                if (master->core->ver < 2) {
@@ -771,7 +829,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
                        return -EINVAL;
                }
                data = CR_SPDIF;
-               fsi->chan = 2;
+               io->chan_num = 2;
                fsi_spdif_clk_ctrl(fsi, 1);
                fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010);
                break;
@@ -788,14 +846,14 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
        /* fifo init */
        fsi_fifo_init(fsi, is_play, dai);
 
-       return ret;
+       return 0;
 }
 
 static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       int is_play = fsi_is_play(substream);
 
        fsi_irq_disable(fsi, is_play);
        fsi_clk_ctrl(fsi, 0);
@@ -808,19 +866,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       int is_play = fsi_is_play(substream);
        int ret = 0;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               fsi_stream_push(fsi, substream,
+               fsi_stream_push(fsi, is_play, substream,
                                frames_to_bytes(runtime, runtime->buffer_size),
                                frames_to_bytes(runtime, runtime->period_size));
                ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
                fsi_irq_disable(fsi, is_play);
-               fsi_stream_pop(fsi);
+               fsi_stream_pop(fsi, is_play);
                break;
        }
 
@@ -835,7 +893,7 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
        struct fsi_master *master = fsi_get_master(fsi);
        int (*set_rate)(int is_porta, int rate) = master->info->set_rate;
        int fsi_ver = master->core->ver;
-       int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int is_play = fsi_is_play(substream);
        int ret;
 
        /* if slave mode, set_rate is not needed */
@@ -916,13 +974,10 @@ static struct snd_soc_dai_ops fsi_dai_ops = {
        .hw_params      = fsi_dai_hw_params,
 };
 
-/************************************************************************
-
-
-               pcm ops
-
+/*
+ *             pcm ops
+ */
 
-************************************************************************/
 static struct snd_pcm_hardware fsi_pcm_hardware = {
        .info =         SNDRV_PCM_INFO_INTERLEAVED      |
                        SNDRV_PCM_INFO_MMAP             |
@@ -971,9 +1026,10 @@ 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_priv(substream);
+       struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
        long location;
 
-       location = (fsi->byte_offset - 1);
+       location = (io->buff_offset - 1);
        if (location < 0)
                location = 0;
 
@@ -988,13 +1044,10 @@ static struct snd_pcm_ops fsi_pcm_ops = {
        .pointer        = fsi_pointer,
 };
 
-/************************************************************************
-
-
-               snd_soc_platform
-
+/*
+ *             snd_soc_platform
+ */
 
-************************************************************************/
 #define PREALLOC_BUFFER                (32 * 1024)
 #define PREALLOC_BUFFER_MAX    (32 * 1024)
 
@@ -1018,17 +1071,13 @@ static int fsi_pcm_new(struct snd_card *card,
                PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
 }
 
-/************************************************************************
-
-
-               alsa struct
-
+/*
+ *             alsa struct
+ */
 
-************************************************************************/
-struct snd_soc_dai fsi_soc_dai[] = {
+static struct snd_soc_dai_driver fsi_soc_dai[] = {
        {
-               .name                   = "FSIA",
-               .id                     = 0,
+               .name                   = "fsia-dai",
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
@@ -1044,8 +1093,7 @@ struct snd_soc_dai fsi_soc_dai[] = {
                .ops = &fsi_dai_ops,
        },
        {
-               .name                   = "FSIB",
-               .id                     = 1,
+               .name                   = "fsib-dai",
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
@@ -1061,23 +1109,17 @@ struct snd_soc_dai fsi_soc_dai[] = {
                .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,
+static struct snd_soc_platform_driver fsi_soc_platform = {
+       .ops            = &fsi_pcm_ops,
        .pcm_new        = fsi_pcm_new,
        .pcm_free       = fsi_pcm_free,
 };
-EXPORT_SYMBOL_GPL(fsi_soc_platform);
-
-/************************************************************************
-
-
-               platform function
 
+/*
+ *             platform function
+ */
 
-************************************************************************/
 static int fsi_probe(struct platform_device *pdev)
 {
        struct fsi_master *master;
@@ -1132,11 +1174,7 @@ static int fsi_probe(struct platform_device *pdev)
 
        pm_runtime_enable(&pdev->dev);
        pm_runtime_resume(&pdev->dev);
-
-       fsi_soc_dai[0].dev              = &pdev->dev;
-       fsi_soc_dai[0].private_data     = &master->fsia;
-       fsi_soc_dai[1].dev              = &pdev->dev;
-       fsi_soc_dai[1].private_data     = &master->fsib;
+       dev_set_drvdata(&pdev->dev, master);
 
        fsi_soft_all_reset(master);
 
@@ -1147,13 +1185,13 @@ static int fsi_probe(struct platform_device *pdev)
                goto exit_iounmap;
        }
 
-       ret = snd_soc_register_platform(&fsi_soc_platform);
+       ret = snd_soc_register_platform(&pdev->dev, &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));
+       return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
 
 exit_free_irq:
        free_irq(irq, master);
@@ -1171,10 +1209,10 @@ static int fsi_remove(struct platform_device *pdev)
 {
        struct fsi_master *master;
 
-       master = fsi_get_master(fsi_soc_dai[0].private_data);
+       master = dev_get_drvdata(&pdev->dev);
 
-       snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
-       snd_soc_unregister_platform(&fsi_soc_platform);
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
+       snd_soc_unregister_platform(&pdev->dev);
 
        pm_runtime_disable(&pdev->dev);
 
@@ -1183,11 +1221,6 @@ static int fsi_remove(struct platform_device *pdev)
        iounmap(master->base);
        kfree(master);
 
-       fsi_soc_dai[0].dev              = NULL;
-       fsi_soc_dai[0].private_data     = NULL;
-       fsi_soc_dai[1].dev              = NULL;
-       fsi_soc_dai[1].private_data     = NULL;
-
        return 0;
 }
 
@@ -1229,11 +1262,13 @@ static struct fsi_core fsi2_core = {
 static struct platform_device_id fsi_id_table[] = {
        { "sh_fsi",     (kernel_ulong_t)&fsi1_core },
        { "sh_fsi2",    (kernel_ulong_t)&fsi2_core },
+       {},
 };
+MODULE_DEVICE_TABLE(platform, fsi_id_table);
 
 static struct platform_driver fsi_driver = {
        .driver         = {
-               .name   = "sh_fsi",
+               .name   = "fsi-pcm-audio",
                .pm     = &fsi_pm_ops,
        },
        .probe          = fsi_probe,
@@ -1250,6 +1285,7 @@ static void __exit fsi_mobile_exit(void)
 {
        platform_driver_unregister(&fsi_driver);
 }
+
 module_init(fsi_mobile_init);
 module_exit(fsi_mobile_exit);
 
index 41db75a..c87e3ff 100644 (file)
@@ -239,8 +239,7 @@ static int hac_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 hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
+       struct hac_priv *hac = &hac_cpu_data[dai->id];
        int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
 
        switch (params->msbits) {
@@ -271,10 +270,9 @@ static struct snd_soc_dai_ops hac_dai_ops = {
        .hw_params      = hac_hw_params,
 };
 
-struct snd_soc_dai sh4_hac_dai[] = {
+static struct snd_soc_dai_driver sh4_hac_dai[] = {
 {
-       .name                   = "HAC0",
-       .id                     = 0,
+       .name                   = "hac-dai.0",
        .ac97_control           = 1,
        .playback = {
                .rates          = AC97_RATES,
@@ -292,8 +290,7 @@ struct snd_soc_dai sh4_hac_dai[] = {
 },
 #ifdef CONFIG_CPU_SUBTYPE_SH7760
 {
-       .name                   = "HAC1",
-       .ac97_control           = 1,
+       .name                   = "hac-dai.1",
        .id                     = 1,
        .playback = {
                .rates          = AC97_RATES,
@@ -312,19 +309,40 @@ struct snd_soc_dai sh4_hac_dai[] = {
 },
 #endif
 };
-EXPORT_SYMBOL_GPL(sh4_hac_dai);
 
-static int __init sh4_hac_init(void)
+static int __devinit hac_soc_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
+                       ARRAY_SIZE(sh4_hac_dai));
+}
+
+static int __devexit hac_soc_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
+       return 0;
+}
+
+static struct platform_driver hac_pcm_driver = {
+       .driver = {
+                       .name = "hac-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = hac_soc_platform_probe,
+       .remove = __devexit_p(hac_soc_platform_remove),
+};
+
+static int __init sh4_hac_pcm_init(void)
 {
-       return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+       return platform_driver_register(&hac_pcm_driver);
 }
-module_init(sh4_hac_init);
+module_init(sh4_hac_pcm_init);
 
-static void __exit sh4_hac_exit(void)
+static void __exit sh4_hac_pcm_exit(void)
 {
-       snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
+       platform_driver_unregister(&hac_pcm_driver);
 }
-module_exit(sh4_hac_exit);
+module_exit(sh4_hac_pcm_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
index 87e2b7f..ac6c49c 100644 (file)
@@ -51,7 +51,7 @@ static int migor_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 *codec_dai = rtd->codec_dai;
        int ret;
        unsigned int rate = params_rate(params);
 
@@ -69,7 +69,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF |
+       ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF |
                                  SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
        if (ret < 0)
                return ret;
@@ -82,7 +82,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
        clk_set_rate(&siumckb_clk, codec_freq);
        dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq);
 
-       ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT,
+       ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, SIU_CLKB_EXT,
                                     codec_freq / 2, SND_SOC_CLOCK_IN);
 
        if (!ret)
@@ -94,7 +94,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
 static int migor_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;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        if (use_count) {
                use_count--;
@@ -137,8 +137,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
        { "Mic Bias", NULL, "External Microphone" },
 };
 
-static int migor_dai_init(struct snd_soc_codec *codec)
+static int migor_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_soc_codec *codec = rtd->codec;
+
        snd_soc_dapm_new_controls(codec, migor_dapm_widgets,
                                  ARRAY_SIZE(migor_dapm_widgets));
 
@@ -151,8 +153,10 @@ static int migor_dai_init(struct snd_soc_codec *codec)
 static struct snd_soc_dai_link migor_dai = {
        .name = "wm8978",
        .stream_name = "WM8978",
-       .cpu_dai = &siu_i2s_dai,
-       .codec_dai = &wm8978_dai,
+       .cpu_dai_name = "siu-i2s-dai",
+       .codec_dai_name = "wm8978-hifi",
+       .platform_name = "siu-pcm-audio",
+       .codec_name = "wm8978.0-001a",
        .ops = &migor_dai_ops,
        .init = migor_dai_init,
 };
@@ -160,17 +164,10 @@ static struct snd_soc_dai_link migor_dai = {
 /* migor audio machine driver */
 static struct snd_soc_card snd_soc_migor = {
        .name = "Migo-R",
-       .platform = &siu_platform,
        .dai_link = &migor_dai,
        .num_links = 1,
 };
 
-/* migor audio subsystem */
-static struct snd_soc_device migor_snd_devdata = {
-       .card = &snd_soc_migor,
-       .codec_dev = &soc_codec_dev_wm8978,
-};
-
 static struct platform_device *migor_snd_device;
 
 static int __init migor_init(void)
@@ -195,9 +192,7 @@ static int __init migor_init(void)
                goto epdevalloc;
        }
 
-       platform_set_drvdata(migor_snd_device, &migor_snd_devdata);
-
-       migor_snd_devdata.dev = &migor_snd_device->dev;
+       platform_set_drvdata(migor_snd_device, &snd_soc_migor);
 
        ret = platform_device_add(migor_snd_device);
        if (ret)
index ce7f95b..b897f7b 100644 (file)
 #include <sound/soc-dapm.h>
 #include <asm/io.h>
 
-#include "../codecs/ac97.h"
-
 #define IPSEL 0xFE400034
 
 /* platform specific structs can be declared here */
-extern struct snd_soc_dai sh4_hac_dai[2];
-extern struct snd_soc_platform sh7760_soc_platform;
+extern struct snd_soc_dai_driver sh4_hac_dai[2];
+extern struct snd_soc_platform_driver sh7760_soc_platform;
 
-static int machine_init(struct snd_soc_codec *codec)
+static int machine_init(struct snd_soc_pcm_runtime *rtd)
 {
-       snd_soc_dapm_sync(codec);
+       snd_soc_dapm_sync(rtd->codec);
        return 0;
 }
 
 static struct snd_soc_dai_link sh7760_ac97_dai = {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &sh4_hac_dai[0],     /* HAC0 */
-       .codec_dai = &ac97_dai,
+       .cpu_dai_name = "hac-dai.0",    /* HAC0 */
+       .codec_dai_name = "ac97-hifi",
+       .platform_name = "sh7760-pcm-audio",
+       .codec_name = "ac97-codec",
        .init = machine_init,
        .ops = NULL,
 };
 
 static struct snd_soc_card sh7760_ac97_soc_machine  = {
        .name = "SH7760 AC97",
-       .platform = &sh7760_soc_platform,
        .dai_link = &sh7760_ac97_dai,
        .num_links = 1,
 };
 
-static struct snd_soc_device sh7760_ac97_snd_devdata = {
-       .card = &sh7760_ac97_soc_machine,
-       .codec_dev = &soc_codec_dev_ac97,
-};
-
 static struct platform_device *sh7760_ac97_snd_device;
 
 static int __init sh7760_ac97_init(void)
@@ -67,8 +61,7 @@ static int __init sh7760_ac97_init(void)
                goto out;
 
        platform_set_drvdata(sh7760_ac97_snd_device,
-                            &sh7760_ac97_snd_devdata);
-       sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev;
+                            &sh7760_ac97_soc_machine);
        ret = platform_device_add(sh7760_ac97_snd_device);
 
        if (ret)
index 492b1ca..9f4dcb9 100644 (file)
@@ -98,7 +98,9 @@ enum {
        SIU_CLKB_EXT
 };
 
+struct device;
 struct siu_info {
+       struct device           *dev;
        int                     port_id;
        u32 __iomem             *pram;
        u32 __iomem             *xram;
@@ -181,8 +183,8 @@ static inline u32 siu_read32(u32 __iomem *addr)
 #define SIU_BRGBSEL    (0x108 / sizeof(u32))
 #define SIU_BRRB       (0x10c / sizeof(u32))
 
-extern struct snd_soc_platform siu_platform;
-extern struct snd_soc_dai siu_i2s_dai;
+extern struct snd_soc_platform_driver siu_platform;
+extern struct siu_info *siu_i2s_data;
 
 int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);
 void siu_free_port(struct siu_port *port_info);
index eeed5ed..af53b64 100644 (file)
@@ -71,6 +71,8 @@ struct port_flag {
        struct format_flag      capture;
 };
 
+struct siu_info *siu_i2s_data;
+
 static struct port_flag siu_flags[SIU_PORT_NUM] = {
        [SIU_PORT_A] = {
                .playback = {
@@ -104,13 +106,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = {
 
 static void siu_dai_start(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
 
        dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
 
        /* Turn on SIU clock */
-       pm_runtime_get_sync(siu_i2s_dai.dev);
+       pm_runtime_get_sync(info->dev);
 
        /* Issue software reset to siu */
        siu_write32(base + SIU_SRCTL, 0);
@@ -148,21 +150,21 @@ static void siu_dai_start(struct siu_port *port_info)
        siu_write32(base + SIU_SBDVCB, port_info->capture.volume);
 }
 
-static void siu_dai_stop(void)
+static void siu_dai_stop(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
 
        /* SIU software reset */
        siu_write32(base + SIU_SRCTL, 0);
 
        /* Turn off SIU clock */
-       pm_runtime_put_sync(siu_i2s_dai.dev);
+       pm_runtime_put_sync(info->dev);
 }
 
 static void siu_dai_spbAselect(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct siu_firmware *fw = &info->fw;
        u32 *ydef = fw->yram0;
        u32 idx;
@@ -187,7 +189,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info)
 
 static void siu_dai_spbBselect(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct siu_firmware *fw = &info->fw;
        u32 *ydef = fw->yram0;
        u32 idx;
@@ -207,7 +209,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info)
 
 static void siu_dai_open(struct siu_stream *siu_stream)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        u32 srctl, ifctl;
 
@@ -238,7 +240,7 @@ static void siu_dai_open(struct siu_stream *siu_stream)
  */
 static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        u32 dpak;
 
@@ -258,7 +260,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
 
 static int siu_dai_spbstart(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_firmware *fw = &info->fw;
        u32 *ydef = fw->yram0;
@@ -323,7 +325,7 @@ static int siu_dai_spbstart(struct siu_port *port_info)
 
 static void siu_dai_spbstop(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
 
        siu_write32(base + SIU_SBACTIV, 0);
@@ -402,7 +404,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
 {
        struct siu_port *port_info = snd_kcontrol_chip(kctrl);
        struct device *dev = port_info->pcm->card->dev;
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        u32 new_vol;
        u32 cur_vol;
@@ -510,7 +512,7 @@ void siu_free_port(struct siu_port *port_info)
 static int siu_dai_startup(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = snd_soc_dai_get_drvdata(dai);
        struct snd_pcm_runtime *rt = substream->runtime;
        struct siu_port *port_info = siu_port_info(substream);
        int ret;
@@ -532,7 +534,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream,
 static void siu_dai_shutdown(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = snd_soc_dai_get_drvdata(dai);
        struct siu_port *port_info = siu_port_info(substream);
 
        dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
@@ -548,7 +550,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,
                /* during stmread or stmwrite ? */
                BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);
                siu_dai_spbstop(port_info);
-               siu_dai_stop();
+               siu_dai_stop(port_info);
        }
 }
 
@@ -556,7 +558,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,
 static int siu_dai_prepare(struct snd_pcm_substream *substream,
                           struct snd_soc_dai *dai)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = snd_soc_dai_get_drvdata(dai);
        struct snd_pcm_runtime *rt = substream->runtime;
        struct siu_port *port_info = siu_port_info(substream);
        struct siu_stream *siu_stream;
@@ -605,7 +607,7 @@ fail:
 static int siu_dai_set_fmt(struct snd_soc_dai *dai,
                           unsigned int fmt)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = snd_soc_dai_get_drvdata(dai);
        u32 __iomem *base = info->reg;
        u32 ifctl;
 
@@ -671,21 +673,37 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
                return -EINVAL;
        }
 
-       siu_clk = clk_get(siu_i2s_dai.dev, siu_name);
-       if (IS_ERR(siu_clk))
+       siu_clk = clk_get(dai->dev, siu_name);
+       if (IS_ERR(siu_clk)) {
+               dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__,
+                       PTR_ERR(siu_clk));
                return PTR_ERR(siu_clk);
+       }
+
+       parent_clk = clk_get(dai->dev, parent_name);
+       if (IS_ERR(parent_clk)) {
+               ret = PTR_ERR(parent_clk);
+               dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret);
+               goto epclkget;
+       }
 
-       parent_clk = clk_get(siu_i2s_dai.dev, parent_name);
-       if (!IS_ERR(parent_clk)) {
-               ret = clk_set_parent(siu_clk, parent_clk);
-               if (!ret)
-                       clk_set_rate(siu_clk, freq);
-               clk_put(parent_clk);
+       ret = clk_set_parent(siu_clk, parent_clk);
+       if (ret < 0) {
+               dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret);
+               goto eclksetp;
        }
 
+       ret = clk_set_rate(siu_clk, freq);
+       if (ret < 0)
+               dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret);
+
+       /* TODO: when clkdev gets reference counting we'll move these to siu_dai_shutdown() */
+eclksetp:
+       clk_put(parent_clk);
+epclkget:
        clk_put(siu_clk);
 
-       return 0;
+       return ret;
 }
 
 static struct snd_soc_dai_ops siu_dai_ops = {
@@ -696,9 +714,8 @@ static struct snd_soc_dai_ops siu_dai_ops = {
        .set_fmt        = siu_dai_set_fmt,
 };
 
-struct snd_soc_dai siu_i2s_dai = {
-       .name = "sh-siu",
-       .id = 0,
+static struct snd_soc_dai_driver siu_i2s_dai = {
+       .name   = "siu-i2s-dai",
        .playback = {
                .channels_min = 2,
                .channels_max = 2,
@@ -713,7 +730,6 @@ struct snd_soc_dai siu_i2s_dai = {
         },
        .ops = &siu_dai_ops,
 };
-EXPORT_SYMBOL_GPL(siu_i2s_dai);
 
 static int __devinit siu_probe(struct platform_device *pdev)
 {
@@ -725,6 +741,8 @@ static int __devinit siu_probe(struct platform_device *pdev)
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
+       siu_i2s_data = info;
+       info->dev = &pdev->dev;
 
        ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);
        if (ret)
@@ -767,14 +785,14 @@ static int __devinit siu_probe(struct platform_device *pdev)
        if (!info->reg)
                goto emapreg;
 
-       siu_i2s_dai.dev = &pdev->dev;
-       siu_i2s_dai.private_data = info;
+       dev_set_drvdata(&pdev->dev, info);
 
-       ret = snd_soc_register_dais(&siu_i2s_dai, 1);
+       /* register using ARRAY version so we can keep dai name */
+       ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1);
        if (ret < 0)
                goto edaiinit;
 
-       ret = snd_soc_register_platform(&siu_platform);
+       ret = snd_soc_register_platform(&pdev->dev, &siu_platform);
        if (ret < 0)
                goto esocregp;
 
@@ -783,7 +801,7 @@ static int __devinit siu_probe(struct platform_device *pdev)
        return ret;
 
 esocregp:
-       snd_soc_unregister_dais(&siu_i2s_dai, 1);
+       snd_soc_unregister_dai(&pdev->dev);
 edaiinit:
        iounmap(info->reg);
 emapreg:
@@ -804,13 +822,13 @@ ereqfw:
 
 static int __devexit siu_remove(struct platform_device *pdev)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = dev_get_drvdata(&pdev->dev);
        struct resource *res;
 
        pm_runtime_disable(&pdev->dev);
 
-       snd_soc_unregister_platform(&siu_platform);
-       snd_soc_unregister_dais(&siu_i2s_dai, 1);
+       snd_soc_unregister_platform(&pdev->dev);
+       snd_soc_unregister_dai(&pdev->dev);
 
        iounmap(info->reg);
        iounmap(info->yram);
@@ -826,7 +844,8 @@ static int __devexit siu_remove(struct platform_device *pdev)
 
 static struct platform_driver siu_driver = {
        .driver         = {
-               .name   = "sh_siu",
+               .owner  = THIS_MODULE,
+               .name   = "siu-pcm-audio",
        },
        .probe          = siu_probe,
        .remove         = __devexit_p(siu_remove),
index 36170be..ed29c9e 100644 (file)
@@ -48,7 +48,7 @@ struct siu_port *siu_ports[SIU_PORT_NUM];
 /* transfersize is number of u32 dma transfers per period */
 static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_stream *siu_stream = &port_info->playback;
        u32 stfifo;
@@ -114,7 +114,7 @@ static void siu_dma_tx_complete(void *arg)
 static int siu_pcm_wr_set(struct siu_port *port_info,
                          dma_addr_t buff, u32 size)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_stream *siu_stream = &port_info->playback;
        struct snd_pcm_substream *substream = siu_stream->substream;
@@ -127,6 +127,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
        sg_init_table(&sg, 1);
        sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
                    size, offset_in_page(buff));
+       sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
@@ -161,7 +162,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
 static int siu_pcm_rd_set(struct siu_port *port_info,
                          dma_addr_t buff, size_t size)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_stream *siu_stream = &port_info->capture;
        struct snd_pcm_substream *substream = siu_stream->substream;
@@ -176,6 +177,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
        sg_init_table(&sg, 1);
        sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
                    size, offset_in_page(buff));
+       sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
@@ -270,7 +272,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info)
 
 static int siu_pcm_stmread_stop(struct siu_port *port_info)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_stream *siu_stream = &port_info->capture;
        struct device *dev = siu_stream->substream->pcm->card->dev;
@@ -294,7 +296,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info)
 static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
                             struct snd_pcm_hw_params *hw_params)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct device *dev = ss->pcm->card->dev;
        int ret;
 
@@ -309,7 +311,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
 
 static int siu_pcm_hw_free(struct snd_pcm_substream *ss)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct siu_port *port_info = siu_port_info(ss);
        struct device *dev = ss->pcm->card->dev;
        struct siu_stream *siu_stream;
@@ -340,11 +342,12 @@ static bool filter(struct dma_chan *chan, void *slave)
 static int siu_pcm_open(struct snd_pcm_substream *ss)
 {
        /* Playback / Capture */
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct snd_soc_pcm_runtime *rtd = ss->private_data;
+       struct siu_platform *pdata = rtd->platform->dev->platform_data;
+       struct siu_info *info = siu_i2s_data;
        struct siu_port *port_info = siu_port_info(ss);
        struct siu_stream *siu_stream;
        u32 port = info->port_id;
-       struct siu_platform *pdata = siu_i2s_dai.dev->platform_data;
        struct device *dev = ss->pcm->card->dev;
        dma_cap_mask_t mask;
        struct sh_dmae_slave *param;
@@ -381,7 +384,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss)
 
 static int siu_pcm_close(struct snd_pcm_substream *ss)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct device *dev = ss->pcm->card->dev;
        struct siu_port *port_info = siu_port_info(ss);
        struct siu_stream *siu_stream;
@@ -403,7 +406,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss)
 
 static int siu_pcm_prepare(struct snd_pcm_substream *ss)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct siu_port *port_info = siu_port_info(ss);
        struct device *dev = ss->pcm->card->dev;
        struct snd_pcm_runtime  *rt = ss->runtime;
@@ -449,7 +452,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss)
 
 static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
 {
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct device *dev = ss->pcm->card->dev;
        struct siu_port *port_info = siu_port_info(ss);
        int ret;
@@ -492,7 +495,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
 static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
 {
        struct device *dev = ss->pcm->card->dev;
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        u32 __iomem *base = info->reg;
        struct siu_port *port_info = siu_port_info(ss);
        struct snd_pcm_runtime *rt = ss->runtime;
@@ -528,7 +531,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
                       struct snd_pcm *pcm)
 {
        /* card->dev == socdev->dev, see snd_soc_new_pcms() */
-       struct siu_info *info = siu_i2s_dai.private_data;
+       struct siu_info *info = siu_i2s_data;
        struct platform_device *pdev = to_platform_device(card->dev);
        int ret;
        int i;
@@ -605,9 +608,8 @@ static struct snd_pcm_ops siu_pcm_ops = {
        .pointer        = siu_pcm_pointer_dma,
 };
 
-struct snd_soc_platform siu_platform = {
-       .name           = "siu-audio",
-       .pcm_ops        = &siu_pcm_ops,
+struct snd_soc_platform_driver siu_platform = {
+       .ops                    = &siu_pcm_ops,
        .pcm_new        = siu_pcm_new,
        .pcm_free       = siu_pcm_free,
 };
index b378096..40bbdf1 100644 (file)
@@ -92,8 +92,7 @@ struct ssi_priv {
 static int ssi_startup(struct snd_pcm_substream *substream,
                       struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
+       struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
        if (ssi->inuse) {
                pr_debug("ssi: already in use!\n");
                return -EBUSY;
@@ -105,8 +104,7 @@ static int ssi_startup(struct snd_pcm_substream *substream,
 static void ssi_shutdown(struct snd_pcm_substream *substream,
                         struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
+       struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
 
        ssi->inuse = 0;
 }
@@ -114,8 +112,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream,
 static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
                       struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
+       struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -135,8 +132,7 @@ static int 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 ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
+       struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
        unsigned long ssicr = SSIREG(SSICR);
        unsigned int bits, channels, swl, recv, i;
 
@@ -346,10 +342,9 @@ static struct snd_soc_dai_ops ssi_dai_ops = {
        .set_fmt        = ssi_set_fmt,
 };
 
-struct snd_soc_dai sh4_ssi_dai[] = {
+struct snd_soc_dai_driver sh4_ssi_dai[] = {
 {
-       .name                   = "SSI0",
-       .id                     = 0,
+       .name                   = "ssi-dai.0",
        .playback = {
                .rates          = SSI_RATES,
                .formats        = SSI_FMTS,
@@ -366,8 +361,7 @@ struct snd_soc_dai sh4_ssi_dai[] = {
 },
 #ifdef CONFIG_CPU_SUBTYPE_SH7760
 {
-       .name                   = "SSI1",
-       .id                     = 1,
+       .name                   = "ssi-dai.1",
        .playback = {
                .rates          = SSI_RATES,
                .formats        = SSI_FMTS,
@@ -384,19 +378,40 @@ struct snd_soc_dai sh4_ssi_dai[] = {
 },
 #endif
 };
-EXPORT_SYMBOL_GPL(sh4_ssi_dai);
 
-static int __init sh4_ssi_init(void)
+static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
+                       ARRAY_SIZE(sh4_ssi_dai));
+}
+
+static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
+       return 0;
+}
+
+static struct platform_driver sh4_ssi_driver = {
+       .driver = {
+                       .name = "sh4-ssi-dai",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = sh4_soc_dai_probe,
+       .remove = __devexit_p(sh4_soc_dai_remove),
+};
+
+static int __init snd_sh4_ssi_init(void)
 {
-       return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+       return platform_driver_register(&sh4_ssi_driver);
 }
-module_init(sh4_ssi_init);
+module_init(snd_sh4_ssi_init);
 
-static void __exit sh4_ssi_exit(void)
+static void __exit snd_sh4_ssi_exit(void)
 {
-       snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
+       platform_driver_unregister(&sh4_ssi_driver);
 }
-module_exit(sh4_ssi_exit);
+module_exit(snd_sh4_ssi_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
index f6b0d28..d214f02 100644 (file)
@@ -19,8 +19,15 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
                                     unsigned int reg)
 {
        u16 *cache = codec->reg_cache;
-       if (reg >= codec->reg_cache_size)
-               return -1;
+
+       if (reg >= codec->driver->reg_cache_size ||
+               snd_soc_codec_volatile_register(codec, reg)) {
+                       if (codec->cache_only)
+                               return -1;
+
+                       return codec->hw_read(codec, reg);
+       }
+
        return cache[reg];
 }
 
@@ -31,13 +38,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
        u8 data[2];
        int ret;
 
-       BUG_ON(codec->volatile_register);
-
        data[0] = (reg << 4) | ((value >> 8) & 0x000f);
        data[1] = value & 0x00ff;
 
-       if (reg < codec->reg_cache_size)
-               cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+               reg < codec->driver->reg_cache_size)
+                       cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -89,8 +95,15 @@ 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;
+
+       if (reg >= codec->driver->reg_cache_size ||
+               snd_soc_codec_volatile_register(codec, reg)) {
+                       if (codec->cache_only)
+                               return -1;
+
+                       return codec->hw_read(codec, reg);
+       }
+
        return cache[reg];
 }
 
@@ -101,13 +114,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
        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;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+               reg < codec->driver->reg_cache_size)
+                       cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -161,14 +173,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
        u8 *cache = codec->reg_cache;
        u8 data[2];
 
-       BUG_ON(codec->volatile_register);
-
        reg &= 0xff;
        data[0] = reg;
        data[1] = value & 0xff;
 
-       if (reg < codec->reg_cache_size)
-               cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+               reg < codec->driver->reg_cache_size)
+                       cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -187,12 +198,49 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
                                     unsigned int reg)
 {
        u8 *cache = codec->reg_cache;
+
        reg &= 0xff;
-       if (reg >= codec->reg_cache_size)
-               return -1;
+       if (reg >= codec->driver->reg_cache_size ||
+               snd_soc_codec_volatile_register(codec, reg)) {
+                       if (codec->cache_only)
+                               return -1;
+
+                       return codec->hw_read(codec, reg);
+       }
+
        return cache[reg];
 }
 
+#if defined(CONFIG_SPI_MASTER)
+static int snd_soc_8_8_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_8_8_spi_write NULL
+#endif
+
 static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
                              unsigned int value)
 {
@@ -203,9 +251,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
        data[1] = (value >> 8) & 0xff;
        data[2] = value & 0xff;
 
-       if (!snd_soc_codec_volatile_register(codec, reg)
-               && reg < codec->reg_cache_size)
-                       reg_cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+           reg < codec->driver->reg_cache_size)
+               reg_cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -225,10 +273,10 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
 {
        u16 *cache = codec->reg_cache;
 
-       if (reg >= codec->reg_cache_size ||
+       if (reg >= codec->driver->reg_cache_size ||
            snd_soc_codec_volatile_register(codec, reg)) {
                if (codec->cache_only)
-                       return -EINVAL;
+                       return -1;
 
                return codec->hw_read(codec, reg);
        } else {
@@ -236,6 +284,37 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
        }
 }
 
+#if defined(CONFIG_SPI_MASTER)
+static int snd_soc_8_16_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[3];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+       msg[2] = data[2];
+
+       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_8_16_spi_write NULL
+#endif
+
 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
 static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
                                          unsigned int r)
@@ -344,8 +423,14 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
        u8 *cache = codec->reg_cache;
 
        reg &= 0xff;
-       if (reg >= codec->reg_cache_size)
-               return -1;
+       if (reg >= codec->driver->reg_cache_size ||
+               snd_soc_codec_volatile_register(codec, reg)) {
+                       if (codec->cache_only)
+                               return -1;
+
+                       return codec->hw_read(codec, reg);
+       }
+
        return cache[reg];
 }
 
@@ -356,15 +441,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
        u8 data[3];
        int ret;
 
-       BUG_ON(codec->volatile_register);
-
        data[0] = (reg >> 8) & 0xff;
        data[1] = reg & 0xff;
        data[2] = value;
 
        reg &= 0xff;
-       if (reg < codec->reg_cache_size)
-               cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+               reg < codec->driver->reg_cache_size)
+                       cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -452,10 +536,10 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
 {
        u16 *cache = codec->reg_cache;
 
-       if (reg >= codec->reg_cache_size ||
+       if (reg >= codec->driver->reg_cache_size ||
            snd_soc_codec_volatile_register(codec, reg)) {
                if (codec->cache_only)
-                       return -EINVAL;
+                       return -1;
 
                return codec->hw_read(codec, reg);
        }
@@ -475,8 +559,9 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
        data[2] = (value >> 8) & 0xff;
        data[3] = value & 0xff;
 
-       if (reg < codec->reg_cache_size)
-               cache[reg] = value;
+       if (!snd_soc_codec_volatile_register(codec, reg) &&
+               reg < codec->driver->reg_cache_size)
+                       cache[reg] = value;
 
        if (codec->cache_only) {
                codec->cache_sync = 1;
@@ -494,6 +579,38 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
                return -EIO;
 }
 
+#if defined(CONFIG_SPI_MASTER)
+static int snd_soc_16_16_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[4];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+       msg[2] = data[2];
+       msg[3] = data[3];
+
+       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_16_16_spi_write NULL
+#endif
+
 static struct {
        int addr_bits;
        int data_bits;
@@ -516,11 +633,13 @@ static struct {
                .addr_bits = 8, .data_bits = 8,
                .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
                .i2c_read = snd_soc_8_8_read_i2c,
+               .spi_write = snd_soc_8_8_spi_write,
        },
        {
                .addr_bits = 8, .data_bits = 16,
                .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
                .i2c_read = snd_soc_8_16_read_i2c,
+               .spi_write = snd_soc_8_16_spi_write,
        },
        {
                .addr_bits = 16, .data_bits = 8,
@@ -532,6 +651,7 @@ static struct {
                .addr_bits = 16, .data_bits = 16,
                .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
                .i2c_read = snd_soc_16_16_read_i2c,
+               .spi_write = snd_soc_16_16_spi_write,
        },
 };
 
@@ -572,8 +692,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
                return -EINVAL;
        }
 
-       codec->write = io_types[i].write;
-       codec->read = io_types[i].read;
+       codec->driver->write = io_types[i].write;
+       codec->driver->read = io_types[i].read;
 
        switch (control) {
        case SND_SOC_CUSTOM:
@@ -585,11 +705,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 #endif
                if (io_types[i].i2c_read)
                        codec->hw_read = io_types[i].i2c_read;
+
+               codec->control_data = container_of(codec->dev,
+                                                  struct i2c_client,
+                                                  dev);
                break;
 
        case SND_SOC_SPI:
                if (io_types[i].spi_write)
                        codec->hw_write = io_types[i].spi_write;
+
+               codec->control_data = container_of(codec->dev,
+                                                  struct spi_device,
+                                                  dev);
                break;
        }
 
index 4057d35..1c8f3f5 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright 2005 Wolfson Microelectronics PLC.
  * Copyright 2005 Openedhand Ltd.
+ * Copyright (C) 2010 Slimlogic Ltd.
+ * Copyright (C) 2010 Texas Instruments Inc.
  *
  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
  *         with code, comments and ideas from :-
@@ -37,6 +39,8 @@
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
 
+#define NAME_SIZE      32
+
 static DEFINE_MUTEX(pcm_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
 
@@ -52,6 +56,7 @@ static LIST_HEAD(codec_list);
 
 static int snd_soc_register_card(struct snd_soc_card *card);
 static int snd_soc_unregister_card(struct snd_soc_card *card);
+static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
 
 /*
  * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -86,30 +91,30 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 {
        int ret, i, step = 1, count = 0;
 
-       if (!codec->reg_cache_size)
+       if (!codec->driver->reg_cache_size)
                return 0;
 
-       if (codec->reg_cache_step)
-               step = codec->reg_cache_step;
+       if (codec->driver->reg_cache_step)
+               step = codec->driver->reg_cache_step;
 
        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))
+       for (i = 0; i < codec->driver->reg_cache_size; i += step) {
+               if (codec->driver->readable_register && !codec->driver->readable_register(i))
                        continue;
 
                count += sprintf(buf + count, "%2x: ", i);
                if (count >= PAGE_SIZE - 1)
                        break;
 
-               if (codec->display_register) {
-                       count += codec->display_register(codec, buf + count,
+               if (codec->driver->display_register) {
+                       count += codec->driver->display_register(codec, buf + count,
                                                         PAGE_SIZE - count, i);
                } else {
                        /* If the read fails it's almost certainly due to
                         * the register being volatile and the device being
                         * powered off.
                         */
-                       ret = codec->read(codec, i);
+                       ret = codec->driver->read(codec, i);
                        if (ret >= 0)
                                count += snprintf(buf + count,
                                                  PAGE_SIZE - count,
@@ -137,8 +142,10 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 static ssize_t codec_reg_show(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
-       struct snd_soc_device *devdata = dev_get_drvdata(dev);
-       return soc_codec_reg_show(devdata->card->codec, buf);
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(dev, struct snd_soc_pcm_runtime, dev);
+
+       return soc_codec_reg_show(rtd->codec, buf);
 }
 
 static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
@@ -146,20 +153,20 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
 static ssize_t pmdown_time_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       struct snd_soc_device *socdev = dev_get_drvdata(dev);
-       struct snd_soc_card *card = socdev->card;
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(dev, struct snd_soc_pcm_runtime, dev);
 
-       return sprintf(buf, "%ld\n", card->pmdown_time);
+       return sprintf(buf, "%ld\n", rtd->pmdown_time);
 }
 
 static ssize_t pmdown_time_set(struct device *dev,
                               struct device_attribute *attr,
                               const char *buf, size_t count)
 {
-       struct snd_soc_device *socdev = dev_get_drvdata(dev);
-       struct snd_soc_card *card = socdev->card;
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(dev, struct snd_soc_pcm_runtime, dev);
 
-       strict_strtol(buf, 10, &card->pmdown_time);
+       strict_strtol(buf, 10, &rtd->pmdown_time);
 
        return count;
 }
@@ -203,19 +210,19 @@ static ssize_t codec_reg_write_file(struct file *file,
                return -EFAULT;
        buf[buf_size] = 0;
 
-       if (codec->reg_cache_step)
-               step = codec->reg_cache_step;
+       if (codec->driver->reg_cache_step)
+               step = codec->driver->reg_cache_step;
 
        while (*start == ' ')
                start++;
        reg = simple_strtoul(start, &start, 16);
-       if ((reg >= codec->reg_cache_size) || (reg % step))
+       if ((reg >= codec->driver->reg_cache_size) || (reg % step))
                return -EINVAL;
        while (*start == ' ')
                start++;
        if (strict_strtoul(start, 16, &value))
                return -EINVAL;
-       codec->write(codec, reg, value);
+       codec->driver->write(codec, reg, value);
        return buf_size;
 }
 
@@ -228,16 +235,7 @@ static const struct file_operations codec_reg_fops = {
 
 static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
 {
-       char codec_root[128];
-
-       if (codec->dev)
-               snprintf(codec_root, sizeof(codec_root),
-                       "%s.%s", codec->name, dev_name(codec->dev));
-       else
-               snprintf(codec_root, sizeof(codec_root),
-                       "%s", codec->name);
-
-       codec->debugfs_codec_root = debugfs_create_dir(codec_root,
+       codec->debugfs_codec_root = debugfs_create_dir(codec->name ,
                                                       debugfs_root);
        if (!codec->debugfs_codec_root) {
                printk(KERN_WARNING
@@ -273,6 +271,106 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
        debugfs_remove_recursive(codec->debugfs_codec_root);
 }
 
+static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+{
+       char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       ssize_t len, ret = 0;
+       struct snd_soc_codec *codec;
+
+       if (!buf)
+               return -ENOMEM;
+
+       list_for_each_entry(codec, &codec_list, list) {
+               len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
+                              codec->name);
+               if (len >= 0)
+                       ret += len;
+               if (ret > PAGE_SIZE) {
+                       ret = PAGE_SIZE;
+                       break;
+               }
+       }
+
+       if (ret >= 0)
+               ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static const struct file_operations codec_list_fops = {
+       .read = codec_list_read_file,
+       .llseek = default_llseek,/* read accesses f_pos */
+};
+
+static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       ssize_t len, ret = 0;
+       struct snd_soc_dai *dai;
+
+       if (!buf)
+               return -ENOMEM;
+
+       list_for_each_entry(dai, &dai_list, list) {
+               len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name);
+               if (len >= 0)
+                       ret += len;
+               if (ret > PAGE_SIZE) {
+                       ret = PAGE_SIZE;
+                       break;
+               }
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static const struct file_operations dai_list_fops = {
+       .read = dai_list_read_file,
+       .llseek = default_llseek,/* read accesses f_pos */
+};
+
+static ssize_t platform_list_read_file(struct file *file,
+                                      char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       ssize_t len, ret = 0;
+       struct snd_soc_platform *platform;
+
+       if (!buf)
+               return -ENOMEM;
+
+       list_for_each_entry(platform, &platform_list, list) {
+               len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
+                              platform->name);
+               if (len >= 0)
+                       ret += len;
+               if (ret > PAGE_SIZE) {
+                       ret = PAGE_SIZE;
+                       break;
+               }
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+
+       return ret;
+}
+
+static const struct file_operations platform_list_fops = {
+       .read = platform_list_read_file,
+       .llseek = default_llseek,/* read accesses f_pos */
+};
+
 #else
 
 static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
@@ -306,7 +404,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
        codec->ac97->dev.release = soc_ac97_device_release;
 
        dev_set_name(&codec->ac97->dev, "%d-%d:%s",
-                    codec->card->number, 0, codec->name);
+                    codec->card->snd_card->number, 0, codec->name);
        err = device_register(&codec->ac97->dev);
        if (err < 0) {
                snd_printk(KERN_ERR "Can't register ac97 bus\n");
@@ -320,24 +418,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
 static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
-           machine->symmetric_rates) {
-               dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
-                       machine->rate);
+       if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates ||
+                       rtd->dai_link->symmetric_rates) {
+               dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n",
+                               rtd->rate);
 
                ret = snd_pcm_hw_constraint_minmax(substream->runtime,
                                                   SNDRV_PCM_HW_PARAM_RATE,
-                                                  machine->rate,
-                                                  machine->rate);
+                                                  rtd->rate,
+                                                  rtd->rate);
                if (ret < 0) {
-                       dev_err(card->dev,
+                       dev_err(&rtd->dev,
                                "Unable to apply rate symmetry constraint: %d\n", ret);
                        return ret;
                }
@@ -354,20 +449,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
 static int soc_pcm_open(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_card *card = socdev->card;
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
+       struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
        int ret = 0;
 
        mutex_lock(&pcm_mutex);
 
        /* startup the audio subsystem */
-       if (cpu_dai->ops->startup) {
-               ret = cpu_dai->ops->startup(substream, cpu_dai);
+       if (cpu_dai->driver->ops->startup) {
+               ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't open interface %s\n",
                                cpu_dai->name);
@@ -375,16 +469,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                }
        }
 
-       if (platform->pcm_ops->open) {
-               ret = platform->pcm_ops->open(substream);
+       if (platform->driver->ops->open) {
+               ret = platform->driver->ops->open(substream);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
                        goto platform_err;
                }
        }
 
-       if (codec_dai->ops->startup) {
-               ret = codec_dai->ops->startup(substream, codec_dai);
+       if (codec_dai->driver->ops->startup) {
+               ret = codec_dai->driver->ops->startup(substream, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't open codec %s\n",
                                codec_dai->name);
@@ -392,10 +486,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                }
        }
 
-       if (machine->ops && machine->ops->startup) {
-               ret = machine->ops->startup(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
+               ret = rtd->dai_link->ops->startup(substream);
                if (ret < 0) {
-                       printk(KERN_ERR "asoc: %s startup failed\n", machine->name);
+                       printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
                        goto machine_err;
                }
        }
@@ -403,50 +497,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        /* Check that the codec and cpu DAI's are compatible */
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                runtime->hw.rate_min =
-                       max(codec_dai->playback.rate_min,
-                           cpu_dai->playback.rate_min);
+                       max(codec_dai_drv->playback.rate_min,
+                           cpu_dai_drv->playback.rate_min);
                runtime->hw.rate_max =
-                       min(codec_dai->playback.rate_max,
-                           cpu_dai->playback.rate_max);
+                       min(codec_dai_drv->playback.rate_max,
+                           cpu_dai_drv->playback.rate_max);
                runtime->hw.channels_min =
-                       max(codec_dai->playback.channels_min,
-                               cpu_dai->playback.channels_min);
+                       max(codec_dai_drv->playback.channels_min,
+                               cpu_dai_drv->playback.channels_min);
                runtime->hw.channels_max =
-                       min(codec_dai->playback.channels_max,
-                               cpu_dai->playback.channels_max);
+                       min(codec_dai_drv->playback.channels_max,
+                               cpu_dai_drv->playback.channels_max);
                runtime->hw.formats =
-                       codec_dai->playback.formats & cpu_dai->playback.formats;
+                       codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
                runtime->hw.rates =
-                       codec_dai->playback.rates & cpu_dai->playback.rates;
-               if (codec_dai->playback.rates
+                       codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
+               if (codec_dai_drv->playback.rates
                           & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-                       runtime->hw.rates |= cpu_dai->playback.rates;
-               if (cpu_dai->playback.rates
+                       runtime->hw.rates |= cpu_dai_drv->playback.rates;
+               if (cpu_dai_drv->playback.rates
                           & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-                       runtime->hw.rates |= codec_dai->playback.rates;
+                       runtime->hw.rates |= codec_dai_drv->playback.rates;
        } else {
                runtime->hw.rate_min =
-                       max(codec_dai->capture.rate_min,
-                           cpu_dai->capture.rate_min);
+                       max(codec_dai_drv->capture.rate_min,
+                           cpu_dai_drv->capture.rate_min);
                runtime->hw.rate_max =
-                       min(codec_dai->capture.rate_max,
-                           cpu_dai->capture.rate_max);
+                       min(codec_dai_drv->capture.rate_max,
+                           cpu_dai_drv->capture.rate_max);
                runtime->hw.channels_min =
-                       max(codec_dai->capture.channels_min,
-                               cpu_dai->capture.channels_min);
+                       max(codec_dai_drv->capture.channels_min,
+                               cpu_dai_drv->capture.channels_min);
                runtime->hw.channels_max =
-                       min(codec_dai->capture.channels_max,
-                               cpu_dai->capture.channels_max);
+                       min(codec_dai_drv->capture.channels_max,
+                               cpu_dai_drv->capture.channels_max);
                runtime->hw.formats =
-                       codec_dai->capture.formats & cpu_dai->capture.formats;
+                       codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
                runtime->hw.rates =
-                       codec_dai->capture.rates & cpu_dai->capture.rates;
-               if (codec_dai->capture.rates
+                       codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
+               if (codec_dai_drv->capture.rates
                           & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-                       runtime->hw.rates |= cpu_dai->capture.rates;
-               if (cpu_dai->capture.rates
+                       runtime->hw.rates |= cpu_dai_drv->capture.rates;
+               if (cpu_dai_drv->capture.rates
                           & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
-                       runtime->hw.rates |= codec_dai->capture.rates;
+                       runtime->hw.rates |= codec_dai_drv->capture.rates;
        }
 
        snd_pcm_limit_hw_rates(runtime);
@@ -462,7 +556,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
        }
        if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
                printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
-                       codec_dai->name, cpu_dai->name);
+                               codec_dai->name, cpu_dai->name);
                goto config_err;
        }
 
@@ -473,7 +567,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                        goto config_err;
        }
 
-       pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
+       pr_debug("asoc: %s <-> %s info:\n",
+                       codec_dai->name, cpu_dai->name);
        pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
        pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
                 runtime->hw.channels_max);
@@ -481,33 +576,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                 runtime->hw.rate_max);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               cpu_dai->playback.active++;
-               codec_dai->playback.active++;
+               cpu_dai->playback_active++;
+               codec_dai->playback_active++;
        } else {
-               cpu_dai->capture.active++;
-               codec_dai->capture.active++;
+               cpu_dai->capture_active++;
+               codec_dai->capture_active++;
        }
        cpu_dai->active++;
        codec_dai->active++;
-       card->codec->active++;
+       rtd->codec->active++;
        mutex_unlock(&pcm_mutex);
        return 0;
 
 config_err:
-       if (machine->ops && machine->ops->shutdown)
-               machine->ops->shutdown(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
+               rtd->dai_link->ops->shutdown(substream);
 
 machine_err:
-       if (codec_dai->ops->shutdown)
-               codec_dai->ops->shutdown(substream, codec_dai);
+       if (codec_dai->driver->ops->shutdown)
+               codec_dai->driver->ops->shutdown(substream, codec_dai);
 
 codec_dai_err:
-       if (platform->pcm_ops->close)
-               platform->pcm_ops->close(substream);
+       if (platform->driver->ops->close)
+               platform->driver->ops->close(substream);
 
 platform_err:
-       if (cpu_dai->ops->shutdown)
-               cpu_dai->ops->shutdown(substream, cpu_dai);
+       if (cpu_dai->driver->ops->shutdown)
+               cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 out:
        mutex_unlock(&pcm_mutex);
        return ret;
@@ -520,29 +615,25 @@ out:
  */
 static void close_delayed_work(struct work_struct *work)
 {
-       struct snd_soc_card *card = container_of(work, struct snd_soc_card,
-                                                delayed_work.work);
-       struct snd_soc_codec *codec = card->codec;
-       struct snd_soc_dai *codec_dai;
-       int i;
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
        mutex_lock(&pcm_mutex);
-       for (i = 0; i < codec->num_dai; i++) {
-               codec_dai = &codec->dai[i];
-
-               pr_debug("pop wq checking: %s status: %s waiting: %s\n",
-                        codec_dai->playback.stream_name,
-                        codec_dai->playback.active ? "active" : "inactive",
-                        codec_dai->pop_wait ? "yes" : "no");
-
-               /* are we waiting on this codec DAI stream */
-               if (codec_dai->pop_wait == 1) {
-                       codec_dai->pop_wait = 0;
-                       snd_soc_dapm_stream_event(codec,
-                               codec_dai->playback.stream_name,
-                               SND_SOC_DAPM_STREAM_STOP);
-               }
+
+       pr_debug("pop wq checking: %s status: %s waiting: %s\n",
+                codec_dai->driver->playback.stream_name,
+                codec_dai->playback_active ? "active" : "inactive",
+                codec_dai->pop_wait ? "yes" : "no");
+
+       /* are we waiting on this codec DAI stream */
+       if (codec_dai->pop_wait == 1) {
+               codec_dai->pop_wait = 0;
+               snd_soc_dapm_stream_event(rtd,
+                       codec_dai->driver->playback.stream_name,
+                       SND_SOC_DAPM_STREAM_STOP);
        }
+
        mutex_unlock(&pcm_mutex);
 }
 
@@ -554,22 +645,19 @@ static void close_delayed_work(struct work_struct *work)
 static int soc_codec_close(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
-       struct snd_soc_codec *codec = card->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = rtd->codec;
 
        mutex_lock(&pcm_mutex);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               cpu_dai->playback.active--;
-               codec_dai->playback.active--;
+               cpu_dai->playback_active--;
+               codec_dai->playback_active--;
        } else {
-               cpu_dai->capture.active--;
-               codec_dai->capture.active--;
+               cpu_dai->capture_active--;
+               codec_dai->capture_active--;
        }
 
        cpu_dai->active--;
@@ -582,27 +670,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                snd_soc_dai_digital_mute(codec_dai, 1);
 
-       if (cpu_dai->ops->shutdown)
-               cpu_dai->ops->shutdown(substream, cpu_dai);
+       if (cpu_dai->driver->ops->shutdown)
+               cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 
-       if (codec_dai->ops->shutdown)
-               codec_dai->ops->shutdown(substream, codec_dai);
+       if (codec_dai->driver->ops->shutdown)
+               codec_dai->driver->ops->shutdown(substream, codec_dai);
 
-       if (machine->ops && machine->ops->shutdown)
-               machine->ops->shutdown(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
+               rtd->dai_link->ops->shutdown(substream);
 
-       if (platform->pcm_ops->close)
-               platform->pcm_ops->close(substream);
+       if (platform->driver->ops->close)
+               platform->driver->ops->close(substream);
+       cpu_dai->runtime = NULL;
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* start delayed pop wq here for playback streams */
                codec_dai->pop_wait = 1;
-               schedule_delayed_work(&card->delayed_work,
-                       msecs_to_jiffies(card->pmdown_time));
+               schedule_delayed_work(&rtd->delayed_work,
+                       msecs_to_jiffies(rtd->pmdown_time));
        } else {
                /* capture streams can be powered down now */
-               snd_soc_dapm_stream_event(codec,
-                       codec_dai->capture.stream_name,
+               snd_soc_dapm_stream_event(rtd,
+                       codec_dai->driver->capture.stream_name,
                        SND_SOC_DAPM_STREAM_STOP);
        }
 
@@ -618,43 +707,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
 static int soc_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
-       struct snd_soc_codec *codec = card->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret = 0;
 
        mutex_lock(&pcm_mutex);
 
-       if (machine->ops && machine->ops->prepare) {
-               ret = machine->ops->prepare(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
+               ret = rtd->dai_link->ops->prepare(substream);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: machine prepare error\n");
                        goto out;
                }
        }
 
-       if (platform->pcm_ops->prepare) {
-               ret = platform->pcm_ops->prepare(substream);
+       if (platform->driver->ops->prepare) {
+               ret = platform->driver->ops->prepare(substream);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: platform prepare error\n");
                        goto out;
                }
        }
 
-       if (codec_dai->ops->prepare) {
-               ret = codec_dai->ops->prepare(substream, codec_dai);
+       if (codec_dai->driver->ops->prepare) {
+               ret = codec_dai->driver->ops->prepare(substream, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: codec DAI prepare error\n");
                        goto out;
                }
        }
 
-       if (cpu_dai->ops->prepare) {
-               ret = cpu_dai->ops->prepare(substream, cpu_dai);
+       if (cpu_dai->driver->ops->prepare) {
+               ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: cpu DAI prepare error\n");
                        goto out;
@@ -665,16 +750,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
            codec_dai->pop_wait) {
                codec_dai->pop_wait = 0;
-               cancel_delayed_work(&card->delayed_work);
+               cancel_delayed_work(&rtd->delayed_work);
        }
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               snd_soc_dapm_stream_event(codec,
-                                         codec_dai->playback.stream_name,
+               snd_soc_dapm_stream_event(rtd,
+                                         codec_dai->driver->playback.stream_name,
                                          SND_SOC_DAPM_STREAM_START);
        else
-               snd_soc_dapm_stream_event(codec,
-                                         codec_dai->capture.stream_name,
+               snd_soc_dapm_stream_event(rtd,
+                                         codec_dai->driver->capture.stream_name,
                                          SND_SOC_DAPM_STREAM_START);
 
        snd_soc_dai_digital_mute(codec_dai, 0);
@@ -693,26 +778,23 @@ static int soc_pcm_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_device *socdev = rtd->socdev;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret = 0;
 
        mutex_lock(&pcm_mutex);
 
-       if (machine->ops && machine->ops->hw_params) {
-               ret = machine->ops->hw_params(substream, params);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
+               ret = rtd->dai_link->ops->hw_params(substream, params);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: machine hw_params failed\n");
                        goto out;
                }
        }
 
-       if (codec_dai->ops->hw_params) {
-               ret = codec_dai->ops->hw_params(substream, params, codec_dai);
+       if (codec_dai->driver->ops->hw_params) {
+               ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: can't set codec %s hw params\n",
                                codec_dai->name);
@@ -720,8 +802,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       if (cpu_dai->ops->hw_params) {
-               ret = cpu_dai->ops->hw_params(substream, params, cpu_dai);
+       if (cpu_dai->driver->ops->hw_params) {
+               ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: interface %s hw params failed\n",
                                cpu_dai->name);
@@ -729,8 +811,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       if (platform->pcm_ops->hw_params) {
-               ret = platform->pcm_ops->hw_params(substream, params);
+       if (platform->driver->ops->hw_params) {
+               ret = platform->driver->ops->hw_params(substream, params);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: platform %s hw params failed\n",
                                platform->name);
@@ -738,23 +820,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       machine->rate = params_rate(params);
+       rtd->rate = params_rate(params);
 
 out:
        mutex_unlock(&pcm_mutex);
        return ret;
 
 platform_err:
-       if (cpu_dai->ops->hw_free)
-               cpu_dai->ops->hw_free(substream, cpu_dai);
+       if (cpu_dai->driver->ops->hw_free)
+               cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 
 interface_err:
-       if (codec_dai->ops->hw_free)
-               codec_dai->ops->hw_free(substream, codec_dai);
+       if (codec_dai->driver->ops->hw_free)
+               codec_dai->driver->ops->hw_free(substream, codec_dai);
 
 codec_err:
-       if (machine->ops && machine->ops->hw_free)
-               machine->ops->hw_free(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
+               rtd->dai_link->ops->hw_free(substream);
 
        mutex_unlock(&pcm_mutex);
        return ret;
@@ -766,13 +848,10 @@ codec_err:
 static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
-       struct snd_soc_codec *codec = card->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_codec *codec = rtd->codec;
 
        mutex_lock(&pcm_mutex);
 
@@ -781,19 +860,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
                snd_soc_dai_digital_mute(codec_dai, 1);
 
        /* free any machine hw params */
-       if (machine->ops && machine->ops->hw_free)
-               machine->ops->hw_free(substream);
+       if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
+               rtd->dai_link->ops->hw_free(substream);
 
        /* free any DMA resources */
-       if (platform->pcm_ops->hw_free)
-               platform->pcm_ops->hw_free(substream);
+       if (platform->driver->ops->hw_free)
+               platform->driver->ops->hw_free(substream);
 
        /* now free hw params for the DAI's  */
-       if (codec_dai->ops->hw_free)
-               codec_dai->ops->hw_free(substream, codec_dai);
+       if (codec_dai->driver->ops->hw_free)
+               codec_dai->driver->ops->hw_free(substream, codec_dai);
 
-       if (cpu_dai->ops->hw_free)
-               cpu_dai->ops->hw_free(substream, cpu_dai);
+       if (cpu_dai->driver->ops->hw_free)
+               cpu_dai->driver->ops->hw_free(substream, cpu_dai);
 
        mutex_unlock(&pcm_mutex);
        return 0;
@@ -802,28 +881,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
 static int soc_pcm_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_card *card= socdev->card;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       if (codec_dai->ops->trigger) {
-               ret = codec_dai->ops->trigger(substream, cmd, codec_dai);
+       if (codec_dai->driver->ops->trigger) {
+               ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
                if (ret < 0)
                        return ret;
        }
 
-       if (platform->pcm_ops->trigger) {
-               ret = platform->pcm_ops->trigger(substream, cmd);
+       if (platform->driver->ops->trigger) {
+               ret = platform->driver->ops->trigger(substream, cmd);
                if (ret < 0)
                        return ret;
        }
 
-       if (cpu_dai->ops->trigger) {
-               ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai);
+       if (cpu_dai->driver->ops->trigger) {
+               ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
                if (ret < 0)
                        return ret;
        }
@@ -838,27 +914,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_device *socdev = rtd->socdev;
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai_link *machine = rtd->dai;
-       struct snd_soc_dai *cpu_dai = machine->cpu_dai;
-       struct snd_soc_dai *codec_dai = machine->codec_dai;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_uframes_t offset = 0;
        snd_pcm_sframes_t delay = 0;
 
-       if (platform->pcm_ops->pointer)
-               offset = platform->pcm_ops->pointer(substream);
+       if (platform->driver->ops->pointer)
+               offset = platform->driver->ops->pointer(substream);
 
-       if (cpu_dai->ops->delay)
-               delay += cpu_dai->ops->delay(substream, cpu_dai);
+       if (cpu_dai->driver->ops->delay)
+               delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
 
-       if (codec_dai->ops->delay)
-               delay += codec_dai->ops->delay(substream, codec_dai);
+       if (codec_dai->driver->ops->delay)
+               delay += codec_dai->driver->ops->delay(substream, codec_dai);
 
-       if (platform->delay)
-               delay += platform->delay(substream, codec_dai);
+       if (platform->driver->delay)
+               delay += platform->driver->delay(substream, codec_dai);
 
        runtime->delay = delay;
 
@@ -881,104 +954,111 @@ static struct snd_pcm_ops soc_pcm_ops = {
 static int soc_suspend(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;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
-       struct snd_soc_codec *codec = card->codec;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
        int i;
 
        /* If the initialization of this soc device failed, there is no codec
         * associated with it. Just bail out in this case.
         */
-       if (!codec)
+       if (list_empty(&card->codec_dev_list))
                return 0;
 
        /* Due to the resume being scheduled into a workqueue we could
        * suspend before that's finished - wait for it to complete.
         */
-       snd_power_lock(codec->card);
-       snd_power_wait(codec->card, SNDRV_CTL_POWER_D0);
-       snd_power_unlock(codec->card);
+       snd_power_lock(card->snd_card);
+       snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
+       snd_power_unlock(card->snd_card);
 
        /* we're going to block userspace touching us until resume completes */
-       snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
+       snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
 
        /* mute any active DAC's */
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *dai = card->rtd[i].codec_dai;
+               struct snd_soc_dai_driver *drv = dai->driver;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (dai->ops->digital_mute && dai->playback.active)
-                       dai->ops->digital_mute(dai, 1);
+               if (drv->ops->digital_mute && dai->playback_active)
+                       drv->ops->digital_mute(dai, 1);
        }
 
        /* suspend all pcms */
-       for (i = 0; i < card->num_links; i++) {
-               if (card->dai_link[i].ignore_suspend)
+       for (i = 0; i < card->num_rtd; i++) {
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               snd_pcm_suspend_all(card->dai_link[i].pcm);
+               snd_pcm_suspend_all(card->rtd[i].pcm);
        }
 
        if (card->suspend_pre)
                card->suspend_pre(pdev, PMSG_SUSPEND);
 
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai  *cpu_dai = card->dai_link[i].cpu_dai;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               struct snd_soc_platform *platform = card->rtd[i].platform;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (cpu_dai->suspend && !cpu_dai->ac97_control)
-                       cpu_dai->suspend(cpu_dai);
-               if (platform->suspend)
-                       platform->suspend(&card->dai_link[i]);
+               if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
+                       cpu_dai->driver->suspend(cpu_dai);
+               if (platform->driver->suspend && !platform->suspended) {
+                       platform->driver->suspend(cpu_dai);
+                       platform->suspended = 1;
+               }
        }
 
        /* close any waiting streams and save state */
-       run_delayed_work(&card->delayed_work);
-       codec->suspend_bias_level = codec->bias_level;
+       for (i = 0; i < card->num_rtd; i++) {
+               run_delayed_work(&card->rtd[i].delayed_work);
+               card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level;
+       }
 
-       for (i = 0; i < codec->num_dai; i++) {
-               char *stream = codec->dai[i].playback.stream_name;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (stream != NULL)
-                       snd_soc_dapm_stream_event(codec, stream,
+               if (driver->playback.stream_name != NULL)
+                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
                                SND_SOC_DAPM_STREAM_SUSPEND);
-               stream = codec->dai[i].capture.stream_name;
-               if (stream != NULL)
-                       snd_soc_dapm_stream_event(codec, stream,
+
+               if (driver->capture.stream_name != NULL)
+                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
                                SND_SOC_DAPM_STREAM_SUSPEND);
        }
 
-       /* If there are paths active then the CODEC will be held with
-        * bias _ON and should not be suspended. */
-       if (codec_dev->suspend) {
-               switch (codec->bias_level) {
-               case SND_SOC_BIAS_STANDBY:
-               case SND_SOC_BIAS_OFF:
-                       codec_dev->suspend(pdev, PMSG_SUSPEND);
-                       break;
-               default:
-                       dev_dbg(socdev->dev, "CODEC is on over suspend\n");
-                       break;
+       /* suspend all CODECs */
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_codec *codec = card->rtd[i].codec;
+               /* If there are paths active then the CODEC will be held with
+                * bias _ON and should not be suspended. */
+               if (!codec->suspended && codec->driver->suspend) {
+                       switch (codec->bias_level) {
+                       case SND_SOC_BIAS_STANDBY:
+                       case SND_SOC_BIAS_OFF:
+                               codec->driver->suspend(codec, PMSG_SUSPEND);
+                               codec->suspended = 1;
+                               break;
+                       default:
+                               dev_dbg(codec->dev, "CODEC is on over suspend\n");
+                               break;
+                       }
                }
        }
 
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (cpu_dai->suspend && cpu_dai->ac97_control)
-                       cpu_dai->suspend(cpu_dai);
+               if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
+                       cpu_dai->driver->suspend(cpu_dai);
        }
 
        if (card->suspend_post)
@@ -992,127 +1072,127 @@ static int soc_suspend(struct device *dev)
  */
 static void soc_resume_deferred(struct work_struct *work)
 {
-       struct snd_soc_card *card = container_of(work,
-                                                struct snd_soc_card,
-                                                deferred_resume_work);
-       struct snd_soc_device *socdev = card->socdev;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
-       struct snd_soc_codec *codec = card->codec;
-       struct platform_device *pdev = to_platform_device(socdev->dev);
+       struct snd_soc_card *card =
+                       container_of(work, struct snd_soc_card, deferred_resume_work);
+       struct platform_device *pdev = to_platform_device(card->dev);
        int i;
 
        /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
         * so userspace apps are blocked from touching us
         */
 
-       dev_dbg(socdev->dev, "starting resume work\n");
+       dev_dbg(card->dev, "starting resume work\n");
 
        /* Bring us up into D2 so that DAPM starts enabling things */
-       snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2);
+       snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
 
        if (card->resume_pre)
                card->resume_pre(pdev);
 
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+       /* resume AC97 DAIs */
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (cpu_dai->resume && cpu_dai->ac97_control)
-                       cpu_dai->resume(cpu_dai);
-       }
-
-       /* If the CODEC was idle over suspend then it will have been
-        * left with bias OFF or STANDBY and suspended so we must now
-        * resume.  Otherwise the suspend was suppressed.
-        */
-       if (codec_dev->resume) {
-               switch (codec->bias_level) {
-               case SND_SOC_BIAS_STANDBY:
-               case SND_SOC_BIAS_OFF:
-                       codec_dev->resume(pdev);
-                       break;
-               default:
-                       dev_dbg(socdev->dev, "CODEC was on over suspend\n");
-                       break;
+               if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
+                       cpu_dai->driver->resume(cpu_dai);
+       }
+
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_codec *codec = card->rtd[i].codec;
+               /* If the CODEC was idle over suspend then it will have been
+                * left with bias OFF or STANDBY and suspended so we must now
+                * resume.  Otherwise the suspend was suppressed.
+                */
+               if (codec->driver->resume && codec->suspended) {
+                       switch (codec->bias_level) {
+                       case SND_SOC_BIAS_STANDBY:
+                       case SND_SOC_BIAS_OFF:
+                               codec->driver->resume(codec);
+                               codec->suspended = 0;
+                               break;
+                       default:
+                               dev_dbg(codec->dev, "CODEC was on over suspend\n");
+                               break;
+                       }
                }
        }
 
-       for (i = 0; i < codec->num_dai; i++) {
-               char *stream = codec->dai[i].playback.stream_name;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (stream != NULL)
-                       snd_soc_dapm_stream_event(codec, stream,
+               if (driver->playback.stream_name != NULL)
+                       snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
                                SND_SOC_DAPM_STREAM_RESUME);
-               stream = codec->dai[i].capture.stream_name;
-               if (stream != NULL)
-                       snd_soc_dapm_stream_event(codec, stream,
+
+               if (driver->capture.stream_name != NULL)
+                       snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
                                SND_SOC_DAPM_STREAM_RESUME);
        }
 
        /* unmute any active DACs */
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *dai = card->rtd[i].codec_dai;
+               struct snd_soc_dai_driver *drv = dai->driver;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (dai->ops->digital_mute && dai->playback.active)
-                       dai->ops->digital_mute(dai, 0);
+               if (drv->ops->digital_mute && dai->playback_active)
+                       drv->ops->digital_mute(dai, 0);
        }
 
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               struct snd_soc_platform *platform = card->rtd[i].platform;
 
-               if (card->dai_link[i].ignore_suspend)
+               if (card->rtd[i].dai_link->ignore_suspend)
                        continue;
 
-               if (cpu_dai->resume && !cpu_dai->ac97_control)
-                       cpu_dai->resume(cpu_dai);
-               if (platform->resume)
-                       platform->resume(&card->dai_link[i]);
+               if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
+                       cpu_dai->driver->resume(cpu_dai);
+               if (platform->driver->resume && platform->suspended) {
+                       platform->driver->resume(cpu_dai);
+                       platform->suspended = 0;
+               }
        }
 
        if (card->resume_post)
                card->resume_post(pdev);
 
-       dev_dbg(socdev->dev, "resume work completed\n");
+       dev_dbg(card->dev, "resume work completed\n");
 
        /* userspace can access us now we are back as we were before */
-       snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
+       snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
 }
 
 /* powers up audio subsystem after a suspend */
 static int soc_resume(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;
-       struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
-
-       /* If the initialization of this soc device failed, there is no codec
-        * associated with it. Just bail out in this case.
-        */
-       if (!card->codec)
-               return 0;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       int i;
 
        /* AC97 devices might have other drivers hanging off them so
         * need to resume immediately.  Other drivers don't have that
         * problem and may take a substantial amount of time to resume
         * due to I/O costs and anti-pop so handle them out of line.
         */
-       if (cpu_dai->ac97_control) {
-               dev_dbg(socdev->dev, "Resuming AC97 immediately\n");
-               soc_resume_deferred(&card->deferred_resume_work);
-       } else {
-               dev_dbg(socdev->dev, "Scheduling resume work\n");
-               if (!schedule_work(&card->deferred_resume_work))
-                       dev_err(socdev->dev, "resume work item may be lost\n");
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
+               if (cpu_dai->driver->ac97_control) {
+                       dev_dbg(dev, "Resuming AC97 immediately\n");
+                       soc_resume_deferred(&card->deferred_resume_work);
+               } else {
+                       dev_dbg(dev, "Scheduling resume work\n");
+                       if (!schedule_work(&card->deferred_resume_work))
+                               dev_err(dev, "resume work item may be lost\n");
+               }
        }
 
        return 0;
@@ -1125,198 +1205,440 @@ static int soc_resume(struct device *dev)
 static struct snd_soc_dai_ops null_dai_ops = {
 };
 
-static void snd_soc_instantiate_card(struct snd_soc_card *card)
+static int soc_bind_dai_link(struct snd_soc_card *card, int num)
 {
-       struct platform_device *pdev = container_of(card->dev,
-                                                   struct platform_device,
-                                                   dev);
-       struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
+       struct snd_soc_dai_link *dai_link = &card->dai_link[num];
+       struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
        struct snd_soc_codec *codec;
        struct snd_soc_platform *platform;
-       struct snd_soc_dai *dai;
-       int i, found, ret, ac97;
+       struct snd_soc_dai *codec_dai, *cpu_dai;
 
-       if (card->instantiated)
-               return;
+       if (rtd->complete)
+               return 1;
+       dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
 
-       found = 0;
-       list_for_each_entry(platform, &platform_list, list)
-               if (card->platform == platform) {
-                       found = 1;
-                       break;
+       /* do we already have the CPU DAI for this link ? */
+       if (rtd->cpu_dai) {
+               goto find_codec;
+       }
+       /* no, then find CPU DAI from registered DAIs*/
+       list_for_each_entry(cpu_dai, &dai_list, list) {
+               if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
+
+                       if (!try_module_get(cpu_dai->dev->driver->owner))
+                               return -ENODEV;
+
+                       rtd->cpu_dai = cpu_dai;
+                       goto find_codec;
                }
-       if (!found) {
-               dev_dbg(card->dev, "Platform %s not registered\n",
-                       card->platform->name);
-               return;
        }
+       dev_dbg(card->dev, "CPU DAI %s not registered\n",
+                       dai_link->cpu_dai_name);
 
-       ac97 = 0;
-       for (i = 0; i < card->num_links; i++) {
-               found = 0;
-               list_for_each_entry(dai, &dai_list, list)
-                       if (card->dai_link[i].cpu_dai == dai) {
-                               found = 1;
-                               break;
+find_codec:
+       /* do we already have the CODEC for this link ? */
+       if (rtd->codec) {
+               goto find_platform;
+       }
+
+       /* no, then find CODEC from registered CODECs*/
+       list_for_each_entry(codec, &codec_list, list) {
+               if (!strcmp(codec->name, dai_link->codec_name)) {
+                       rtd->codec = codec;
+
+                       if (!try_module_get(codec->dev->driver->owner))
+                               return -ENODEV;
+
+                       /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
+                       list_for_each_entry(codec_dai, &dai_list, list) {
+                               if (codec->dev == codec_dai->dev &&
+                                               !strcmp(codec_dai->name, dai_link->codec_dai_name)) {
+                                       rtd->codec_dai = codec_dai;
+                                       goto find_platform;
+                               }
                        }
-               if (!found) {
-                       dev_dbg(card->dev, "DAI %s not registered\n",
-                               card->dai_link[i].cpu_dai->name);
-                       return;
+                       dev_dbg(card->dev, "CODEC DAI %s not registered\n",
+                                       dai_link->codec_dai_name);
+
+                       goto find_platform;
                }
+       }
+       dev_dbg(card->dev, "CODEC %s not registered\n",
+                       dai_link->codec_name);
 
-               if (card->dai_link[i].cpu_dai->ac97_control)
-                       ac97 = 1;
+find_platform:
+       /* do we already have the CODEC DAI for this link ? */
+       if (rtd->platform) {
+               goto out;
        }
+       /* no, then find CPU DAI from registered DAIs*/
+       list_for_each_entry(platform, &platform_list, list) {
+               if (!strcmp(platform->name, dai_link->platform_name)) {
 
-       for (i = 0; i < card->num_links; i++) {
-               if (!card->dai_link[i].codec_dai->ops)
-                       card->dai_link[i].codec_dai->ops = &null_dai_ops;
+                       if (!try_module_get(platform->dev->driver->owner))
+                               return -ENODEV;
+
+                       rtd->platform = platform;
+                       goto out;
+               }
        }
 
-       /* If we have AC97 in the system then don't wait for the
-        * codec.  This will need revisiting if we have to handle
-        * systems with mixed AC97 and non-AC97 parts.  Only check for
-        * DAIs currently; we can't do this per link since some AC97
-        * codecs have non-AC97 DAIs.
-        */
-       if (!ac97)
-               for (i = 0; i < card->num_links; i++) {
-                       found = 0;
-                       list_for_each_entry(dai, &dai_list, list)
-                               if (card->dai_link[i].codec_dai == dai) {
-                                       found = 1;
-                                       break;
-                               }
-                       if (!found) {
-                               dev_dbg(card->dev, "DAI %s not registered\n",
-                                       card->dai_link[i].codec_dai->name);
-                               return;
-                       }
+       dev_dbg(card->dev, "platform %s not registered\n",
+                       dai_link->platform_name);
+       return 0;
+
+out:
+       /* mark rtd as complete if we found all 4 of our client devices */
+       if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
+               rtd->complete = 1;
+               card->num_rtd++;
+       }
+       return 1;
+}
+
+static void soc_remove_dai_link(struct snd_soc_card *card, int num)
+{
+       struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
+       int err;
+
+       /* unregister the rtd device */
+       if (rtd->dev_registered) {
+               device_remove_file(&rtd->dev, &dev_attr_pmdown_time);
+               device_unregister(&rtd->dev);
+               rtd->dev_registered = 0;
+       }
+
+       /* remove the CODEC DAI */
+       if (codec_dai && codec_dai->probed) {
+               if (codec_dai->driver->remove) {
+                       err = codec_dai->driver->remove(codec_dai);
+                       if (err < 0)
+                               printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
                }
+               codec_dai->probed = 0;
+               list_del(&codec_dai->card_list);
+       }
 
-       /* Note that we do not current check for codec components */
+       /* remove the platform */
+       if (platform && platform->probed) {
+               if (platform->driver->remove) {
+                       err = platform->driver->remove(platform);
+                       if (err < 0)
+                               printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+               }
+               platform->probed = 0;
+               list_del(&platform->card_list);
+               module_put(platform->dev->driver->owner);
+       }
 
-       dev_dbg(card->dev, "All components present, instantiating\n");
+       /* remove the CODEC */
+       if (codec && codec->probed) {
+               if (codec->driver->remove) {
+                       err = codec->driver->remove(codec);
+                       if (err < 0)
+                               printk(KERN_ERR "asoc: failed to remove %s\n", codec->name);
+               }
 
-       /* Found everything, bring it up */
-       card->pmdown_time = pmdown_time;
+               /* Make sure all DAPM widgets are freed */
+               snd_soc_dapm_free(codec);
 
-       if (card->probe) {
-               ret = card->probe(pdev);
-               if (ret < 0)
-                       return;
+               soc_cleanup_codec_debugfs(codec);
+               device_remove_file(&rtd->dev, &dev_attr_codec_reg);
+               codec->probed = 0;
+               list_del(&codec->card_list);
+               module_put(codec->dev->driver->owner);
        }
 
-       for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
-               if (cpu_dai->probe) {
-                       ret = cpu_dai->probe(pdev, cpu_dai);
-                       if (ret < 0)
-                               goto cpu_dai_err;
+       /* remove the cpu_dai */
+       if (cpu_dai && cpu_dai->probed) {
+               if (cpu_dai->driver->remove) {
+                       err = cpu_dai->driver->remove(cpu_dai);
+                       if (err < 0)
+                               printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
                }
+               cpu_dai->probed = 0;
+               list_del(&cpu_dai->card_list);
+               module_put(cpu_dai->dev->driver->owner);
        }
+}
 
-       if (codec_dev->probe) {
-               ret = codec_dev->probe(pdev);
-               if (ret < 0)
-                       goto cpu_dai_err;
+static void rtd_release(struct device *dev) {}
+
+static int soc_probe_dai_link(struct snd_soc_card *card, int num)
+{
+       struct snd_soc_dai_link *dai_link = &card->dai_link[num];
+       struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
+       int ret;
+
+       dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
+
+       /* config components */
+       codec_dai->codec = codec;
+       codec->card = card;
+       cpu_dai->platform = platform;
+       rtd->card = card;
+       rtd->dev.parent = card->dev;
+       codec_dai->card = card;
+       cpu_dai->card = card;
+
+       /* set default power off timeout */
+       rtd->pmdown_time = pmdown_time;
+
+       /* probe the cpu_dai */
+       if (!cpu_dai->probed) {
+               if (cpu_dai->driver->probe) {
+                       ret = cpu_dai->driver->probe(cpu_dai);
+                       if (ret < 0) {
+                               printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
+                                               cpu_dai->name);
+                               return ret;
+                       }
+               }
+               cpu_dai->probed = 1;
+               /* mark cpu_dai as probed and add to card cpu_dai list */
+               list_add(&cpu_dai->card_list, &card->dai_dev_list);
        }
-       codec = card->codec;
 
-       if (platform->probe) {
-               ret = platform->probe(pdev);
-               if (ret < 0)
-                       goto platform_err;
+       /* probe the CODEC */
+       if (!codec->probed) {
+               if (codec->driver->probe) {
+                       ret = codec->driver->probe(codec);
+                       if (ret < 0) {
+                               printk(KERN_ERR "asoc: failed to probe CODEC %s\n",
+                                               codec->name);
+                               return ret;
+                       }
+               }
+
+               soc_init_codec_debugfs(codec);
+
+               /* mark codec as probed and add to card codec list */
+               codec->probed = 1;
+               list_add(&codec->card_list, &card->codec_dev_list);
        }
 
-       /* DAPM stream work */
-       INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
-#ifdef CONFIG_PM
-       /* deferred resume work */
-       INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
-#endif
+       /* probe the platform */
+       if (!platform->probed) {
+               if (platform->driver->probe) {
+                       ret = platform->driver->probe(platform);
+                       if (ret < 0) {
+                               printk(KERN_ERR "asoc: failed to probe platform %s\n",
+                                               platform->name);
+                               return ret;
+                       }
+               }
+               /* mark platform as probed and add to card platform list */
+               platform->probed = 1;
+               list_add(&platform->card_list, &card->platform_dev_list);
+       }
 
-       for (i = 0; i < card->num_links; i++) {
-               if (card->dai_link[i].init) {
-                       ret = card->dai_link[i].init(codec);
+       /* probe the CODEC DAI */
+       if (!codec_dai->probed) {
+               if (codec_dai->driver->probe) {
+                       ret = codec_dai->driver->probe(codec_dai);
                        if (ret < 0) {
-                               printk(KERN_ERR "asoc: failed to init %s\n",
-                                       card->dai_link[i].stream_name);
-                               continue;
+                               printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
+                                               codec_dai->name);
+                               return ret;
                        }
                }
-               if (card->dai_link[i].codec_dai->ac97_control)
-                       ac97 = 1;
+
+               /* mark cpu_dai as probed and add to card cpu_dai list */
+               codec_dai->probed = 1;
+               list_add(&codec_dai->card_list, &card->dai_dev_list);
        }
 
-       snprintf(codec->card->shortname, sizeof(codec->card->shortname),
-                "%s",  card->name);
-       snprintf(codec->card->longname, sizeof(codec->card->longname),
-                "%s (%s)", card->name, codec->name);
+       /* DAPM dai link stream work */
+       INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
+
+       /* now that all clients have probed, initialise the DAI link */
+       if (dai_link->init) {
+               ret = dai_link->init(rtd);
+               if (ret < 0) {
+                       printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name);
+                       return ret;
+               }
+       }
 
        /* Make sure all DAPM widgets are instantiated */
        snd_soc_dapm_new_widgets(codec);
+       snd_soc_dapm_sync(codec);
 
-       ret = snd_card_register(codec->card);
+       /* register the rtd device */
+       rtd->dev.release = rtd_release;
+       rtd->dev.init_name = dai_link->name;
+       ret = device_register(&rtd->dev);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
-                               codec->name);
-               goto card_err;
+               printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret);
+               return ret;
        }
 
-       mutex_lock(&codec->mutex);
+       rtd->dev_registered = 1;
+       ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time);
+       if (ret < 0)
+               printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+
+       /* add DAPM sysfs entries for this codec */
+       ret = snd_soc_dapm_sys_add(&rtd->dev);
+       if (ret < 0)
+               printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n");
+
+       /* add codec sysfs entries */
+       ret = device_create_file(&rtd->dev, &dev_attr_codec_reg);
+       if (ret < 0)
+               printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
+
+       /* create the pcm */
+       ret = soc_new_pcm(rtd, num);
+       if (ret < 0) {
+               printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+               return ret;
+       }
+
+       /* add platform data for AC97 devices */
+       if (rtd->codec_dai->driver->ac97_control)
+               snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
+
+       return 0;
+}
+
 #ifdef CONFIG_SND_SOC_AC97_BUS
+static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
+{
+       int ret;
+
        /* Only instantiate AC97 if not already done by the adaptor
         * for the generic AC97 subsystem.
         */
-       if (ac97 && strcmp(codec->name, "AC97") != 0) {
-               ret = soc_ac97_dev_register(codec);
+       if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) {
+               /*
+                * It is possible that the AC97 device is already registered to
+                * the device subsystem. This happens when the device is created
+                * via snd_ac97_mixer(). Currently only SoC codec that does so
+                * is the generic AC97 glue but others migh emerge.
+                *
+                * In those cases we don't try to register the device again.
+                */
+               if (!rtd->codec->ac97_created)
+                       return 0;
+
+               ret = soc_ac97_dev_register(rtd->codec);
                if (ret < 0) {
                        printk(KERN_ERR "asoc: AC97 device register failed\n");
-                       snd_card_free(codec->card);
-                       mutex_unlock(&codec->mutex);
-                       goto card_err;
+                       return ret;
                }
+
+               rtd->codec->ac97_registered = 1;
+       }
+       return 0;
+}
+
+static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
+{
+       if (codec->ac97_registered) {
+               soc_ac97_dev_unregister(codec);
+               codec->ac97_registered = 0;
        }
+}
 #endif
 
-       ret = snd_soc_dapm_sys_add(card->socdev->dev);
-       if (ret < 0)
-               printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
+static void snd_soc_instantiate_card(struct snd_soc_card *card)
+{
+       struct platform_device *pdev = to_platform_device(card->dev);
+       int ret, i;
 
-       ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time);
-       if (ret < 0)
-               printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+       mutex_lock(&card->mutex);
 
-       ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg);
-       if (ret < 0)
-               printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
+       if (card->instantiated) {
+               mutex_unlock(&card->mutex);
+               return;
+       }
 
-       soc_init_codec_debugfs(codec);
-       mutex_unlock(&codec->mutex);
+       /* bind DAIs */
+       for (i = 0; i < card->num_links; i++)
+               soc_bind_dai_link(card, i);
 
-       card->instantiated = 1;
+       /* bind completed ? */
+       if (card->num_rtd != card->num_links) {
+               mutex_unlock(&card->mutex);
+               return;
+       }
 
-       return;
+       /* card bind complete so register a sound card */
+       ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                       card->owner, 0, &card->snd_card);
+       if (ret < 0) {
+               printk(KERN_ERR "asoc: can't create sound card for card %s\n",
+                       card->name);
+               mutex_unlock(&card->mutex);
+               return;
+       }
+       card->snd_card->dev = card->dev;
 
-card_err:
-       if (platform->remove)
-               platform->remove(pdev);
+#ifdef CONFIG_PM
+       /* deferred resume work */
+       INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
+#endif
 
-platform_err:
-       if (codec_dev->remove)
-               codec_dev->remove(pdev);
+       /* initialise the sound card only once */
+       if (card->probe) {
+               ret = card->probe(pdev);
+               if (ret < 0)
+                       goto card_probe_error;
+       }
 
-cpu_dai_err:
-       for (i--; i >= 0; i--) {
-               struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
-               if (cpu_dai->remove)
-                       cpu_dai->remove(pdev, cpu_dai);
+       for (i = 0; i < card->num_links; i++) {
+               ret = soc_probe_dai_link(card, i);
+               if (ret < 0) {
+                       pr_err("asoc: failed to instantiate card %s: %d\n",
+                              card->name, ret);
+                       goto probe_dai_err;
+               }
        }
 
+       snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
+                "%s",  card->name);
+       snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
+                "%s", card->name);
+
+       ret = snd_card_register(card->snd_card);
+       if (ret < 0) {
+               printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+               goto probe_dai_err;
+       }
+
+#ifdef CONFIG_SND_SOC_AC97_BUS
+       /* register any AC97 codecs */
+       for (i = 0; i < card->num_rtd; i++) {
+                       ret = soc_register_ac97_dai_link(&card->rtd[i]);
+                       if (ret < 0) {
+                               printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+                               goto probe_dai_err;
+                       }
+               }
+#endif
+
+       card->instantiated = 1;
+       mutex_unlock(&card->mutex);
+       return;
+
+probe_dai_err:
+       for (i = 0; i < card->num_links; i++)
+               soc_remove_dai_link(card, i);
+
+card_probe_error:
        if (card->remove)
                card->remove(pdev);
+
+       snd_card_free(card->snd_card);
+
+       mutex_unlock(&card->mutex);
 }
 
 /*
@@ -1333,15 +1655,15 @@ static void snd_soc_instantiate_cards(void)
 /* probes a new socdev */
 static int soc_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
        int ret = 0;
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-
-       /* Bodge while we push things out of socdev */
-       card->socdev = socdev;
 
        /* Bodge while we unpick instantiation */
        card->dev = &pdev->dev;
+       INIT_LIST_HEAD(&card->dai_dev_list);
+       INIT_LIST_HEAD(&card->codec_dev_list);
+       INIT_LIST_HEAD(&card->platform_dev_list);
+
        ret = snd_soc_register_card(card);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to register card\n");
@@ -1354,50 +1676,49 @@ static int soc_probe(struct platform_device *pdev)
 /* removes a socdev */
 static int soc_remove(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
        int i;
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
 
-       if (card->instantiated) {
-               run_delayed_work(&card->delayed_work);
-
-               if (platform->remove)
-                       platform->remove(pdev);
+               if (card->instantiated) {
 
-               if (codec_dev->remove)
-                       codec_dev->remove(pdev);
-
-               for (i = 0; i < card->num_links; i++) {
-                       struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
-                       if (cpu_dai->remove)
-                               cpu_dai->remove(pdev, cpu_dai);
+               /* make sure any delayed work runs */
+               for (i = 0; i < card->num_rtd; i++) {
+                       struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+                       run_delayed_work(&rtd->delayed_work);
                }
 
+               /* remove and free each DAI */
+               for (i = 0; i < card->num_rtd; i++)
+                       soc_remove_dai_link(card, i);
+
+               /* remove the card */
                if (card->remove)
                        card->remove(pdev);
-       }
 
+               kfree(card->rtd);
+               snd_card_free(card->snd_card);
+       }
        snd_soc_unregister_card(card);
-
        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;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       int i;
 
        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);
+       for (i = 0; i < card->num_rtd; i++) {
+               struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+               run_delayed_work(&rtd->delayed_work);
+       }
 
-       snd_soc_dapm_shutdown(socdev);
+       snd_soc_dapm_shutdown(card);
 
        return 0;
 }
@@ -1420,53 +1741,42 @@ static struct platform_driver soc_driver = {
 };
 
 /* create a new pcm */
-static int soc_new_pcm(struct snd_soc_device *socdev,
-       struct snd_soc_dai_link *dai_link, int num)
-{
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_codec *codec = card->codec;
-       struct snd_soc_platform *platform = card->platform;
-       struct snd_soc_dai *codec_dai = dai_link->codec_dai;
-       struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
-       struct snd_soc_pcm_runtime *rtd;
+static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
+{
+       struct snd_soc_codec *codec = rtd->codec;
+       struct snd_soc_platform *platform = rtd->platform;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct snd_pcm *pcm;
        char new_name[64];
        int ret = 0, playback = 0, capture = 0;
 
-       rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
-       if (rtd == NULL)
-               return -ENOMEM;
-
-       rtd->dai = dai_link;
-       rtd->socdev = socdev;
-       codec_dai->codec = card->codec;
-
        /* check client and interface hw capabilities */
        snprintf(new_name, sizeof(new_name), "%s %s-%d",
-                dai_link->stream_name, codec_dai->name, num);
+                       rtd->dai_link->stream_name, codec_dai->name, num);
 
-       if (codec_dai->playback.channels_min)
+       if (codec_dai->driver->playback.channels_min)
                playback = 1;
-       if (codec_dai->capture.channels_min)
+       if (codec_dai->driver->capture.channels_min)
                capture = 1;
 
-       ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
-               capture, &pcm);
+       dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
+       ret = snd_pcm_new(rtd->card->snd_card, new_name,
+                       num, playback, capture, &pcm);
        if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create pcm for codec %s\n",
-                       codec->name);
-               kfree(rtd);
+               printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
                return ret;
        }
 
-       dai_link->pcm = pcm;
+       rtd->pcm = pcm;
        pcm->private_data = rtd;
-       soc_pcm_ops.mmap = platform->pcm_ops->mmap;
-       soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
-       soc_pcm_ops.copy = platform->pcm_ops->copy;
-       soc_pcm_ops.silence = platform->pcm_ops->silence;
-       soc_pcm_ops.ack = platform->pcm_ops->ack;
-       soc_pcm_ops.page = platform->pcm_ops->page;
+       soc_pcm_ops.mmap = platform->driver->ops->mmap;
+       soc_pcm_ops.pointer = platform->driver->ops->pointer;
+       soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
+       soc_pcm_ops.copy = platform->driver->ops->copy;
+       soc_pcm_ops.silence = platform->driver->ops->silence;
+       soc_pcm_ops.ack = platform->driver->ops->ack;
+       soc_pcm_ops.page = platform->driver->ops->page;
 
        if (playback)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -1474,14 +1784,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
        if (capture)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
 
-       ret = platform->pcm_new(codec->card, codec_dai, pcm);
+       ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm);
        if (ret < 0) {
                printk(KERN_ERR "asoc: platform pcm constructor failed\n");
-               kfree(rtd);
                return ret;
        }
 
-       pcm->private_free = platform->pcm_free;
+       pcm->private_free = platform->driver->pcm_free;
        printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
                cpu_dai->name);
        return ret;
@@ -1497,8 +1806,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
  */
 int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
 {
-       if (codec->volatile_register)
-               return codec->volatile_register(reg);
+       if (codec->driver->volatile_register)
+               return codec->driver->volatile_register(reg);
        else
                return 0;
 }
@@ -1533,7 +1842,13 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
 
        codec->ac97->bus->ops = ops;
        codec->ac97->num = num;
-       codec->dev = &codec->ac97->dev;
+
+       /*
+        * Mark the AC97 device to be created by us. This way we ensure that the
+        * device will be registered with the device subsystem later on.
+        */
+       codec->ac97_created = 1;
+
        mutex_unlock(&codec->mutex);
        return 0;
 }
@@ -1548,9 +1863,13 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
 void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
 {
        mutex_lock(&codec->mutex);
+#ifdef CONFIG_SND_SOC_AC97_BUS
+       soc_unregister_ac97_dai_link(codec);
+#endif
        kfree(codec->ac97->bus);
        kfree(codec->ac97);
        codec->ac97 = NULL;
+       codec->ac97_created = 0;
        mutex_unlock(&codec->mutex);
 }
 EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
@@ -1634,95 +1953,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
 EXPORT_SYMBOL_GPL(snd_soc_test_bits);
 
 /**
- * snd_soc_new_pcms - create new sound card and pcms
- * @socdev: the SoC audio device
- * @idx: ALSA card index
- * @xid: card identification
- *
- * Create a new sound card based upon the codec and interface pcms.
- *
- * Returns 0 for success, else error.
- */
-int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
-{
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_codec *codec = card->codec;
-       int ret, i;
-
-       mutex_lock(&codec->mutex);
-
-       /* register a sound card */
-       ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card);
-       if (ret < 0) {
-               printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
-                       codec->name);
-               mutex_unlock(&codec->mutex);
-               return ret;
-       }
-
-       codec->socdev = socdev;
-       codec->card->dev = socdev->dev;
-       codec->card->private_data = codec;
-       strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
-
-       /* create the pcms */
-       for (i = 0; i < card->num_links; i++) {
-               ret = soc_new_pcm(socdev, &card->dai_link[i], i);
-               if (ret < 0) {
-                       printk(KERN_ERR "asoc: can't create pcm %s\n",
-                               card->dai_link[i].stream_name);
-                       mutex_unlock(&codec->mutex);
-                       return ret;
-               }
-               /* Check for codec->ac97 to handle the ac97.c fun */
-               if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) {
-                       snd_ac97_dev_add_pdata(codec->ac97,
-                               card->dai_link[i].cpu_dai->ac97_pdata);
-               }
-       }
-
-       mutex_unlock(&codec->mutex);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
-
-/**
- * snd_soc_free_pcms - free sound card and pcms
- * @socdev: the SoC audio device
- *
- * Frees sound card and pcms associated with the socdev.
- * Also unregister the codec if it is an AC97 device.
- */
-void snd_soc_free_pcms(struct snd_soc_device *socdev)
-{
-       struct snd_soc_codec *codec = socdev->card->codec;
-#ifdef CONFIG_SND_SOC_AC97_BUS
-       struct snd_soc_dai *codec_dai;
-       int i;
-#endif
-
-       mutex_lock(&codec->mutex);
-       soc_cleanup_codec_debugfs(codec);
-#ifdef CONFIG_SND_SOC_AC97_BUS
-       for (i = 0; i < codec->num_dai; i++) {
-               codec_dai = &codec->dai[i];
-               if (codec_dai->ac97_control && codec->ac97 &&
-                   strcmp(codec->name, "AC97") != 0) {
-                       soc_ac97_dev_unregister(codec);
-                       goto free_card;
-               }
-       }
-free_card:
-#endif
-
-       if (codec->card)
-               snd_card_free(codec->card);
-       device_remove_file(socdev->dev, &dev_attr_codec_reg);
-       mutex_unlock(&codec->mutex);
-}
-EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
-
-/**
  * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
  * @substream: the pcm substream
  * @hw: the hardware parameters
@@ -1783,15 +2013,15 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
 int snd_soc_add_controls(struct snd_soc_codec *codec,
        const struct snd_kcontrol_new *controls, int num_controls)
 {
-       struct snd_card *card = codec->card;
+       struct snd_card *card = codec->card->snd_card;
        int err, i;
 
        for (i = 0; i < num_controls; i++) {
                const struct snd_kcontrol_new *control = &controls[i];
                err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
                if (err < 0) {
-                       dev_err(codec->dev, "%s: Failed to add %s\n",
-                               codec->name, control->name);
+                       dev_err(codec->dev, "%s: Failed to add %s: %d\n",
+                               codec->name, control->name, err);
                        return err;
                }
        }
@@ -2338,7 +2568,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
 int snd_soc_limit_volume(struct snd_soc_codec *codec,
        const char *name, int max)
 {
-       struct snd_card *card = codec->card;
+       struct snd_card *card = codec->card->snd_card;
        struct snd_kcontrol *kctl;
        struct soc_mixer_control *mc;
        int found = 0;
@@ -2470,8 +2700,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
 int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
        unsigned int freq, int dir)
 {
-       if (dai->ops && dai->ops->set_sysclk)
-               return dai->ops->set_sysclk(dai, clk_id, freq, dir);
+       if (dai->driver && dai->driver->ops->set_sysclk)
+               return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
        else
                return -EINVAL;
 }
@@ -2490,8 +2720,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
 int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
        int div_id, int div)
 {
-       if (dai->ops && dai->ops->set_clkdiv)
-               return dai->ops->set_clkdiv(dai, div_id, div);
+       if (dai->driver && dai->driver->ops->set_clkdiv)
+               return dai->driver->ops->set_clkdiv(dai, div_id, div);
        else
                return -EINVAL;
 }
@@ -2510,8 +2740,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
 int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
        unsigned int freq_in, unsigned int freq_out)
 {
-       if (dai->ops && dai->ops->set_pll)
-               return dai->ops->set_pll(dai, pll_id, source,
+       if (dai->driver && dai->driver->ops->set_pll)
+               return dai->driver->ops->set_pll(dai, pll_id, source,
                                         freq_in, freq_out);
        else
                return -EINVAL;
@@ -2527,8 +2757,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
  */
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
-       if (dai->ops && dai->ops->set_fmt)
-               return dai->ops->set_fmt(dai, fmt);
+       if (dai->driver && dai->driver->ops->set_fmt)
+               return dai->driver->ops->set_fmt(dai, fmt);
        else
                return -EINVAL;
 }
@@ -2548,8 +2778,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_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)
 {
-       if (dai->ops && dai->ops->set_tdm_slot)
-               return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask,
+       if (dai->driver && dai->driver->ops->set_tdm_slot)
+               return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
                                slots, slot_width);
        else
                return -EINVAL;
@@ -2572,8 +2802,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
        unsigned int tx_num, unsigned int *tx_slot,
        unsigned int rx_num, unsigned int *rx_slot)
 {
-       if (dai->ops && dai->ops->set_channel_map)
-               return dai->ops->set_channel_map(dai, tx_num, tx_slot,
+       if (dai->driver && dai->driver->ops->set_channel_map)
+               return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
                        rx_num, rx_slot);
        else
                return -EINVAL;
@@ -2589,8 +2819,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
  */
 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
 {
-       if (dai->ops && dai->ops->set_tristate)
-               return dai->ops->set_tristate(dai, tristate);
+       if (dai->driver && dai->driver->ops->set_tristate)
+               return dai->driver->ops->set_tristate(dai, tristate);
        else
                return -EINVAL;
 }
@@ -2605,8 +2835,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
  */
 int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
 {
-       if (dai->ops && dai->ops->digital_mute)
-               return dai->ops->digital_mute(dai, mute);
+       if (dai->driver && dai->driver->ops->digital_mute)
+               return dai->driver->ops->digital_mute(dai, mute);
        else
                return -EINVAL;
 }
@@ -2623,11 +2853,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
  */
 static int snd_soc_register_card(struct snd_soc_card *card)
 {
+       int i;
+
        if (!card->name || !card->dev)
                return -EINVAL;
 
+       card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links,
+                       GFP_KERNEL);
+       if (card->rtd == NULL)
+               return -ENOMEM;
+
+       for (i = 0; i < card->num_links; i++)
+               card->rtd[i].dai_link = &card->dai_link[i];
+
        INIT_LIST_HEAD(&card->list);
        card->instantiated = 0;
+       mutex_init(&card->mutex);
 
        mutex_lock(&client_mutex);
        list_add(&card->list, &card_list);
@@ -2653,30 +2894,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
        mutex_lock(&client_mutex);
        list_del(&card->list);
        mutex_unlock(&client_mutex);
-
        dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
 
        return 0;
 }
 
+/*
+ * Simplify DAI link configuration by removing ".-1" from device names
+ * and sanitizing names.
+ */
+static inline char *fmt_single_name(struct device *dev, int *id)
+{
+       char *found, name[NAME_SIZE];
+       int id1, id2;
+
+       if (dev_name(dev) == NULL)
+               return NULL;
+
+       strncpy(name, dev_name(dev), NAME_SIZE);
+
+       /* are we a "%s.%d" name (platform and SPI components) */
+       found = strstr(name, dev->driver->name);
+       if (found) {
+               /* get ID */
+               if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) {
+
+                       /* discard ID from name if ID == -1 */
+                       if (*id == -1)
+                               found[strlen(dev->driver->name)] = '\0';
+               }
+
+       } else {
+               /* I2C component devices are named "bus-addr"  */
+               if (sscanf(name, "%x-%x", &id1, &id2) == 2) {
+                       char tmp[NAME_SIZE];
+
+                       /* create unique ID number from I2C addr and bus */
+                       *id = ((id1 & 0xffff) << 16) + id2;
+
+                       /* sanitize component name for DAI link creation */
+                       snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name);
+                       strncpy(name, tmp, NAME_SIZE);
+               } else
+                       *id = 0;
+       }
+
+       return kstrdup(name, GFP_KERNEL);
+}
+
+/*
+ * Simplify DAI link naming for single devices with multiple DAIs by removing
+ * any ".-1" and using the DAI name (instead of device name).
+ */
+static inline char *fmt_multiple_name(struct device *dev,
+               struct snd_soc_dai_driver *dai_drv)
+{
+       if (dai_drv->name == NULL) {
+               printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+                               dev_name(dev));
+               return NULL;
+       }
+
+       return kstrdup(dai_drv->name, GFP_KERNEL);
+}
+
 /**
  * snd_soc_register_dai - Register a DAI with the ASoC core
  *
  * @dai: DAI to register
  */
-int snd_soc_register_dai(struct snd_soc_dai *dai)
+int snd_soc_register_dai(struct device *dev,
+               struct snd_soc_dai_driver *dai_drv)
 {
-       if (!dai->name)
-               return -EINVAL;
+       struct snd_soc_dai *dai;
+
+       dev_dbg(dev, "dai register %s\n", dev_name(dev));
 
-       /* The device should become mandatory over time */
-       if (!dai->dev)
-               printk(KERN_WARNING "No device for DAI %s\n", dai->name);
+       dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
+       if (dai == NULL)
+                       return -ENOMEM;
 
-       if (!dai->ops)
-               dai->ops = &null_dai_ops;
+       /* create DAI component name */
+       dai->name = fmt_single_name(dev, &dai->id);
+       if (dai->name == NULL) {
+               kfree(dai);
+               return -ENOMEM;
+       }
 
-       INIT_LIST_HEAD(&dai->list);
+       dai->dev = dev;
+       dai->driver = dai_drv;
+       if (!dai->driver->ops)
+               dai->driver->ops = &null_dai_ops;
 
        mutex_lock(&client_mutex);
        list_add(&dai->list, &dai_list);
@@ -2694,13 +3002,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai);
  *
  * @dai: DAI to unregister
  */
-void snd_soc_unregister_dai(struct snd_soc_dai *dai)
+void snd_soc_unregister_dai(struct device *dev)
 {
+       struct snd_soc_dai *dai;
+
+       list_for_each_entry(dai, &dai_list, list) {
+               if (dev == dai->dev)
+                       goto found;
+       }
+       return;
+
+found:
        mutex_lock(&client_mutex);
        list_del(&dai->list);
        mutex_unlock(&client_mutex);
 
        pr_debug("Unregistered DAI '%s'\n", dai->name);
+       kfree(dai->name);
+       kfree(dai);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
 
@@ -2710,21 +3029,50 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
  * @dai: Array of DAIs to register
  * @count: Number of DAIs
  */
-int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
+int snd_soc_register_dais(struct device *dev,
+               struct snd_soc_dai_driver *dai_drv, size_t count)
 {
-       int i, ret;
+       struct snd_soc_dai *dai;
+       int i, ret = 0;
+
+       dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
 
        for (i = 0; i < count; i++) {
-               ret = snd_soc_register_dai(&dai[i]);
-               if (ret != 0)
+
+               dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
+               if (dai == NULL)
+                       return -ENOMEM;
+
+               /* create DAI component name */
+               dai->name = fmt_multiple_name(dev, &dai_drv[i]);
+               if (dai->name == NULL) {
+                       kfree(dai);
+                       ret = -EINVAL;
                        goto err;
+               }
+
+               dai->dev = dev;
+               dai->driver = &dai_drv[i];
+               if (dai->driver->id)
+                       dai->id = dai->driver->id;
+               else
+                       dai->id = i;
+               if (!dai->driver->ops)
+                       dai->driver->ops = &null_dai_ops;
+
+               mutex_lock(&client_mutex);
+               list_add(&dai->list, &dai_list);
+               mutex_unlock(&client_mutex);
+
+               pr_debug("Registered DAI '%s'\n", dai->name);
        }
 
+       snd_soc_instantiate_cards();
        return 0;
 
 err:
        for (i--; i >= 0; i--)
-               snd_soc_unregister_dai(&dai[i]);
+               snd_soc_unregister_dai(dev);
 
        return ret;
 }
@@ -2736,12 +3084,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
  * @dai: Array of DAIs to unregister
  * @count: Number of DAIs
  */
-void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
+void snd_soc_unregister_dais(struct device *dev, size_t count)
 {
        int i;
 
        for (i = 0; i < count; i++)
-               snd_soc_unregister_dai(&dai[i]);
+               snd_soc_unregister_dai(dev);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
 
@@ -2750,12 +3098,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
  *
  * @platform: platform to register
  */
-int snd_soc_register_platform(struct snd_soc_platform *platform)
+int snd_soc_register_platform(struct device *dev,
+               struct snd_soc_platform_driver *platform_drv)
 {
-       if (!platform->name)
-               return -EINVAL;
+       struct snd_soc_platform *platform;
+
+       dev_dbg(dev, "platform register %s\n", dev_name(dev));
 
-       INIT_LIST_HEAD(&platform->list);
+       platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
+       if (platform == NULL)
+                       return -ENOMEM;
+
+       /* create platform component name */
+       platform->name = fmt_single_name(dev, &platform->id);
+       if (platform->name == NULL) {
+               kfree(platform);
+               return -ENOMEM;
+       }
+
+       platform->dev = dev;
+       platform->driver = platform_drv;
 
        mutex_lock(&client_mutex);
        list_add(&platform->list, &platform_list);
@@ -2773,13 +3135,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
  *
  * @platform: platform to unregister
  */
-void snd_soc_unregister_platform(struct snd_soc_platform *platform)
+void snd_soc_unregister_platform(struct device *dev)
 {
+       struct snd_soc_platform *platform;
+
+       list_for_each_entry(platform, &platform_list, list) {
+               if (dev == platform->dev)
+                       goto found;
+       }
+       return;
+
+found:
        mutex_lock(&client_mutex);
        list_del(&platform->list);
        mutex_unlock(&client_mutex);
 
        pr_debug("Unregistered platform '%s'\n", platform->name);
+       kfree(platform->name);
+       kfree(platform);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
 
@@ -2821,22 +3194,61 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
  *
  * @codec: codec to register
  */
-int snd_soc_register_codec(struct snd_soc_codec *codec)
+int snd_soc_register_codec(struct device *dev,
+               struct snd_soc_codec_driver *codec_drv,
+               struct snd_soc_dai_driver *dai_drv, int num_dai)
 {
-       int i;
+       struct snd_soc_codec *codec;
+       int ret, i;
 
-       if (!codec->name)
-               return -EINVAL;
+       dev_dbg(dev, "codec register %s\n", dev_name(dev));
+
+       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+       if (codec == NULL)
+               return -ENOMEM;
+
+       /* create CODEC component name */
+       codec->name = fmt_single_name(dev, &codec->id);
+       if (codec->name == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
 
-       /* The device should become mandatory over time */
-       if (!codec->dev)
-               printk(KERN_WARNING "No device for codec %s\n", codec->name);
+       /* allocate CODEC register cache */
+       if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
 
-       INIT_LIST_HEAD(&codec->list);
+               if (codec_drv->reg_cache_default)
+                       codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
+                               codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL);
+               else
+                       codec->reg_cache = kzalloc(codec_drv->reg_cache_size *
+                               codec_drv->reg_word_size, GFP_KERNEL);
 
-       for (i = 0; i < codec->num_dai; i++) {
-               fixup_codec_formats(&codec->dai[i].playback);
-               fixup_codec_formats(&codec->dai[i].capture);
+               if (codec->reg_cache == NULL) {
+                       kfree(codec->name);
+                       kfree(codec);
+                       return -ENOMEM;
+               }
+       }
+
+       codec->dev = dev;
+       codec->driver = codec_drv;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->num_dai = num_dai;
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       for (i = 0; i < num_dai; i++) {
+               fixup_codec_formats(&dai_drv[i].playback);
+               fixup_codec_formats(&dai_drv[i].capture);
+       }
+
+       /* register any DAIs */
+       if (num_dai) {
+               ret = snd_soc_register_dais(dev, dai_drv, num_dai);
+               if (ret < 0)
+                       goto error;
        }
 
        mutex_lock(&client_mutex);
@@ -2845,8 +3257,17 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
        mutex_unlock(&client_mutex);
 
        pr_debug("Registered codec '%s'\n", codec->name);
-
        return 0;
+
+error:
+       for (i--; i >= 0; i--)
+               snd_soc_unregister_dai(dev);
+
+       if (codec->reg_cache)
+               kfree(codec->reg_cache);
+       kfree(codec->name);
+       kfree(codec);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_register_codec);
 
@@ -2855,13 +3276,32 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
  *
  * @codec: codec to unregister
  */
-void snd_soc_unregister_codec(struct snd_soc_codec *codec)
+void snd_soc_unregister_codec(struct device *dev)
 {
+       struct snd_soc_codec *codec;
+       int i;
+
+       list_for_each_entry(codec, &codec_list, list) {
+               if (dev == codec->dev)
+                       goto found;
+       }
+       return;
+
+found:
+       if (codec->num_dai)
+               for (i = 0; i < codec->num_dai; i++)
+                       snd_soc_unregister_dai(dev);
+
        mutex_lock(&client_mutex);
        list_del(&codec->list);
        mutex_unlock(&client_mutex);
 
        pr_debug("Unregistered codec '%s'\n", codec->name);
+
+       if (codec->reg_cache)
+               kfree(codec->reg_cache);
+       kfree(codec->name);
+       kfree(codec);
 }
 EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 
@@ -2874,10 +3314,23 @@ static int __init snd_soc_init(void)
                       "ASoC: Failed to create debugfs directory\n");
                debugfs_root = NULL;
        }
+
+       if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL,
+                                &codec_list_fops))
+               pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
+
+       if (!debugfs_create_file("dais", 0444, debugfs_root, NULL,
+                                &dai_list_fops))
+               pr_warn("ASoC: Failed to create DAI list debugfs file\n");
+
+       if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL,
+                                &platform_list_fops))
+               pr_warn("ASoC: Failed to create platform list debugfs file\n");
 #endif
 
        return platform_driver_register(&soc_driver);
 }
+module_init(snd_soc_init);
 
 static void __exit snd_soc_exit(void)
 {
@@ -2886,8 +3339,6 @@ static void __exit snd_soc_exit(void)
 #endif
        platform_driver_unregister(&soc_driver);
 }
-
-module_init(snd_soc_init);
 module_exit(snd_soc_exit);
 
 /* Module information */
index 72a53d0..7d85c64 100644 (file)
@@ -112,43 +112,41 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 
 /**
  * snd_soc_dapm_set_bias_level - set the bias level for the system
- * @socdev: audio device
+ * @card: audio device
  * @level: level to configure
  *
  * Configure the bias (power) levels for the SoC audio device.
  *
  * Returns 0 for success else error.
  */
-static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
-                                      enum snd_soc_bias_level level)
+static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card,
+               struct snd_soc_codec *codec, enum snd_soc_bias_level level)
 {
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_codec *codec = socdev->card->codec;
        int ret = 0;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
-               dev_dbg(socdev->dev, "Setting full bias\n");
+               dev_dbg(codec->dev, "Setting full bias\n");
                break;
        case SND_SOC_BIAS_PREPARE:
-               dev_dbg(socdev->dev, "Setting bias prepare\n");
+               dev_dbg(codec->dev, "Setting bias prepare\n");
                break;
        case SND_SOC_BIAS_STANDBY:
-               dev_dbg(socdev->dev, "Setting standby bias\n");
+               dev_dbg(codec->dev, "Setting standby bias\n");
                break;
        case SND_SOC_BIAS_OFF:
-               dev_dbg(socdev->dev, "Setting bias off\n");
+               dev_dbg(codec->dev, "Setting bias off\n");
                break;
        default:
-               dev_err(socdev->dev, "Setting invalid bias %d\n", level);
+               dev_err(codec->dev, "Setting invalid bias %d\n", level);
                return -EINVAL;
        }
 
-       if (card->set_bias_level)
+       if (card && 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);
+               if (codec->driver->set_bias_level)
+                       ret = codec->driver->set_bias_level(codec, level);
                else
                        codec->bias_level = level;
        }
@@ -370,7 +368,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
 
                        path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
                                path->long_name);
-                       ret = snd_ctl_add(codec->card, path->kcontrol);
+                       ret = snd_ctl_add(codec->card->snd_card, path->kcontrol);
                        if (ret < 0) {
                                printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
                                       path->long_name,
@@ -398,7 +396,7 @@ static int dapm_new_mux(struct snd_soc_codec *codec,
        }
 
        kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
-       ret = snd_ctl_add(codec->card, kcontrol);
+       ret = snd_ctl_add(codec->card->snd_card, kcontrol);
        if (ret < 0)
                goto err;
 
@@ -437,9 +435,9 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec)
  */
 static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
 {
-       struct snd_soc_codec *codec = widget->codec;
+       int level = snd_power_get_state(widget->codec->card->snd_card);
 
-       switch (snd_power_get_state(codec->card)) {
+       switch (level) {
        case SNDRV_CTL_POWER_D3hot:
        case SNDRV_CTL_POWER_D3cold:
                if (widget->ignore_suspend)
@@ -893,7 +891,7 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
  */
 static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 {
-       struct snd_soc_device *socdev = codec->socdev;
+       struct snd_soc_card *card = codec->card;
        struct snd_soc_dapm_widget *w;
        LIST_HEAD(up_list);
        LIST_HEAD(down_list);
@@ -966,7 +964,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
        }
 
        if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) {
-               ret = snd_soc_dapm_set_bias_level(socdev,
+               ret = snd_soc_dapm_set_bias_level(card, codec,
                                                  SND_SOC_BIAS_STANDBY);
                if (ret != 0)
                        pr_err("Failed to turn on bias: %d\n", ret);
@@ -975,8 +973,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
        /* 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)) {
-               ret = snd_soc_dapm_set_bias_level(socdev,
-                                                 SND_SOC_BIAS_PREPARE);
+               ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE);
                if (ret != 0)
                        pr_err("Failed to prepare bias: %d\n", ret);
        }
@@ -989,8 +986,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 
        /* If we just powered the last thing off drop to standby bias */
        if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
-               ret = snd_soc_dapm_set_bias_level(socdev,
-                                                 SND_SOC_BIAS_STANDBY);
+               ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY);
                if (ret != 0)
                        pr_err("Failed to apply standby bias: %d\n", ret);
        }
@@ -998,15 +994,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
        /* If we're in standby and can support bias off then do that */
        if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
            codec->idle_bias_off) {
-               ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
+               ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);
                if (ret != 0)
                        pr_err("Failed to turn off bias: %d\n", ret);
        }
 
        /* If we just powered up then move to active bias */
        if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
-               ret = snd_soc_dapm_set_bias_level(socdev,
-                                                 SND_SOC_BIAS_ON);
+               ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON);
                if (ret != 0)
                        pr_err("Failed to apply active bias: %d\n", ret);
        }
@@ -1189,8 +1184,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
 static ssize_t dapm_widget_show(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
-       struct snd_soc_device *devdata = dev_get_drvdata(dev);
-       struct snd_soc_codec *codec = devdata->card->codec;
+       struct snd_soc_pcm_runtime *rtd =
+                       container_of(dev, struct snd_soc_pcm_runtime, dev);
+       struct snd_soc_codec *codec =rtd->codec;
        struct snd_soc_dapm_widget *w;
        int count = 0;
        char *state = "not set";
@@ -1999,9 +1995,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
  *
  * Returns 0 for success else error.
  */
-int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
-       char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
+       const char *stream, int event)
 {
+       struct snd_soc_codec *codec = rtd->codec;
        struct snd_soc_dapm_widget *w;
 
        if (stream == NULL)
@@ -2169,25 +2166,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
 
 /**
  * snd_soc_dapm_free - free dapm resources
- * @socdev: SoC device
+ * @card: SoC device
  *
  * Free all dapm widgets and resources.
  */
-void snd_soc_dapm_free(struct snd_soc_device *socdev)
+void snd_soc_dapm_free(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       snd_soc_dapm_sys_remove(socdev->dev);
+       snd_soc_dapm_sys_remove(codec->dev);
        dapm_free_widgets(codec);
 }
 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)
+static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
        struct snd_soc_dapm_widget *w;
        LIST_HEAD(down_list);
        int powerdown = 0;
@@ -2204,12 +2195,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
         * standby.
         */
        if (powerdown) {
-               snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE);
+               snd_soc_dapm_set_bias_level(NULL, codec, 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(NULL, codec, SND_SOC_BIAS_STANDBY);
        }
+}
+
+/*
+ * snd_soc_dapm_shutdown - callback for system shutdown
+ */
+void snd_soc_dapm_shutdown(struct snd_soc_card *card)
+{
+       struct snd_soc_codec *codec;
+
+       list_for_each_entry(codec, &card->codec_dev_list, list)
+               soc_dapm_shutdown_codec(codec);
 
-       snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
+       snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);
 }
 
 /* Module information */
index 29159e1..8a0a920 100644 (file)
  * Returns zero if successful, or a negative error code on failure.
  * On success jack will be initialised.
  */
-int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
+int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
                     struct snd_soc_jack *jack)
 {
-       jack->card = card;
+       jack->codec = codec;
        INIT_LIST_HEAD(&jack->pins);
        BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
 
-       return snd_jack_new(card->codec->card, id, type, &jack->jack);
+       return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
 }
 EXPORT_SYMBOL_GPL(snd_soc_jack_new);
 
@@ -67,7 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        if (!jack)
                return;
 
-       codec = jack->card->codec;
+       codec = jack->codec;
 
        mutex_lock(&codec->mutex);
 
@@ -188,9 +188,6 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
        int enable;
        int report;
 
-       if (gpio->debounce_time > 0)
-               mdelay(gpio->debounce_time);
-
        enable = gpio_get_value(gpio->gpio);
        if (gpio->invert)
                enable = !enable;
@@ -211,7 +208,8 @@ static irqreturn_t gpio_handler(int irq, void *data)
 {
        struct snd_soc_jack_gpio *gpio = data;
 
-       schedule_work(&gpio->work);
+       schedule_delayed_work(&gpio->work,
+                             msecs_to_jiffies(gpio->debounce_time));
 
        return IRQ_HANDLED;
 }
@@ -221,7 +219,7 @@ static void gpio_work(struct work_struct *work)
 {
        struct snd_soc_jack_gpio *gpio;
 
-       gpio = container_of(work, struct snd_soc_jack_gpio, work);
+       gpio = container_of(work, struct snd_soc_jack_gpio, work.work);
        snd_soc_jack_gpio_detect(gpio);
 }
 
@@ -262,13 +260,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                if (ret)
                        goto err;
 
-               INIT_WORK(&gpios[i].work, gpio_work);
+               INIT_DELAYED_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,
-                               jack->card->dev->driver->name,
+                               jack->codec->dev->driver->name,
                                &gpios[i]);
                if (ret)
                        goto err;
@@ -312,6 +310,7 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
                gpio_unexport(gpios[i].gpio);
 #endif
                free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
+               cancel_delayed_work_sync(&gpios[i].work);
                gpio_free(gpios[i].gpio);
                gpios[i].jack = NULL;
        }
index 0ec20b6..743d07b 100644 (file)
 
 static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
 
-/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */
-static struct txx9aclc_soc_device *txx9aclc_soc_dev;
+/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
+static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
 
-static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
+static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
 {
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
-
        return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
 }
 
@@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
 static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
                                         unsigned short reg)
 {
-       struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
        void __iomem *base = drvdata->base;
        u32 dat;
 
@@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
        dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
        __raw_writel(dat, base + ACREGACC);
        __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
-       if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
+       if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
                __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
-               dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg);
+               printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
                dat = 0xffff;
                goto done;
        }
        dat = __raw_readl(base + ACREGACC);
        if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
-               dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n",
+               printk(KERN_ERR "reg mismatch %x with %x\n",
                        dat, reg);
                dat = 0xffff;
                goto done;
@@ -84,16 +81,15 @@ done:
 static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
                                unsigned short val)
 {
-       struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
        void __iomem *base = drvdata->base;
 
        __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
                     (val << ACREGACC_DAT_SHIFT),
                     base + ACREGACC);
        __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
-       if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) {
-               dev_err(dev->soc_dev.dev,
+       if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
+               printk(KERN_ERR
                        "ac97 write timeout (reg %#x)\n", reg);
        }
        __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
@@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 
 static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
 {
-       struct txx9aclc_soc_device *dev = txx9aclc_soc_dev;
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
        void __iomem *base = drvdata->base;
        u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
 
@@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int txx9aclc_ac97_probe(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct txx9aclc_soc_device *dev =
-               container_of(socdev, struct txx9aclc_soc_device, soc_dev);
-
-       dev->aclc_pdev = to_platform_device(dai->dev);
-       txx9aclc_soc_dev = dev;
+       txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
        return 0;
 }
 
-static void txx9aclc_ac97_remove(struct platform_device *pdev,
-                                struct snd_soc_dai *dai)
+static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
 {
-       struct platform_device *aclc_pdev = to_platform_device(dai->dev);
-       struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev);
+       struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);
 
        /* disable AC-link */
        __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
-       txx9aclc_soc_dev = NULL;
+       txx9aclc_drvdata = NULL;
+       return 0;
 }
 
-struct snd_soc_dai txx9aclc_ac97_dai = {
-       .name                   = "txx9aclc_ac97",
+static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
        .ac97_control           = 1,
        .probe                  = txx9aclc_ac97_probe,
        .remove                 = txx9aclc_ac97_remove,
@@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = {
                .channels_max   = 2,
        },
 };
-EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);
 
 static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
 {
@@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
-       txx9aclc_ac97_dai.dev = &pdev->dev;
-       return snd_soc_register_dai(&txx9aclc_ac97_dai);
+       return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
 }
 
 static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_dai(&txx9aclc_ac97_dai);
+       snd_soc_unregister_dai(&pdev->dev);
        return 0;
 }
 
index 95b17f7..6770e71 100644 (file)
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
-#include "../codecs/ac97.h"
 #include "txx9aclc.h"
 
 static struct snd_soc_dai_link txx9aclc_generic_dai = {
        .name = "AC97",
        .stream_name = "AC97 HiFi",
-       .cpu_dai = &txx9aclc_ac97_dai,
-       .codec_dai = &ac97_dai,
+       .cpu_dai_name = "txx9aclc-ac97",
+       .codec_dai_name = "ac97-hifi",
+       .platform_name  = "txx9aclc-pcm-audio",
+       .codec_name     = "ac97-codec",
 };
 
 static struct snd_soc_card txx9aclc_generic_card = {
        .name           = "Generic TXx9 ACLC Audio",
-       .platform       = &txx9aclc_soc_platform,
        .dai_link       = &txx9aclc_generic_dai,
        .num_links      = 1,
 };
 
-static struct txx9aclc_soc_device txx9aclc_generic_soc_device = {
-       .soc_dev = {
-               .card           = &txx9aclc_generic_card,
-               .codec_dev      = &soc_codec_dev_ac97,
-       },
-};
+static struct platform_device *soc_pdev;
 
 static int __init txx9aclc_generic_probe(struct platform_device *pdev)
 {
-       struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device;
-       struct platform_device *soc_pdev;
        int ret;
 
        soc_pdev = platform_device_alloc("soc-audio", -1);
        if (!soc_pdev)
                return -ENOMEM;
-       platform_set_drvdata(soc_pdev, &dev->soc_dev);
-       dev->soc_dev.dev = &soc_pdev->dev;
+       platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);
        ret = platform_device_add(soc_pdev);
        if (ret) {
                platform_device_put(soc_pdev);
                return ret;
        }
-       platform_set_drvdata(pdev, soc_pdev);
+
        return 0;
 }
 
 static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
 {
-       struct platform_device *soc_pdev = platform_get_drvdata(pdev);
-
        platform_device_unregister(soc_pdev);
        return 0;
 }
index 0e34523..f4aa4e0 100644 (file)
 #include <sound/soc.h>
 #include "txx9aclc.h"
 
+static struct txx9aclc_soc_device {
+       struct txx9aclc_dmadata dmadata[2];
+} txx9aclc_soc_device;
+
+/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
+static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
+
+static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
+                            struct txx9aclc_dmadata *dmadata);
+
 static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
        /*
         * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
@@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct snd_soc_device *socdev = rtd->socdev;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct txx9aclc_dmadata *dmadata = runtime->private_data;
        int ret;
@@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       dev_dbg(socdev->dev,
+       dev_dbg(rtd->platform->dev,
                "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
                "runtime->min_align %ld\n",
                (unsigned long)runtime->dma_area,
                (unsigned long)runtime->dma_addr, runtime->dma_bytes,
                runtime->min_align);
-       dev_dbg(socdev->dev,
+       dev_dbg(rtd->platform->dev,
                "periods %d period_bytes %d stream %d\n",
                params_periods(params), params_period_bytes(params),
                substream->stream);
@@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
 
        spin_lock_irqsave(&dmadata->dma_lock, flags);
        if (dmadata->frag_count < 0) {
-               struct txx9aclc_soc_device *dev =
-                       container_of(dmadata, struct txx9aclc_soc_device,
-                                    dmadata[substream->stream]);
-               struct txx9aclc_plat_drvdata *drvdata =
-                       txx9aclc_get_plat_drvdata(dev);
+               struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
                void __iomem *base = drvdata->base;
 
                spin_unlock_irqrestore(&dmadata->dma_lock, flags);
@@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
 static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct txx9aclc_soc_device *dev =
-               container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
        void __iomem *base = drvdata->base;
        unsigned long flags;
        int ret = 0;
@@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream)
 
 static int txx9aclc_pcm_open(struct snd_pcm_substream *substream)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct txx9aclc_soc_device *dev =
-               container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
+       struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;
        struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
        int ret;
 
@@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
 static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
                            struct snd_pcm *pcm)
 {
+       struct platform_device *pdev = to_platform_device(dai->platform->dev);
+       struct txx9aclc_soc_device *dev;
+       struct resource *r;
+       int i;
+       int ret;
+
+       /* at this point onwards the AC97 component has probed and this will be valid */
+       dev = snd_soc_dai_get_drvdata(dai);
+
+       dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
+       dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
+       for (i = 0; i < 2; i++) {
+               r = platform_get_resource(pdev, IORESOURCE_DMA, i);
+               if (!r) {
+                       ret = -EBUSY;
+                       goto exit;
+               }
+               dev->dmadata[i].dma_res = r;
+               ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
+               if (ret)
+                       goto exit;
+       }
        return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                card->dev, 64 * 1024, 4 * 1024 * 1024);
+
+exit:
+       for (i = 0; i < 2; i++) {
+               if (dev->dmadata[i].dma_chan)
+                       dma_release_channel(dev->dmadata[i].dma_chan);
+               dev->dmadata[i].dma_chan = NULL;
+       }
+       return ret;
 }
 
 static bool filter(struct dma_chan *chan, void *param)
@@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param)
 static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
                             struct txx9aclc_dmadata *dmadata)
 {
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
        struct txx9dmac_slave *ds = &dmadata->dma_slave;
        dma_cap_mask_t mask;
 
@@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
        dma_cap_set(DMA_SLAVE, mask);
        dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
        if (!dmadata->dma_chan) {
-               dev_err(dev->soc_dev.dev,
+               printk(KERN_ERR
                        "DMA channel for %s is not available\n",
                        dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
                        "playback" : "capture");
@@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
        return 0;
 }
 
-static int txx9aclc_pcm_probe(struct platform_device *pdev)
+static int txx9aclc_pcm_probe(struct snd_soc_platform *platform)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct txx9aclc_soc_device *dev =
-               container_of(socdev, struct txx9aclc_soc_device, soc_dev);
-       struct resource *r;
-       int i;
-       int ret;
-
-       dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
-       dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
-       for (i = 0; i < 2; i++) {
-               r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i);
-               if (!r) {
-                       ret = -EBUSY;
-                       goto exit;
-               }
-               dev->dmadata[i].dma_res = r;
-               ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
-               if (ret)
-                       goto exit;
-       }
+       snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device);
        return 0;
-
-exit:
-       for (i = 0; i < 2; i++) {
-               if (dev->dmadata[i].dma_chan)
-                       dma_release_channel(dev->dmadata[i].dma_chan);
-               dev->dmadata[i].dma_chan = NULL;
-       }
-       return ret;
 }
 
-static int txx9aclc_pcm_remove(struct platform_device *pdev)
+static int txx9aclc_pcm_remove(struct snd_soc_platform *platform)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct txx9aclc_soc_device *dev =
-               container_of(socdev, struct txx9aclc_soc_device, soc_dev);
-       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
+       struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform);
+       struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
        void __iomem *base = drvdata->base;
        int i;
 
@@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev)
        return 0;
 }
 
-struct snd_soc_platform txx9aclc_soc_platform = {
-       .name           = "txx9aclc-audio",
+static struct snd_soc_platform_driver txx9aclc_soc_platform = {
        .probe          = txx9aclc_pcm_probe,
        .remove         = txx9aclc_pcm_remove,
-       .pcm_ops        = &txx9aclc_pcm_ops,
+       .ops            = &txx9aclc_pcm_ops,
        .pcm_new        = txx9aclc_pcm_new,
        .pcm_free       = txx9aclc_pcm_free_dma_buffers,
 };
-EXPORT_SYMBOL_GPL(txx9aclc_soc_platform);
 
-static int __init txx9aclc_soc_platform_init(void)
+static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
 {
-       return snd_soc_register_platform(&txx9aclc_soc_platform);
+       return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
 }
 
-static void __exit txx9aclc_soc_platform_exit(void)
+static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
 {
-       snd_soc_unregister_platform(&txx9aclc_soc_platform);
+       snd_soc_unregister_platform(&pdev->dev);
+       return 0;
 }
 
-module_init(txx9aclc_soc_platform_init);
-module_exit(txx9aclc_soc_platform_exit);
+static struct platform_driver txx9aclc_pcm_driver = {
+       .driver = {
+                       .name = "txx9aclc-pcm-audio",
+                       .owner = THIS_MODULE,
+       },
+
+       .probe = txx9aclc_soc_platform_probe,
+       .remove = __devexit_p(txx9aclc_soc_platform_remove),
+};
+
+static int __init snd_txx9aclc_pcm_init(void)
+{
+       return platform_driver_register(&txx9aclc_pcm_driver);
+}
+module_init(snd_txx9aclc_pcm_init);
+
+static void __exit snd_txx9aclc_pcm_exit(void)
+{
+       platform_driver_unregister(&txx9aclc_pcm_driver);
+}
+module_exit(snd_txx9aclc_pcm_exit);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
 MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
index 6769aab..9c2de84 100644 (file)
@@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata {
        u64 physbase;
 };
 
-struct txx9aclc_soc_device {
-       struct snd_soc_device soc_dev;
-       struct platform_device *aclc_pdev;      /* for ioresources, drvdata */
-       struct txx9aclc_dmadata dmadata[2];
-};
-
 static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
-       struct txx9aclc_soc_device *sdev)
+       struct snd_soc_dai *dai)
 {
-       return platform_get_drvdata(sdev->aclc_pdev);
+       return dev_get_drvdata(dai->dev);
 }
 
-extern struct snd_soc_platform txx9aclc_soc_platform;
-extern struct snd_soc_dai txx9aclc_ac97_dai;
-
 #endif /* __TXX9ACLC_H */
index ff0b2a8..5ae1eae 100644 (file)
@@ -128,6 +128,9 @@ snd_emux_init_hwdep(struct snd_emux *emu)
        strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
        hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
        hw->ops.ioctl = snd_emux_hwdep_ioctl;
+       /* The ioctl parameter types are compatible between 32- and
+        * 64-bit architectures, so use the same function. */
+       hw->ops.ioctl_compat = snd_emux_hwdep_ioctl;
        hw->exclusive = 1;
        hw->private_data = emu;
        if ((err = snd_card_register(emu->card)) < 0)
index 44d6d2e..112984f 100644 (file)
@@ -65,6 +65,7 @@ config SND_USB_CAIAQ
            * Native Instruments Guitar Rig Session I/O
            * Native Instruments Guitar Rig mobile
            * Native Instruments Traktor Kontrol X1
+           * Native Instruments Traktor Kontrol S4
 
           To compile this driver as a module, choose M here: the module
           will be called snd-usb-caiaq.
@@ -82,6 +83,7 @@ config SND_USB_CAIAQ_INPUT
           * Native Instruments Kore Controller
           * Native Instruments Kore Controller 2
           * Native Instruments Audio Kontrol 1
+          * Native Instruments Traktor Kontrol S4
 
 config SND_USB_US122L
        tristate "Tascam US-122L USB driver"
index 4328cad..68b9747 100644 (file)
@@ -111,7 +111,7 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
        memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
        dev->input_panic = 0;
        dev->output_panic = 0;
-       dev->first_packet = 1;
+       dev->first_packet = 4;
        dev->streaming = 1;
        dev->warned = 0;
 
@@ -169,7 +169,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
 }
 
 static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
-                                       struct snd_pcm_hw_params *hw_params)
+                                      struct snd_pcm_hw_params *hw_params)
 {
        debug("%s(%p)\n", __func__, sub);
        return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
@@ -189,7 +189,7 @@ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 #endif
 
 static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
-                                 48000, 64000, 88200, 96000, 176400, 192000 };
+                               48000, 64000, 88200, 96000, 176400, 192000 };
 
 static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
 {
@@ -201,12 +201,39 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
        debug("%s(%p)\n", __func__, substream);
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               dev->period_out_count[index] = BYTES_PER_SAMPLE + 1;
-               dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
+               int out_pos;
+
+               switch (dev->spec.data_alignment) {
+               case 0:
+               case 2:
+                       out_pos = BYTES_PER_SAMPLE + 1;
+                       break;
+               case 3:
+               default:
+                       out_pos = 0;
+                       break;
+               }
+
+               dev->period_out_count[index] = out_pos;
+               dev->audio_out_buf_pos[index] = out_pos;
        } else {
-               int in_pos = (dev->spec.data_alignment == 2) ? 0 : 2;
-               dev->period_in_count[index] = BYTES_PER_SAMPLE + in_pos;
-               dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE + in_pos;
+               int in_pos;
+
+               switch (dev->spec.data_alignment) {
+               case 0:
+                       in_pos = BYTES_PER_SAMPLE + 2;
+                       break;
+               case 2:
+                       in_pos = BYTES_PER_SAMPLE;
+                       break;
+               case 3:
+               default:
+                       in_pos = 0;
+                       break;
+               }
+
+               dev->period_in_count[index] = in_pos;
+               dev->audio_in_buf_pos[index] = in_pos;
        }
 
        if (dev->streaming)
@@ -221,7 +248,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
        snd_pcm_limit_hw_rates(runtime);
 
        bytes_per_sample = BYTES_PER_SAMPLE;
-       if (dev->spec.data_alignment == 2)
+       if (dev->spec.data_alignment >= 2)
                bytes_per_sample++;
 
        bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
@@ -253,6 +280,8 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
 {
        struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
 
+       debug("%s(%p) cmd %d\n", __func__, sub, cmd);
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -402,6 +431,61 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
        }
 }
 
+static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
+                             const struct urb *urb,
+                             const struct usb_iso_packet_descriptor *iso)
+{
+       unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+       int stream, i;
+
+       /* paranoia check */
+       if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM))
+               return;
+
+       for (i = 0; i < iso->actual_length;) {
+               for (stream = 0; stream < dev->n_streams; stream++) {
+                       struct snd_pcm_substream *sub = dev->sub_capture[stream];
+                       char *audio_buf = NULL;
+                       int c, n, sz = 0;
+
+                       if (sub && !dev->input_panic) {
+                               struct snd_pcm_runtime *rt = sub->runtime;
+                               audio_buf = rt->dma_area;
+                               sz = frames_to_bytes(rt, rt->buffer_size);
+                       }
+
+                       for (c = 0; c < CHANNELS_PER_STREAM; c++) {
+                               /* 3 audio data bytes, followed by 1 check byte */
+                               if (audio_buf) {
+                                       for (n = 0; n < BYTES_PER_SAMPLE; n++) {
+                                               audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n];
+
+                                               if (dev->audio_in_buf_pos[stream] == sz)
+                                                       dev->audio_in_buf_pos[stream] = 0;
+                                       }
+
+                                       dev->period_in_count[stream] += BYTES_PER_SAMPLE;
+                               }
+
+                               i += BYTES_PER_SAMPLE;
+
+                               if (usb_buf[i] != ((stream << 1) | c) &&
+                                   !dev->first_packet) {
+                                       if (!dev->input_panic)
+                                               printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
+                                                       ((stream << 1) | c), usb_buf[i], c, stream, i);
+                                       dev->input_panic = 1;
+                               }
+
+                               i++;
+                       }
+               }
+       }
+
+       if (dev->first_packet > 0)
+               dev->first_packet--;
+}
+
 static void read_in_urb(struct snd_usb_caiaqdev *dev,
                        const struct urb *urb,
                        const struct usb_iso_packet_descriptor *iso)
@@ -419,6 +503,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
        case 2:
                read_in_urb_mode2(dev, urb, iso);
                break;
+       case 3:
+               read_in_urb_mode3(dev, urb, iso);
+               break;
        }
 
        if ((dev->input_panic || dev->output_panic) && !dev->warned) {
@@ -429,9 +516,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
        }
 }
 
-static void fill_out_urb(struct snd_usb_caiaqdev *dev,
-                        struct urb *urb,
-                        const struct usb_iso_packet_descriptor *iso)
+static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev,
+                               struct urb *urb,
+                               const struct usb_iso_packet_descriptor *iso)
 {
        unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
        struct snd_pcm_substream *sub;
@@ -457,9 +544,67 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
                /* fill in the check bytes */
                if (dev->spec.data_alignment == 2 &&
                    i % (dev->n_streams * BYTES_PER_SAMPLE_USB) ==
-                       (dev->n_streams * CHANNELS_PER_STREAM))
-                   for (stream = 0; stream < dev->n_streams; stream++, i++)
-                       usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+                       (dev->n_streams * CHANNELS_PER_STREAM))
+                       for (stream = 0; stream < dev->n_streams; stream++, i++)
+                               usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+       }
+}
+
+static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
+                               struct urb *urb,
+                               const struct usb_iso_packet_descriptor *iso)
+{
+       unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+       int stream, i;
+
+       for (i = 0; i < iso->length;) {
+               for (stream = 0; stream < dev->n_streams; stream++) {
+                       struct snd_pcm_substream *sub = dev->sub_playback[stream];
+                       char *audio_buf = NULL;
+                       int c, n, sz = 0;
+
+                       if (sub) {
+                               struct snd_pcm_runtime *rt = sub->runtime;
+                               audio_buf = rt->dma_area;
+                               sz = frames_to_bytes(rt, rt->buffer_size);
+                       }
+
+                       for (c = 0; c < CHANNELS_PER_STREAM; c++) {
+                               for (n = 0; n < BYTES_PER_SAMPLE; n++) {
+                                       if (audio_buf) {
+                                               usb_buf[i+n] = audio_buf[dev->audio_out_buf_pos[stream]++];
+
+                                               if (dev->audio_out_buf_pos[stream] == sz)
+                                                       dev->audio_out_buf_pos[stream] = 0;
+                                       } else {
+                                               usb_buf[i+n] = 0;
+                                       }
+                               }
+
+                               if (audio_buf)
+                                       dev->period_out_count[stream] += BYTES_PER_SAMPLE;
+
+                               i += BYTES_PER_SAMPLE;
+
+                               /* fill in the check byte pattern */
+                               usb_buf[i++] = (stream << 1) | c;
+                       }
+               }
+       }
+}
+
+static inline void fill_out_urb(struct snd_usb_caiaqdev *dev,
+                               struct urb *urb,
+                               const struct usb_iso_packet_descriptor *iso)
+{
+       switch (dev->spec.data_alignment) {
+       case 0:
+       case 2:
+               fill_out_urb_mode_0(dev, urb, iso);
+               break;
+       case 3:
+               fill_out_urb_mode_3(dev, urb, iso);
+               break;
        }
 }
 
index 91c804c..00e5d0a 100644 (file)
@@ -55,6 +55,10 @@ static int control_info(struct snd_kcontrol *kcontrol,
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
                maxval = 127;
                break;
+
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+               maxval = 31;
+               break;
        }
 
        if (is_intval) {
@@ -93,6 +97,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
        struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
        struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
        int pos = kcontrol->private_value;
+       int v = ucontrol->value.integer.value[0];
        unsigned char cmd = EP1_CMD_WRITE_IO;
 
        if (dev->chip.usb_id ==
@@ -100,12 +105,27 @@ static int control_put(struct snd_kcontrol *kcontrol,
                cmd = EP1_CMD_DIMM_LEDS;
 
        if (pos & CNT_INTVAL) {
-               dev->control_state[pos & ~CNT_INTVAL]
-                       = ucontrol->value.integer.value[0];
-               snd_usb_caiaq_send_command(dev, cmd,
-                               dev->control_state, sizeof(dev->control_state));
+               int i = pos & ~CNT_INTVAL;
+
+               dev->control_state[i] = v;
+
+               if (dev->chip.usb_id ==
+                       USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4)) {
+                       int actual_len;
+
+                       dev->ep8_out_buf[0] = i;
+                       dev->ep8_out_buf[1] = v;
+
+                       usb_bulk_msg(dev->chip.dev,
+                                    usb_sndbulkpipe(dev->chip.dev, 8),
+                                    dev->ep8_out_buf, sizeof(dev->ep8_out_buf),
+                                    &actual_len, 200);
+               } else {
+                       snd_usb_caiaq_send_command(dev, cmd,
+                                       dev->control_state, sizeof(dev->control_state));
+               }
        } else {
-               if (ucontrol->value.integer.value[0])
+               if (v)
                        dev->control_state[pos / 8] |= 1 << (pos % 8);
                else
                        dev->control_state[pos / 8] &= ~(1 << (pos % 8));
@@ -296,6 +316,179 @@ static struct caiaq_controller kontrolx1_controller[] = {
        { "LED Deck B: SYNC",           8  | CNT_INTVAL },
 };
 
+static struct caiaq_controller kontrols4_controller[] = {
+       { "LED: Master: Quant",                 10  | CNT_INTVAL },
+       { "LED: Master: Headphone",             11  | CNT_INTVAL },
+       { "LED: Master: Master",                12  | CNT_INTVAL },
+       { "LED: Master: Snap",                  14  | CNT_INTVAL },
+       { "LED: Master: Warning",               15  | CNT_INTVAL },
+       { "LED: Master: Master button",         112 | CNT_INTVAL },
+       { "LED: Master: Snap button",           113 | CNT_INTVAL },
+       { "LED: Master: Rec",                   118 | CNT_INTVAL },
+       { "LED: Master: Size",                  119 | CNT_INTVAL },
+       { "LED: Master: Quant button",          120 | CNT_INTVAL },
+       { "LED: Master: Browser button",        121 | CNT_INTVAL },
+       { "LED: Master: Play button",           126 | CNT_INTVAL },
+       { "LED: Master: Undo button",           127 | CNT_INTVAL },
+
+       { "LED: Channel A: >",                  4   | CNT_INTVAL },
+       { "LED: Channel A: <",                  5   | CNT_INTVAL },
+       { "LED: Channel A: Meter 1",            97  | CNT_INTVAL },
+       { "LED: Channel A: Meter 2",            98  | CNT_INTVAL },
+       { "LED: Channel A: Meter 3",            99  | CNT_INTVAL },
+       { "LED: Channel A: Meter 4",            100 | CNT_INTVAL },
+       { "LED: Channel A: Meter 5",            101 | CNT_INTVAL },
+       { "LED: Channel A: Meter 6",            102 | CNT_INTVAL },
+       { "LED: Channel A: Meter clip",         103 | CNT_INTVAL },
+       { "LED: Channel A: Active",             114 | CNT_INTVAL },
+       { "LED: Channel A: Cue",                116 | CNT_INTVAL },
+       { "LED: Channel A: FX1",                149 | CNT_INTVAL },
+       { "LED: Channel A: FX2",                148 | CNT_INTVAL },
+
+       { "LED: Channel B: >",                  2   | CNT_INTVAL },
+       { "LED: Channel B: <",                  3   | CNT_INTVAL },
+       { "LED: Channel B: Meter 1",            89  | CNT_INTVAL },
+       { "LED: Channel B: Meter 2",            90  | CNT_INTVAL },
+       { "LED: Channel B: Meter 3",            91  | CNT_INTVAL },
+       { "LED: Channel B: Meter 4",            92  | CNT_INTVAL },
+       { "LED: Channel B: Meter 5",            93  | CNT_INTVAL },
+       { "LED: Channel B: Meter 6",            94  | CNT_INTVAL },
+       { "LED: Channel B: Meter clip",         95  | CNT_INTVAL },
+       { "LED: Channel B: Active",             122 | CNT_INTVAL },
+       { "LED: Channel B: Cue",                125 | CNT_INTVAL },
+       { "LED: Channel B: FX1",                147 | CNT_INTVAL },
+       { "LED: Channel B: FX2",                146 | CNT_INTVAL },
+
+       { "LED: Channel C: >",                  6   | CNT_INTVAL },
+       { "LED: Channel C: <",                  7   | CNT_INTVAL },
+       { "LED: Channel C: Meter 1",            105 | CNT_INTVAL },
+       { "LED: Channel C: Meter 2",            106 | CNT_INTVAL },
+       { "LED: Channel C: Meter 3",            107 | CNT_INTVAL },
+       { "LED: Channel C: Meter 4",            108 | CNT_INTVAL },
+       { "LED: Channel C: Meter 5",            109 | CNT_INTVAL },
+       { "LED: Channel C: Meter 6",            110 | CNT_INTVAL },
+       { "LED: Channel C: Meter clip",         111 | CNT_INTVAL },
+       { "LED: Channel C: Active",             115 | CNT_INTVAL },
+       { "LED: Channel C: Cue",                117 | CNT_INTVAL },
+       { "LED: Channel C: FX1",                151 | CNT_INTVAL },
+       { "LED: Channel C: FX2",                150 | CNT_INTVAL },
+
+       { "LED: Channel D: >",                  0   | CNT_INTVAL },
+       { "LED: Channel D: <",                  1   | CNT_INTVAL },
+       { "LED: Channel D: Meter 1",            81  | CNT_INTVAL },
+       { "LED: Channel D: Meter 2",            82  | CNT_INTVAL },
+       { "LED: Channel D: Meter 3",            83  | CNT_INTVAL },
+       { "LED: Channel D: Meter 4",            84  | CNT_INTVAL },
+       { "LED: Channel D: Meter 5",            85  | CNT_INTVAL },
+       { "LED: Channel D: Meter 6",            86  | CNT_INTVAL },
+       { "LED: Channel D: Meter clip",         87  | CNT_INTVAL },
+       { "LED: Channel D: Active",             123 | CNT_INTVAL },
+       { "LED: Channel D: Cue",                124 | CNT_INTVAL },
+       { "LED: Channel D: FX1",                145 | CNT_INTVAL },
+       { "LED: Channel D: FX2",                144 | CNT_INTVAL },
+
+       { "LED: Deck A: 1 (blue)",              22  | CNT_INTVAL },
+       { "LED: Deck A: 1 (green)",             23  | CNT_INTVAL },
+       { "LED: Deck A: 2 (blue)",              20  | CNT_INTVAL },
+       { "LED: Deck A: 2 (green)",             21  | CNT_INTVAL },
+       { "LED: Deck A: 3 (blue)",              18  | CNT_INTVAL },
+       { "LED: Deck A: 3 (green)",             19  | CNT_INTVAL },
+       { "LED: Deck A: 4 (blue)",              16  | CNT_INTVAL },
+       { "LED: Deck A: 4 (green)",             17  | CNT_INTVAL },
+       { "LED: Deck A: Load",                  44  | CNT_INTVAL },
+       { "LED: Deck A: Deck C button",         45  | CNT_INTVAL },
+       { "LED: Deck A: In",                    47  | CNT_INTVAL },
+       { "LED: Deck A: Out",                   46  | CNT_INTVAL },
+       { "LED: Deck A: Shift",                 24  | CNT_INTVAL },
+       { "LED: Deck A: Sync",                  27  | CNT_INTVAL },
+       { "LED: Deck A: Cue",                   26  | CNT_INTVAL },
+       { "LED: Deck A: Play",                  25  | CNT_INTVAL },
+       { "LED: Deck A: Tempo up",              33  | CNT_INTVAL },
+       { "LED: Deck A: Tempo down",            32  | CNT_INTVAL },
+       { "LED: Deck A: Master",                34  | CNT_INTVAL },
+       { "LED: Deck A: Keylock",               35  | CNT_INTVAL },
+       { "LED: Deck A: Deck A",                37  | CNT_INTVAL },
+       { "LED: Deck A: Deck C",                36  | CNT_INTVAL },
+       { "LED: Deck A: Samples",               38  | CNT_INTVAL },
+       { "LED: Deck A: On Air",                39  | CNT_INTVAL },
+       { "LED: Deck A: Sample 1",              31  | CNT_INTVAL },
+       { "LED: Deck A: Sample 2",              30  | CNT_INTVAL },
+       { "LED: Deck A: Sample 3",              29  | CNT_INTVAL },
+       { "LED: Deck A: Sample 4",              28  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - A",           55  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - B",           54  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - C",           53  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - D",           52  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - E",           51  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - F",           50  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - G",           49  | CNT_INTVAL },
+       { "LED: Deck A: Digit 1 - dot",         48  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - A",           63  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - B",           62  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - C",           61  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - D",           60  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - E",           59  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - F",           58  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - G",           57  | CNT_INTVAL },
+       { "LED: Deck A: Digit 2 - dot",         56  | CNT_INTVAL },
+
+       { "LED: Deck B: 1 (blue)",              78  | CNT_INTVAL },
+       { "LED: Deck B: 1 (green)",             79  | CNT_INTVAL },
+       { "LED: Deck B: 2 (blue)",              76  | CNT_INTVAL },
+       { "LED: Deck B: 2 (green)",             77  | CNT_INTVAL },
+       { "LED: Deck B: 3 (blue)",              74  | CNT_INTVAL },
+       { "LED: Deck B: 3 (green)",             75  | CNT_INTVAL },
+       { "LED: Deck B: 4 (blue)",              72  | CNT_INTVAL },
+       { "LED: Deck B: 4 (green)",             73  | CNT_INTVAL },
+       { "LED: Deck B: Load",                  180 | CNT_INTVAL },
+       { "LED: Deck B: Deck D button",         181 | CNT_INTVAL },
+       { "LED: Deck B: In",                    183 | CNT_INTVAL },
+       { "LED: Deck B: Out",                   182 | CNT_INTVAL },
+       { "LED: Deck B: Shift",                 64  | CNT_INTVAL },
+       { "LED: Deck B: Sync",                  67  | CNT_INTVAL },
+       { "LED: Deck B: Cue",                   66  | CNT_INTVAL },
+       { "LED: Deck B: Play",                  65  | CNT_INTVAL },
+       { "LED: Deck B: Tempo up",              185 | CNT_INTVAL },
+       { "LED: Deck B: Tempo down",            184 | CNT_INTVAL },
+       { "LED: Deck B: Master",                186 | CNT_INTVAL },
+       { "LED: Deck B: Keylock",               187 | CNT_INTVAL },
+       { "LED: Deck B: Deck B",                189 | CNT_INTVAL },
+       { "LED: Deck B: Deck D",                188 | CNT_INTVAL },
+       { "LED: Deck B: Samples",               190 | CNT_INTVAL },
+       { "LED: Deck B: On Air",                191 | CNT_INTVAL },
+       { "LED: Deck B: Sample 1",              71  | CNT_INTVAL },
+       { "LED: Deck B: Sample 2",              70  | CNT_INTVAL },
+       { "LED: Deck B: Sample 3",              69  | CNT_INTVAL },
+       { "LED: Deck B: Sample 4",              68  | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - A",           175 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - B",           174 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - C",           173 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - D",           172 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - E",           171 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - F",           170 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - G",           169 | CNT_INTVAL },
+       { "LED: Deck B: Digit 1 - dot",         168 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - A",           167 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - B",           166 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - C",           165 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - D",           164 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - E",           163 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - F",           162 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - G",           161 | CNT_INTVAL },
+       { "LED: Deck B: Digit 2 - dot",         160 | CNT_INTVAL },
+
+       { "LED: FX1: dry/wet",                  153 | CNT_INTVAL },
+       { "LED: FX1: 1",                        154 | CNT_INTVAL },
+       { "LED: FX1: 2",                        155 | CNT_INTVAL },
+       { "LED: FX1: 3",                        156 | CNT_INTVAL },
+       { "LED: FX1: Mode",                     157 | CNT_INTVAL },
+       { "LED: FX2: dry/wet",                  129 | CNT_INTVAL },
+       { "LED: FX2: 1",                        130 | CNT_INTVAL },
+       { "LED: FX2: 2",                        131 | CNT_INTVAL },
+       { "LED: FX2: 3",                        132 | CNT_INTVAL },
+       { "LED: FX2: Mode",                     133 | CNT_INTVAL },
+};
+
 static int __devinit add_controls(struct caiaq_controller *c, int num,
                                  struct snd_usb_caiaqdev *dev)
 {
@@ -354,6 +547,11 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
                ret = add_controls(kontrolx1_controller,
                        ARRAY_SIZE(kontrolx1_controller), dev);
                break;
+
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+               ret = add_controls(kontrols4_controller,
+                       ARRAY_SIZE(kontrols4_controller), dev);
+               break;
        }
 
        return ret;
index cdfb856..6480c32 100644 (file)
@@ -36,7 +36,7 @@
 #include "input.h"
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.21");
+MODULE_DESCRIPTION("caiaq USB audio");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
@@ -48,7 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, Audio 8 DJ},"
                         "{Native Instruments, Session I/O},"
                         "{Native Instruments, GuitarRig mobile}"
-                        "{Native Instruments, Traktor Kontrol X1}");
+                        "{Native Instruments, Traktor Kontrol X1}"
+                        "{Native Instruments, Traktor Kontrol S4}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
 static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -134,6 +135,11 @@ static struct usb_device_id snd_usb_id_table[] = {
                .idVendor =     USB_VID_NATIVEINSTRUMENTS,
                .idProduct =    USB_PID_TRAKTORKONTROLX1
        },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     USB_VID_NATIVEINSTRUMENTS,
+               .idProduct =    USB_PID_TRAKTORKONTROLS4
+       },
        { /* terminator */ }
 };
 
index f1117ec..e3d8a3e 100644 (file)
@@ -16,6 +16,7 @@
 #define USB_PID_SESSIONIO              0x1915
 #define USB_PID_GUITARRIGMOBILE                0x0d8d
 #define USB_PID_TRAKTORKONTROLX1       0x2305
+#define USB_PID_TRAKTORKONTROLS4       0xbaff
 
 #define EP1_BUFSIZE 64
 #define EP4_BUFSIZE 512
@@ -99,13 +100,14 @@ struct snd_usb_caiaqdev {
        struct snd_pcm_substream *sub_capture[MAX_STREAMS];
 
        /* Controls */
-       unsigned char control_state[64];
+       unsigned char control_state[256];
+       unsigned char ep8_out_buf[2];
 
        /* Linux input */
 #ifdef CONFIG_SND_USB_CAIAQ_INPUT
        struct input_dev *input_dev;
        char phys[64];                  /* physical device path */
-       unsigned short keycode[64];
+       unsigned short keycode[128];
        struct urb *ep4_in_urb;
        unsigned char ep4_in_buf[EP4_BUFSIZE];
 #endif
index dcb6207..4432ef7 100644 (file)
@@ -67,7 +67,12 @@ static unsigned short keycode_kore[] = {
        KEY_BRL_DOT5
 };
 
-#define KONTROLX1_INPUTS 40
+#define KONTROLX1_INPUTS       (40)
+#define KONTROLS4_BUTTONS      (12 * 8)
+#define KONTROLS4_AXIS         (46)
+
+#define KONTROLS4_BUTTON(X)    ((X) + BTN_MISC)
+#define KONTROLS4_ABS(X)       ((X) + ABS_HAT0X)
 
 #define DEG90          (range / 2)
 #define DEG180         (range)
@@ -139,6 +144,13 @@ static unsigned int decode_erp(unsigned char a, unsigned char b)
 #undef HIGH_PEAK
 #undef LOW_PEAK
 
+static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *dev,
+                                             int axis, const unsigned char *buf,
+                                             int offset)
+{
+       input_report_abs(dev->input_dev, axis,
+                        (buf[offset * 2] << 8) | buf[offset * 2 + 1]);
+}
 
 static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
                                        const unsigned char *buf,
@@ -148,36 +160,30 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
 
        switch (dev->chip.usb_id) {
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
-               input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]);
-               input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]);
-               input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]);
-               input_sync(input_dev);
+               snd_caiaq_input_report_abs(dev, ABS_X, buf, 2);
+               snd_caiaq_input_report_abs(dev, ABS_Y, buf, 0);
+               snd_caiaq_input_report_abs(dev, ABS_Z, buf, 1);
                break;
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
-               input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
-               input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
-               input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
-               input_sync(input_dev);
-               break;
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
-               input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
-               input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
-               input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
-               input_sync(input_dev);
+               snd_caiaq_input_report_abs(dev, ABS_X, buf, 0);
+               snd_caiaq_input_report_abs(dev, ABS_Y, buf, 1);
+               snd_caiaq_input_report_abs(dev, ABS_Z, buf, 2);
                break;
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
-               input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8)  | buf[9]);
-               input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8)  | buf[5]);
-               input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
-               input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8)  | buf[3]);
-               input_report_abs(input_dev, ABS_HAT2X, (buf[14] << 8) | buf[15]);
-               input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8)  | buf[1]);
-               input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
-               input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8)  | buf[7]);
-               input_sync(input_dev);
+               snd_caiaq_input_report_abs(dev, ABS_HAT0X, buf, 4);
+               snd_caiaq_input_report_abs(dev, ABS_HAT0Y, buf, 2);
+               snd_caiaq_input_report_abs(dev, ABS_HAT1X, buf, 6);
+               snd_caiaq_input_report_abs(dev, ABS_HAT1Y, buf, 1);
+               snd_caiaq_input_report_abs(dev, ABS_HAT2X, buf, 7);
+               snd_caiaq_input_report_abs(dev, ABS_HAT2Y, buf, 0);
+               snd_caiaq_input_report_abs(dev, ABS_HAT3X, buf, 5);
+               snd_caiaq_input_report_abs(dev, ABS_HAT3Y, buf, 3);
                break;
        }
+
+       input_sync(input_dev);
 }
 
 static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
@@ -250,6 +256,150 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
        input_sync(input_dev);
 }
 
+#define TKS4_MSGBLOCK_SIZE     16
+
+static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
+                                       const unsigned char *buf,
+                                       unsigned int len)
+{
+       while (len) {
+               unsigned int i, block_id = (buf[0] << 8) | buf[1];
+
+               switch (block_id) {
+               case 0:
+                       /* buttons */
+                       for (i = 0; i < KONTROLS4_BUTTONS; i++)
+                               input_report_key(dev->input_dev, KONTROLS4_BUTTON(i),
+                                                (buf[4 + (i / 8)] >> (i % 8)) & 1);
+                       break;
+
+               case 1:
+                       /* left wheel */
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8));
+                       /* right wheel */
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8));
+
+                       /* rotary encoders */
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4);
+                       input_report_abs(dev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf);
+
+                       break;
+               case 2:
+                       /* Volume Fader Channel D */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(0), buf, 1);
+                       /* Volume Fader Channel B */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(1), buf, 2);
+                       /* Volume Fader Channel A */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(2), buf, 3);
+                       /* Volume Fader Channel C */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(3), buf, 4);
+                       /* Loop Volume */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(4), buf, 6);
+                       /* Crossfader */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(7), buf, 7);
+
+                       break;
+
+               case 3:
+                       /* Tempo Fader R */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(6), buf, 3);
+                       /* Tempo Fader L */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(5), buf, 4);
+                       /* Mic Volume */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(8), buf, 6);
+                       /* Cue Mix */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(9), buf, 7);
+
+                       break;
+
+               case 4:
+                       /* Wheel distance sensor L */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(10), buf, 1);
+                       /* Wheel distance sensor R */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(11), buf, 2);
+                       /* Channel D EQ - Filter */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(12), buf, 3);
+                       /* Channel D EQ - Low */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(13), buf, 4);
+                       /* Channel D EQ - Mid */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(14), buf, 5);
+                       /* Channel D EQ - Hi */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(15), buf, 6);
+                       /* FX2 - dry/wet */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(16), buf, 7);
+
+                       break;
+
+               case 5:
+                       /* FX2 - 1 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(17), buf, 1);
+                       /* FX2 - 2 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(18), buf, 2);
+                       /* FX2 - 3 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(19), buf, 3);
+                       /* Channel B EQ - Filter */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(20), buf, 4);
+                       /* Channel B EQ - Low */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(21), buf, 5);
+                       /* Channel B EQ - Mid */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(22), buf, 6);
+                       /* Channel B EQ - Hi */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(23), buf, 7);
+
+                       break;
+
+               case 6:
+                       /* Channel A EQ - Filter */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(24), buf, 1);
+                       /* Channel A EQ - Low */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(25), buf, 2);
+                       /* Channel A EQ - Mid */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(26), buf, 3);
+                       /* Channel A EQ - Hi */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(27), buf, 4);
+                       /* Channel C EQ - Filter */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(28), buf, 5);
+                       /* Channel C EQ - Low */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(29), buf, 6);
+                       /* Channel C EQ - Mid */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(30), buf, 7);
+
+                       break;
+
+               case 7:
+                       /* Channel C EQ - Hi */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(31), buf, 1);
+                       /* FX1 - wet/dry */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(32), buf, 2);
+                       /* FX1 - 1 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(33), buf, 3);
+                       /* FX1 - 2 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(34), buf, 4);
+                       /* FX1 - 3 */
+                       snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(35), buf, 5);
+
+                       break;
+
+               default:
+                       debug("%s(): bogus block (id %d)\n",
+                               __func__, block_id);
+                       return;
+               }
+
+               len -= TKS4_MSGBLOCK_SIZE;
+               buf += TKS4_MSGBLOCK_SIZE;
+       }
+
+       input_sync(dev->input_dev);
+}
+
 static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
 {
        struct snd_usb_caiaqdev *dev = urb->context;
@@ -259,11 +409,11 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
        if (urb->status || !dev || urb != dev->ep4_in_urb)
                return;
 
-       if (urb->actual_length < 24)
-               goto requeue;
-
        switch (dev->chip.usb_id) {
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
+               if (urb->actual_length < 24)
+                       goto requeue;
+
                if (buf[0] & 0x3)
                        snd_caiaq_input_read_io(dev, buf + 1, 7);
 
@@ -271,6 +421,10 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
                        snd_caiaq_input_read_analog(dev, buf + 8, 16);
 
                break;
+
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+               snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
+               break;
        }
 
 requeue:
@@ -289,6 +443,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
 
        switch (dev->chip.usb_id) {
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
                if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
                        return -EIO;
                break;
@@ -306,6 +461,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
 
        switch (dev->chip.usb_id) {
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
                usb_kill_urb(dev->ep4_in_urb);
                break;
        }
@@ -456,6 +612,46 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
                snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
 
                break;
+
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+               input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+               BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLS4_BUTTONS);
+               for (i = 0; i < KONTROLS4_BUTTONS; i++)
+                       dev->keycode[i] = KONTROLS4_BUTTON(i);
+               input->keycodemax = KONTROLS4_BUTTONS;
+
+               for (i = 0; i < KONTROLS4_AXIS; i++) {
+                       int axis = KONTROLS4_ABS(i);
+                       input->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
+               }
+
+               /* 36 analog potentiometers and faders */
+               for (i = 0; i < 36; i++)
+                       input_set_abs_params(input, KONTROLS4_ABS(i), 0, 0xfff, 0, 10);
+
+               /* 2 encoder wheels */
+               input_set_abs_params(input, KONTROLS4_ABS(36), 0, 0x3ff, 0, 1);
+               input_set_abs_params(input, KONTROLS4_ABS(37), 0, 0x3ff, 0, 1);
+
+               /* 9 rotary encoders */
+               for (i = 0; i < 9; i++)
+                       input_set_abs_params(input, KONTROLS4_ABS(38+i), 0, 0xf, 0, 1);
+
+               dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->ep4_in_urb) {
+                       ret = -ENOMEM;
+                       goto exit_free_idev;
+               }
+
+               usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+                                 usb_rcvbulkpipe(usb_dev, 0x4),
+                                 dev->ep4_in_buf, EP4_BUFSIZE,
+                                 snd_usb_caiaq_ep4_reply_dispatch, dev);
+
+               snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+
+               break;
+
        default:
                /* no input methods supported on this device */
                goto exit_free_idev;
index 4eabafa..800f7cb 100644 (file)
@@ -300,9 +300,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 
        *rchip = NULL;
 
-       if (snd_usb_get_speed(dev) != USB_SPEED_LOW &&
-           snd_usb_get_speed(dev) != USB_SPEED_FULL &&
-           snd_usb_get_speed(dev) != USB_SPEED_HIGH) {
+       switch (snd_usb_get_speed(dev)) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+       case USB_SPEED_HIGH:
+       case USB_SPEED_SUPER:
+               break;
+       default:
                snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
                return -ENXIO;
        }
@@ -378,11 +382,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        if (len < sizeof(card->longname))
                usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
 
-       strlcat(card->longname,
-               snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" :
-               snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" :
-               ", high speed",
-               sizeof(card->longname));
+       switch (snd_usb_get_speed(dev)) {
+       case USB_SPEED_LOW:
+               strlcat(card->longname, ", low speed", sizeof(card->longname));
+               break;
+       case USB_SPEED_FULL:
+               strlcat(card->longname, ", full speed", sizeof(card->longname));
+               break;
+       case USB_SPEED_HIGH:
+               strlcat(card->longname, ", high speed", sizeof(card->longname));
+               break;
+       case USB_SPEED_SUPER:
+               strlcat(card->longname, ", super speed", sizeof(card->longname));
+               break;
+       default:
+               break;
+       }
 
        snd_usb_audio_create_proc(chip);
 
index ef0a07e..b0ef9f5 100644 (file)
@@ -405,8 +405,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        break;
                case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
                case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
-               case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8 */
-               case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
                        /* doesn't set the sample rate attribute, but supports it */
                        fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
                        break;
index d48d6f8..f280c19 100644 (file)
@@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
                                         struct usb_host_interface *alts)
 {
-       if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH &&
-           get_endpoint(alts, 0)->bInterval >= 1 &&
-           get_endpoint(alts, 0)->bInterval <= 4)
-               return get_endpoint(alts, 0)->bInterval - 1;
-       else
-               return 0;
+       switch (snd_usb_get_speed(chip->dev)) {
+       case USB_SPEED_HIGH:
+       case USB_SPEED_SUPER:
+               if (get_endpoint(alts, 0)->bInterval >= 1 &&
+                   get_endpoint(alts, 0)->bInterval <= 4)
+                       return get_endpoint(alts, 0)->bInterval - 1;
+               break;
+       default:
+               break;
+       }
+       return 0;
 }
 
index b9c2bc6..25bce7e 100644 (file)
@@ -784,7 +784,7 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
 };
 
 /*
- * "raw" protocol: used by the MOTU FastLane.
+ * "raw" protocol: just move raw MIDI bytes from/to the endpoint
  */
 
 static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
 
        if (!ep->ports[0].active)
                return;
-       count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2;
+       switch (snd_usb_get_speed(ep->umidi->dev)) {
+       case USB_SPEED_HIGH:
+       case USB_SPEED_SUPER:
+               count = 1;
+               break;
+       default:
+               count = 2;
+       }
        count = snd_rawmidi_transmit(ep->ports[0].substream,
                                     urb->transfer_buffer,
                                     count);
@@ -2115,7 +2122,7 @@ int snd_usbmidi_create(struct snd_card *card,
                umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
                err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
                break;
-       case QUIRK_MIDI_FASTLANE:
+       case QUIRK_MIDI_RAW_BYTES:
                umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
                /*
                 * Interface 1 contains isochronous endpoints, but with the same
@@ -2126,7 +2133,8 @@ int snd_usbmidi_create(struct snd_card *card,
                 * interface 0, so we have to make sure that the USB core looks
                 * again at interface 0 by calling usb_set_interface() on it.
                 */
-               usb_set_interface(umidi->dev, 0, 0);
+               if (umidi->usb_id == USB_ID(0x07fd, 0x0001)) /* MOTU Fastlane */
+                       usb_set_interface(umidi->dev, 0, 0);
                err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
                break;
        case QUIRK_MIDI_EMAGIC:
index 3ed3901..f2d74d6 100644 (file)
@@ -759,8 +759,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  */
 static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 {
-       struct snd_usb_audio *chip = cval->mixer->chip;
-
        /* for failsafe */
        cval->min = default_min;
        cval->max = cval->min + 1;
@@ -783,7 +781,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
                if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
                    get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
                        snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
-                                  cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id);
+                                  cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id);
                        return -EINVAL;
                }
                if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -1642,9 +1640,10 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        uinfo->count = 1;
        uinfo->value.enumerated.items = cval->max;
-       if ((int)uinfo->value.enumerated.item >= cval->max)
+       if (uinfo->value.enumerated.item >= cval->max)
                uinfo->value.enumerated.item = cval->max - 1;
-       strcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item]);
+       strlcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item],
+               sizeof(uinfo->value.enumerated.name));
        return 0;
 }
 
index e7df1e5..7dae05d 100644 (file)
@@ -60,6 +60,7 @@ static const struct rc_config {
        { USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
        { USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
        { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
+       { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi */
        { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
 };
 
index 3b5135c..f49756c 100644 (file)
@@ -466,7 +466,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* check whether the period time is >= the data packet interval */
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) {
+       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
                ptime = 125 * (1 << fp->datainterval);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
@@ -734,7 +734,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
        }
 
        param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH)
+       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
                /* full speed devices have fixed data packet interval */
                ptmin = 1000;
        if (ptmin == 1000)
index f5e3f35..3c650ab 100644 (file)
@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
-               if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
+               if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
                        snd_iprintf(buffer, "    Data packet interval: %d us\n",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
index 2e8003f..ad7079d 100644 (file)
@@ -240,9 +240,21 @@ YAMAHA_DEVICE(0x104f, NULL),
 YAMAHA_DEVICE(0x1050, NULL),
 YAMAHA_DEVICE(0x1051, NULL),
 YAMAHA_DEVICE(0x1052, NULL),
+YAMAHA_INTERFACE(0x1053, 0, NULL),
+YAMAHA_INTERFACE(0x1054, 0, NULL),
+YAMAHA_DEVICE(0x1055, NULL),
+YAMAHA_DEVICE(0x1056, NULL),
+YAMAHA_DEVICE(0x1057, NULL),
+YAMAHA_DEVICE(0x1058, NULL),
+YAMAHA_DEVICE(0x1059, NULL),
+YAMAHA_DEVICE(0x105a, NULL),
+YAMAHA_DEVICE(0x105b, NULL),
+YAMAHA_DEVICE(0x105c, NULL),
+YAMAHA_DEVICE(0x105d, NULL),
 YAMAHA_DEVICE(0x2000, "DGP-7"),
 YAMAHA_DEVICE(0x2001, "DGP-5"),
 YAMAHA_DEVICE(0x2002, NULL),
+YAMAHA_DEVICE(0x2003, NULL),
 YAMAHA_DEVICE(0x5000, "CS1D"),
 YAMAHA_DEVICE(0x5001, "DSP1D"),
 YAMAHA_DEVICE(0x5002, "DME32"),
@@ -1136,11 +1148,34 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
+       /* has ID 0x0066 when not in "Advanced Driver" mode */
+       USB_DEVICE(0x0582, 0x0064),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "PCR-1", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+{
        /* has ID 0x0067 when not in "Advanced Driver" mode */
        USB_DEVICE(0x0582, 0x0065),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-               .vendor_name = "EDIROL",
-               .product_name = "PCR-1",
+               /* .vendor_name = "EDIROL", */
+               /* .product_name = "PCR-1", */
                .ifnum = 0,
                .type = QUIRK_MIDI_FIXED_ENDPOINT,
                .data = & (const struct snd_usb_midi_endpoint_info) {
@@ -1525,6 +1560,50 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                }
        }
 },
+{
+       /* has ID 0x0110 when not in Advanced Driver mode */
+       USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "Roland", */
+               /* .product_name = "A-PRO", */
+               .ifnum = 1,
+               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+               .data = & (const struct snd_usb_midi_endpoint_info) {
+                       .out_cables = 0x0003,
+                       .in_cables  = 0x0007
+               }
+       }
+},
+{
+       USB_DEVICE(0x0582, 0x0113),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "BOSS", */
+               /* .product_name = "ME-25", */
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 1,
+                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                       },
+                       {
+                               .ifnum = 2,
+                               .type = QUIRK_MIDI_FIXED_ENDPOINT,
+                               .data = & (const struct snd_usb_midi_endpoint_info) {
+                                       .out_cables = 0x0001,
+                                       .in_cables  = 0x0001
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 /* Guillemot devices */
 {
@@ -1830,7 +1909,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        USB_DEVICE(0x0763, 0x2080),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
                /* .vendor_name = "M-Audio", */
-               /* .product_name = "Fast Track Ultra 8", */
+               /* .product_name = "Fast Track Ultra", */
                .ifnum = QUIRK_ANY_INTERFACE,
                .type = QUIRK_COMPOSITE,
                .data = & (const struct snd_usb_audio_quirk[]) {
@@ -1840,11 +1919,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                        },
                        {
                                .ifnum = 1,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = & (const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = 0x09,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000, 88200, 96000
+                                       }
+                               }
                        },
                        {
                                .ifnum = 2,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = & (const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x81,
+                                       .ep_attr = 0x05,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000, 88200, 96000
+                                       }
+                               }
                        },
                        /* interface 3 (MIDI) is standard compliant */
                        {
@@ -1867,11 +1986,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                        },
                        {
                                .ifnum = 1,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = & (const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 1,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x01,
+                                       .ep_attr = 0x09,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                                       44100, 48000, 88200, 96000
+                                       }
+                               }
                        },
                        {
                                .ifnum = 2,
-                               .type = QUIRK_AUDIO_STANDARD_INTERFACE
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = & (const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 2,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+                                       .endpoint = 0x81,
+                                       .ep_attr = 0x05,
+                                       .rates = SNDRV_PCM_RATE_44100 |
+                                                SNDRV_PCM_RATE_48000 |
+                                                SNDRV_PCM_RATE_88200 |
+                                                SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 4,
+                                       .rate_table = (unsigned int[]) {
+                                               44100, 48000, 88200, 96000
+                                       }
+                               }
                        },
                        /* interface 3 (MIDI) is standard compliant */
                        {
@@ -1919,7 +2078,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
                .data = & (const struct snd_usb_audio_quirk[]) {
                        {
                                .ifnum = 0,
-                               .type = QUIRK_MIDI_FASTLANE
+                               .type = QUIRK_MIDI_RAW_BYTES
                        },
                        {
                                .ifnum = 1,
@@ -2068,6 +2227,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
        }
 },
 {
+       USB_DEVICE(0x1235, 0x000e),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               /* .vendor_name = "Novation", */
+               /* .product_name = "Launchpad", */
+               .ifnum = 0,
+               .type = QUIRK_MIDI_RAW_BYTES
+       }
+},
+{
        USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
        .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
                .vendor_name = "Novation",
index 9a9da09..cf8bf08 100644 (file)
@@ -287,7 +287,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
                [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
                [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
-               [QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
+               [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
                [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
                [QUIRK_MIDI_CME] = create_any_midi_quirk,
                [QUIRK_MIDI_AKAI] = create_any_midi_quirk,
index de607d4..8deeaad 100644 (file)
@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
        else
                subs->curpacksize = maxsize;
 
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
+       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
                packs_per_ms = 8 >> subs->datainterval;
        else
                packs_per_ms = 1;
index 24d3319..db3eb21 100644 (file)
@@ -70,7 +70,7 @@ enum quirk_type {
        QUIRK_MIDI_YAMAHA,
        QUIRK_MIDI_MIDIMAN,
        QUIRK_MIDI_NOVATION,
-       QUIRK_MIDI_FASTLANE,
+       QUIRK_MIDI_RAW_BYTES,
        QUIRK_MIDI_EMAGIC,
        QUIRK_MIDI_CME,
        QUIRK_MIDI_AKAI,
index 2a528e5..287ef73 100644 (file)
@@ -36,9 +36,9 @@
          plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the
          cost of easier triggered i.e. aeolus xruns (128 or 256frames,
          2periods works but is useless cause of crackling).
+
  This is a first "proof of concept" implementation.
- Later, funcionalities should migrate to more apropriate places:
+ Later, functionalities should migrate to more apropriate places:
  Userland:
  - The jackd could mmap its float-pcm buffers directly from alsa-lib.
  - alsa-lib could provide power of 2 period sized shaping combined with int/float
@@ -54,7 +54,7 @@
 #include <linux/gfp.h>
 #include "usbusx2yaudio.c"
 
-#if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) &&  USX2Y_NRPACKS == 1)
+#if defined(USX2Y_NRPACKS_VARIABLE) || USX2Y_NRPACKS == 1
 
 #include <sound/hwdep.h>